Integer collectionIndex = 0;
Boolean collectionIsSet = value instanceof Set<?>;
Boolean topLevel = collectionPath.equals( DBNames.QNAME_TABLE_COLLECTION_PATH_TOP_LEVEL_NAME );
String collTable = TABLE_NAME_PREFIX + currentTableIndex;
String collCol = DBNames.QNAME_TABLE_COLLECTION_PATH_COLUMN_NAME;
ColumnReferenceByName collColExp = c.colName( collTable, collCol );
BooleanBuilder collectionCondition = b.booleanBuilder();
if( topLevel && negationActive )
{
afterWhere
.and( b
.booleanBuilder(
b.neq( collColExp,
l.s( DBNames.QNAME_TABLE_COLLECTION_PATH_TOP_LEVEL_NAME ) ) )
.or( b.isNull( collColExp ) ).createExpression() );
}
Integer totalItemsProcessed = 0;
for( Object item : (Collection<?>) value )
{
String path = collectionPath + DBNames.QNAME_TABLE_COLLECTION_PATH_SEPARATOR
+ ( collectionIsSet ? "*{1,}" : collectionIndex );
Boolean isCollection = ( item instanceof Collection<?> );
BooleanBuilder newWhere = b.booleanBuilder();
if( !isCollection )
{
newWhere.reset( b.regexp( collColExp, l.s( path ) ) );
}
totalItemsProcessed
= totalItemsProcessed
+ modifyFromClauseAndWhereClauseToGetValue( qName, item, predicate,
negationActive,
currentTableIndex, maxTableIndex, columnName, path, vendor,
newWhere, afterWhere, fromClause,
groupBy, having, qNameJoins, variables, values, valueSQLTypes );
++collectionIndex;
collectionCondition.or( newWhere.createExpression() );
}
result = totalItemsProcessed;
if( topLevel )
{
if( totalItemsProcessed == 0 )
{
collectionCondition.and( b.isNotNull( collColExp ) )
.and(
b.eq( collColExp,
l.l( DBNames.QNAME_TABLE_COLLECTION_PATH_TOP_LEVEL_NAME ) ) );
}
else if( !negationActive )
{
groupBy.addGroupingElements( q.groupingElement( c.colName( TABLE_NAME_PREFIX
+ currentTableIndex,
DBNames.ENTITY_TABLE_PK_COLUMN_NAME ) ) );
having
.and( b.eq(
l.func( SQLFunctions.COUNT,
c.colName( TABLE_NAME_PREFIX + currentTableIndex,
DBNames.QNAME_TABLE_VALUE_COLUMN_NAME ) ),
l.n( totalItemsProcessed ) ) );
}
}
whereClause.and( collectionCondition.createExpression() );
}
else if( value instanceof ValueComposite )
{
// Visit all properties with recursion and make joins as necessary
// @formatter:off
for( Property<?> property
: Qi4j.FUNCTION_COMPOSITE_INSTANCE_OF.map( (ValueComposite) value ).state().properties() )
{
Boolean qNameJoinDone = false;
Integer sourceIndex = maxTableIndex.getInt();
Integer targetIndex = sourceIndex + 1;
for( QNameJoin join : qNameJoins )
{
if( join.getSourceQName().equals( qName ) )
{
sourceIndex = join.getSourceTableIndex();
if( join.getTargetQName().equals( spi.propertyDescriptorFor( property ).qualifiedName() ) )
{
// This join has already been done once
qNameJoinDone = true;
targetIndex = join.getTargetTableIndex();
break;
}
}
}
if( !qNameJoinDone )
{
// @formatter:off
QNameInfo info = _state.qNameInfos().get().get( spi.propertyDescriptorFor( property ).qualifiedName() );
String prevTableName = TABLE_NAME_PREFIX + sourceIndex;
String nextTableName = TABLE_NAME_PREFIX + targetIndex;
fromClause.addQualifiedJoin(
JoinType.LEFT_OUTER,
t.table( t.tableName( schemaName, info.getTableName() ), t.tableAlias( TABLE_NAME_PREFIX + targetIndex ) ),
t.jc(
b.booleanBuilder( b.eq(
c.colName( prevTableName, DBNames.ALL_QNAMES_TABLE_PK_COLUMN_NAME ),
c.colName( nextTableName, DBNames.QNAME_TABLE_PARENT_QNAME_COLUMN_NAME )
) )
.and( b.eq(
c.colName( prevTableName, DBNames.ENTITY_TABLE_PK_COLUMN_NAME ),
c.colName( nextTableName, DBNames.ENTITY_TABLE_PK_COLUMN_NAME )
) ).createExpression()
)
);
// @formatter:on
qNameJoins.add( new QNameJoin( qName, spi.propertyDescriptorFor( property )
.qualifiedName(), sourceIndex, targetIndex ) );
maxTableIndex.setInt( maxTableIndex.getInt() + 1 );
}
modifyFromClauseAndWhereClauseToGetValue( spi.propertyDescriptorFor( property )
.qualifiedName(), property.get(), predicate, negationActive,
targetIndex, maxTableIndex, columnName, collectionPath, vendor, whereClause,
afterWhere,
fromClause, groupBy, having, qNameJoins, variables, values, valueSQLTypes );
}
// @formatter:on
}
else
{
// Primitive
ColumnReferenceByName valueCol = c.colName( TABLE_NAME_PREFIX + currentTableIndex, columnName );
if( value == null )
{
whereClause.and( b.isNull( valueCol ) );
}
else