Java Code Examples for org.hibernate.type.Type#isCollectionType()

The following examples show how to use org.hibernate.type.Type#isCollectionType() . These examples are extracted from open source projects. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
public void end(QueryTranslatorImpl q) throws QueryException {
	ignoreInitialJoin = false;

	Type propertyType = getPropertyType();
	if ( propertyType != null && propertyType.isCollectionType() ) {
		collectionRole = ( ( CollectionType ) propertyType ).getRole();
		collectionName = q.createNameForCollection( collectionRole );
		prepareForIndex( q );
	}
	else {
		columns = currentColumns();
		setType();
	}

	//important!!
	continuation = false;

}
 
Example 2
private FromElement createCollectionJoin(JoinSequence collectionJoinSequence, String tableAlias)
			throws SemanticException {
		String text = queryableCollection.getTableName();
		AST ast = createFromElement( text );
		FromElement destination = (FromElement) ast;
		Type elementType = queryableCollection.getElementType();
		if ( elementType.isCollectionType() ) {
			throw new SemanticException( "Collections of collections are not supported!" );
		}
		destination.initializeCollection( fromClause, classAlias, tableAlias );
		destination.setType( JOIN_FRAGMENT );        // Tag this node as a JOIN.
		destination.setIncludeSubclasses( false );    // Don't include subclasses in the join.
		destination.setCollectionJoin( true );        // This is a clollection join.
		destination.setJoinSequence( collectionJoinSequence );
		destination.setOrigin( origin, false );
		destination.setCollectionTableAlias( tableAlias );
//		origin.addDestination( destination );
// This was the cause of HHH-242
//		origin.setType( FROM_FRAGMENT );			// Set the parent node type so that the AST is properly formed.
		origin.setText( "" );                        // The destination node will have all the FROM text.
		origin.setCollectionJoin( true );            // The parent node is a collection join too (voodoo - see JoinProcessor)
		fromClause.addCollectionJoinFromElementByPath( path, destination );
		fromClause.getWalker().addQuerySpaces( queryableCollection.getCollectionSpaces() );
		return destination;
	}
 
Example 3
private static NonIdentifierAttributeNature decode(Type type) {
	if ( type.isAssociationType() ) {
		AssociationType associationType = (AssociationType) type;

		if ( type.isComponentType() ) {
			// an any type is both an association and a composite...
			return NonIdentifierAttributeNature.ANY;
		}

		return type.isCollectionType()
				? NonIdentifierAttributeNature.COLLECTION
				: NonIdentifierAttributeNature.ENTITY;
	}
	else {
		if ( type.isComponentType() ) {
			return NonIdentifierAttributeNature.COMPOSITE;
		}

		return NonIdentifierAttributeNature.BASIC;
	}
}
 
Example 4
protected QueryableCollection getQueryableCollection(String entityName, String propertyName, SessionFactoryImplementor factory)
        throws HibernateException {
	PropertyMapping ownerMapping = ( PropertyMapping ) factory.getEntityPersister( entityName );
	Type type = ownerMapping.toType( propertyName );
	if ( !type.isCollectionType() ) {
		throw new MappingException(
		        "Property path [" + entityName + "." + propertyName + "] does not reference a collection"
		);
	}

	String role = ( ( CollectionType ) type ).getRole();
	try {
		return ( QueryableCollection ) factory.getCollectionPersister( role );
	}
	catch ( ClassCastException cce ) {
		throw new QueryException( "collection role is not queryable: " + role );
	}
	catch ( Exception e ) {
		throw new QueryException( "collection role not found: " + role );
	}
}
 
Example 5
Source Project: lams   File: TwoPhaseLoad.java    License: GNU General Public License v2.0 6 votes vote down vote up
/**
 * Check if eager of the association is overriden by anything.
 *
 * @param session session
 * @param entityName entity name
 * @param associationName association name
 *
 * @return null if there is no overriding, true if it is overridden to eager and false if it is overridden to lazy
 */
private static Boolean getOverridingEager(
		SharedSessionContractImplementor session,
		String entityName,
		String associationName,
		Type type) {
	if ( type.isAssociationType() || type.isCollectionType() ) {
		Boolean overridingEager = isEagerFetchProfile( session, entityName + "." + associationName );

		if ( LOG.isDebugEnabled() ) {
			if ( overridingEager != null ) {
				LOG.debugf(
						"Overriding eager fetching using active fetch profile. EntityName: %s, associationName: %s, eager fetching: %s",
						entityName,
						associationName,
						overridingEager
				);
			}
		}

		return overridingEager;
	}
	return null;
}
 
Example 6
private void evictCachedCollections(Type[] types, Serializable id, EventSource source)
		throws HibernateException {
	for ( Type type : types ) {
		if ( type.isCollectionType() ) {
			CollectionPersister collectionPersister = source.getFactory().getMetamodel().collectionPersister( ( (CollectionType) type ).getRole() );
			if ( collectionPersister.hasCache() ) {
				final CollectionDataAccess cache = collectionPersister.getCacheAccessStrategy();
				final Object ck = cache.generateCacheKey(
					id,
					collectionPersister,
					source.getFactory(),
					source.getTenantIdentifier()
				);
				final SoftLock lock = cache.lockItem( source, ck, null );
				cache.remove( source, ck );
				source.getActionQueue().registerProcess( (success, session) -> cache.unlockItem( session, ck, lock ) );
			}
		}
		else if ( type.isComponentType() ) {
			CompositeType actype = (CompositeType) type;
			evictCachedCollections( actype.getSubtypes(), id, source );
		}
	}
}
 
Example 7
/**
 * Visit a property value. Dispatch to the
 * correct handler for the property type.
 * @param value
 * @param type
 * @throws HibernateException
 */
final Object processValue(Object value, Type type) throws HibernateException {

	if ( type.isCollectionType() ) {
		//even process null collections
		return processCollection( value, (CollectionType) type );
	}
	else if ( type.isEntityType() ) {
		return processEntity( value, (EntityType) type );
	}
	else if ( type.isComponentType() ) {
		return processComponent( value, (CompositeType) type );
	}
	else {
		return null;
	}
}
 
Example 8
public void end(QueryTranslatorImpl q) throws QueryException {
	if ( !isCollectionValued() ) {
		Type type = getPropertyType();
		if ( type.isEntityType() ) {
			// "finish off" the join
			token( ".", q );
			token( null, q );
		}
		else if ( type.isCollectionType() ) {
			// default to element set if no elements() specified
			token( ".", q );
			token( CollectionPropertyNames.COLLECTION_ELEMENTS, q );
		}
	}
	super.end( q );
}
 
Example 9
private void evictCachedCollections(Type[] types, Serializable id, EventSource source)
		throws HibernateException {
	final ActionQueue actionQueue = source.getActionQueue();
	final SessionFactoryImplementor factory = source.getFactory();
	final MetamodelImplementor metamodel = factory.getMetamodel();
	for ( Type type : types ) {
		if ( type.isCollectionType() ) {
			CollectionPersister collectionPersister = metamodel.collectionPersister( ( (CollectionType) type ).getRole() );
			if ( collectionPersister.hasCache() ) {
				final CollectionDataAccess cache = collectionPersister.getCacheAccessStrategy();
				final Object ck = cache.generateCacheKey(
					id,
					collectionPersister,
					factory,
					source.getTenantIdentifier()
				);
				final SoftLock lock = cache.lockItem( source, ck, null );
				cache.remove( source, ck );
				actionQueue.registerProcess( (success, session) -> cache.unlockItem( session, ck, lock ) );
			}
		}
		else if ( type.isComponentType() ) {
			CompositeType actype = (CompositeType) type;
			evictCachedCollections( actype.getSubtypes(), id, source );
		}
	}
}
 
Example 10
private boolean indicatesCollection(Type type) {
	if ( type.isCollectionType() ) {
		return true;
	}
	else if ( type.isComponentType() ) {
		Type[] subtypes = ( ( AbstractComponentType ) type ).getSubtypes();
		for ( int i = 0; i < subtypes.length; i++ ) {
			if ( indicatesCollection( subtypes[i] ) ) {
				return true;
			}
		}
	}
	return false;
}
 
Example 11
private void processJoinReturn(NativeSQLQueryJoinReturn fetchReturn) {
		String alias = fetchReturn.getAlias();
//		if ( alias2Persister.containsKey( alias ) || collectionAliases.contains( alias ) ) {
		if ( alias2Persister.containsKey( alias ) || alias2CollectionPersister.containsKey( alias ) ) {
			// already been processed...
			return;
		}

		String ownerAlias = fetchReturn.getOwnerAlias();

		// Make sure the owner alias is known...
		if ( !alias2Return.containsKey( ownerAlias ) ) {
			throw new HibernateException( "Owner alias [" + ownerAlias + "] is unknown for alias [" + alias + "]" );
		}

		// If this return's alias has not been processed yet, do so b4 further processing of this return
		if ( !alias2Persister.containsKey( ownerAlias ) ) {
			NativeSQLQueryNonScalarReturn ownerReturn = ( NativeSQLQueryNonScalarReturn ) alias2Return.get(ownerAlias);
			processReturn( ownerReturn );
		}

		SQLLoadable ownerPersister = ( SQLLoadable ) alias2Persister.get( ownerAlias );
		Type returnType = ownerPersister.getPropertyType( fetchReturn.getOwnerProperty() );

		if ( returnType.isCollectionType() ) {
			String role = ownerPersister.getEntityName() + '.' + fetchReturn.getOwnerProperty();
			addCollection( role, alias, fetchReturn.getPropertyResultsMap() );
//			collectionOwnerAliases.add( ownerAlias );
		}
		else if ( returnType.isEntityType() ) {
			EntityType eType = ( EntityType ) returnType;
			String returnEntityName = eType.getAssociatedEntityName();
			SQLLoadable persister = getSQLLoadable( returnEntityName );
			addPersister( alias, fetchReturn.getPropertyResultsMap(), persister );
		}

	}
 
Example 12
/**
 * Warning:
 * When there are duplicated property names in the subclasses
 * of the class, this method may return the wrong table
 * number for the duplicated subclass property (note that
 * SingleTableEntityPersister defines an overloaded form
 * which takes the entity name.
 */
public int getSubclassPropertyTableNumber(String propertyPath) {
	String rootPropertyName = StringHelper.root( propertyPath );
	Type type = propertyMapping.toType( rootPropertyName );
	if ( type.isAssociationType() ) {
		AssociationType assocType = (AssociationType) type;
		if ( assocType.useLHSPrimaryKey() ) {
			// performance op to avoid the array search
			return 0;
		}
		else if ( type.isCollectionType() ) {
			// properly handle property-ref-based associations
			rootPropertyName = assocType.getLHSPropertyName();
		}
	}
	//Enable for HHH-440, which we don't like:
	/*if ( type.isComponentType() && !propertyName.equals(rootPropertyName) ) {
		String unrooted = StringHelper.unroot(propertyName);
		int idx = ArrayHelper.indexOf( getSubclassColumnClosure(), unrooted );
		if ( idx != -1 ) {
			return getSubclassColumnTableNumberClosure()[idx];
		}
	}*/
	int index = ArrayHelper.indexOf(
			getSubclassPropertyNameClosure(),
			rootPropertyName
	); //TODO: optimize this better!
	return index == -1 ? 0 : getSubclassPropertyTableNumber( index );
}
 
Example 13
public CteValuesListDeleteHandlerImpl(
		SessionFactoryImplementor factory,
		HqlSqlWalker walker,
		String catalog,
		String schema) {
	super( factory, walker, catalog, schema );

	final String idSubselect = generateIdSubselect( getTargetedQueryable() );

	for ( Type type : getTargetedQueryable().getPropertyTypes() ) {
		if ( type.isCollectionType() ) {
			CollectionType cType = (CollectionType) type;
			AbstractCollectionPersister cPersister = (AbstractCollectionPersister) factory.getMetamodel().collectionPersister( cType.getRole() );
			if ( cPersister.isManyToMany() ) {
				deletes.add( generateDelete(
						cPersister.getTableName(),
						cPersister.getKeyColumnNames(),
						idSubselect,
						"bulk delete - m2m join table cleanup"
				) );
			}
		}
	}

	String[] tableNames = getTargetedQueryable().getConstraintOrderedTableNameClosure();
	String[][] columnNames = getTargetedQueryable().getContraintOrderedTableKeyColumnClosure();
	for ( int i = 0; i < tableNames.length; i++ ) {
		// TODO : an optimization here would be to consider cascade deletes and not gen those delete statements;
		//      the difficulty is the ordering of the tables here vs the cascade attributes on the persisters ->
		//          the table info gotten here should really be self-contained (i.e., a class representation
		//          defining all the needed attributes), then we could then get an array of those
		deletes.add( generateDelete( tableNames[i], columnNames[i], idSubselect, "bulk delete" ) );
	}
}
 
Example 14
private void processJoinReturn(NativeSQLQueryJoinReturn fetchReturn) {
		String alias = fetchReturn.getAlias();
//		if ( alias2Persister.containsKey( alias ) || collectionAliases.contains( alias ) ) {
		if ( alias2Persister.containsKey( alias ) || alias2CollectionPersister.containsKey( alias ) ) {
			// already been processed...
			return;
		}

		String ownerAlias = fetchReturn.getOwnerAlias();

		// Make sure the owner alias is known...
		if ( !alias2Return.containsKey( ownerAlias ) ) {
			throw new HibernateException( "Owner alias [" + ownerAlias + "] is unknown for alias [" + alias + "]" );
		}

		// If this return's alias has not been processed yet, do so b4 further processing of this return
		if ( !alias2Persister.containsKey( ownerAlias ) ) {
			NativeSQLQueryNonScalarReturn ownerReturn = ( NativeSQLQueryNonScalarReturn ) alias2Return.get(ownerAlias);
			processReturn( ownerReturn );
		}

		SQLLoadable ownerPersister = ( SQLLoadable ) alias2Persister.get( ownerAlias );
		Type returnType = ownerPersister.getPropertyType( fetchReturn.getOwnerProperty() );

		if ( returnType.isCollectionType() ) {
			String role = ownerPersister.getEntityName() + '.' + fetchReturn.getOwnerProperty();
			addCollection( role, alias, fetchReturn.getPropertyResultsMap() );
//			collectionOwnerAliases.add( ownerAlias );
		}
		else if ( returnType.isEntityType() ) {
			EntityType eType = ( EntityType ) returnType;
			String returnEntityName = eType.getAssociatedEntityName();
			SQLLoadable persister = getSQLLoadable( returnEntityName );
			addPersister( alias, fetchReturn.getPropertyResultsMap(), persister );
		}

	}
 
Example 15
public DeleteExecutor(HqlSqlWalker walker, Queryable persister) {
	super( walker, persister );
	
	final SessionFactoryImplementor factory = walker.getSessionFactoryHelper().getFactory();
	final Dialect dialect = factory.getJdbcServices().getJdbcEnvironment().getDialect();
	
	try {
		final DeleteStatement deleteStatement = (DeleteStatement) walker.getAST();
		
		final String idSubselectWhere;
		if ( deleteStatement.hasWhereClause() ) {
			final AST whereClause = deleteStatement.getWhereClause();
			final SqlGenerator gen = new SqlGenerator( factory );
			gen.whereClause( whereClause );
			parameterSpecifications = gen.getCollectedParameters();
			idSubselectWhere = gen.getSQL().length() > 7 ? gen.getSQL() : "";
		}
		else {
			parameterSpecifications = new ArrayList<>();
			idSubselectWhere = "";
		}
		
		// If many-to-many, delete the FK row in the collection table.
		for ( Type type : persister.getPropertyTypes() ) {
			if ( type.isCollectionType() ) {
				final CollectionType cType = (CollectionType) type;
				final AbstractCollectionPersister cPersister = (AbstractCollectionPersister) factory.getMetamodel().collectionPersister( cType.getRole() );
				if ( cPersister.isManyToMany() ) {
					if ( persister.getIdentifierColumnNames().length > 1
							&& !dialect.supportsTuplesInSubqueries() ) {
						LOG.warn(
								"This dialect is unable to cascade the delete into the many-to-many join table" +
								" when the entity has multiple primary keys.  Either properly setup cascading on" +
								" the constraints or manually clear the associations prior to deleting the entities."
						);
					}
					else {
						final String idSubselect = "(select "
								+ String.join( ", ", persister.getIdentifierColumnNames() ) + " from "
								+ persister.getTableName() + idSubselectWhere + ")";
						final String where = "(" + String.join( ", ", cPersister.getKeyColumnNames() )
								+ ") in " + idSubselect;
						final Delete delete = new Delete().setTableName( cPersister.getTableName() ).setWhere( where );
						if ( factory.getSessionFactoryOptions().isCommentsEnabled() ) {
							delete.setComment( "delete FKs in join table" );
						}
						deletes.add( delete.toStatementString() );
					}
				}
			}
		}
	}
	catch (RecognitionException e) {
		throw new HibernateException( "Unable to delete the FKs in the join table!", e );
	}
}
 
Example 16
private CriteriaInfoProvider getPathInfo(String path) {
	StringTokenizer tokens = new StringTokenizer( path, "." );
	String componentPath = "";

	// start with the 'rootProvider'
	CriteriaInfoProvider provider = nameCriteriaInfoMap.get( rootEntityName );

	while ( tokens.hasMoreTokens() ) {
		componentPath += tokens.nextToken();
		final Type type = provider.getType( componentPath );
		if ( type.isAssociationType() ) {
			// CollectionTypes are always also AssociationTypes - but there's not always an associated entity...
			final AssociationType atype = (AssociationType) type;
			final CollectionType ctype = type.isCollectionType() ? (CollectionType)type : null;
			final Type elementType = (ctype != null) ? ctype.getElementType( sessionFactory ) : null;
			// is the association a collection of components or value-types? (i.e a colloction of valued types?)
			if ( ctype != null  && elementType.isComponentType() ) {
				provider = new ComponentCollectionCriteriaInfoProvider( helper.getCollectionPersister(ctype.getRole()) );
			}
			else if ( ctype != null && !elementType.isEntityType() ) {
				provider = new ScalarCollectionCriteriaInfoProvider( helper, ctype.getRole() );
			}
			else {
				provider = new EntityCriteriaInfoProvider(
						(Queryable) sessionFactory.getEntityPersister( atype.getAssociatedEntityName( sessionFactory ) )
				);
			}

			componentPath = "";
		}
		else if ( type.isComponentType() ) {
			if (!tokens.hasMoreTokens()) {
				throw new QueryException(
						"Criteria objects cannot be created directly on components.  Create a criteria on " +
								"owning entity and use a dotted property to access component property: " + path
				);
			}
			else {
				componentPath += '.';
			}
		}
		else {
			throw new QueryException( "not an association: " + componentPath );
		}
	}

	return provider;
}
 
Example 17
Source Project: lams   File: DotNode.java    License: GNU General Public License v2.0 4 votes vote down vote up
public void resolve(boolean generateJoin, boolean implicitJoin, String classAlias, AST parent, AST parentPredicate)
		throws SemanticException {
	// If this dot has already been resolved, stop now.
	if ( isResolved() ) {
		return;
	}

	Type propertyType = prepareLhs(); // Prepare the left hand side and get the data type.

	if ( parent == null && AbstractEntityPersister.ENTITY_CLASS.equals( propertyName ) ) {
		DeprecationLogger.DEPRECATION_LOGGER.logDeprecationOfClassEntityTypeSelector( getLhs().getPath() );
	}

	// If there is no data type for this node, and we're at the end of the path (top most dot node), then
	// this might be a Java constant.
	if ( propertyType == null ) {
		if ( parent == null ) {
			getWalker().getLiteralProcessor().lookupConstant( this );
		}
		// If the propertyType is null and there isn't a parent, just
		// stop now... there was a problem resolving the node anyway.
		return;
	}

	if ( propertyType.isComponentType() ) {
		// The property is a component...
		checkLhsIsNotCollection();
		dereferenceComponent( parent );
		initText();
	}
	else if ( propertyType.isEntityType() ) {
		// The property is another class..
		checkLhsIsNotCollection();
		dereferenceEntity( (EntityType) propertyType, implicitJoin, classAlias, generateJoin, parent, parentPredicate );
		initText();
	}
	else if ( propertyType.isCollectionType() ) {
		// The property is a collection...
		checkLhsIsNotCollection();
		dereferenceCollection( (CollectionType) propertyType, implicitJoin, false, classAlias, parent );
	}
	else {
		// Otherwise, this is a primitive type.
		if ( !CollectionProperties.isAnyCollectionProperty( propertyName ) ) {
			checkLhsIsNotCollection();
		}
		dereferenceType = DereferenceType.PRIMITIVE;
		initText();
	}
	setResolved();
}
 
Example 18
@Override
public int execute(
        SharedSessionContractImplementor session,
        QueryParameters queryParameters) {

    IdsClauseBuilder values = prepareInlineStatement( session, queryParameters );

    List<String> currentDeletes = new ArrayList<>();

    if ( !values.getIds().isEmpty() ) {
        final String idSubselect = values.toStatement();

        for ( Type type : getTargetedQueryable().getPropertyTypes() ) {
            if ( type.isCollectionType() ) {
                CollectionType cType = (CollectionType) type;
                AbstractCollectionPersister cPersister = (AbstractCollectionPersister) factory().getMetamodel().collectionPersister( cType.getRole() );
                if ( cPersister.isManyToMany() ) {
                    currentDeletes.add( generateDelete(
                            cPersister.getTableName(),
                            cPersister.getKeyColumnNames(),
                            idSubselect,
                            "bulk delete - m2m join table cleanup"
                    ).toStatementString() );
                }
            }
        }

        String[] tableNames = getTargetedQueryable().getConstraintOrderedTableNameClosure();
        String[][] columnNames = getTargetedQueryable().getContraintOrderedTableKeyColumnClosure();
        for ( int i = 0; i < tableNames.length; i++ ) {
            // TODO : an optimization here would be to consider cascade deletes and not gen those delete statements;
            //      the difficulty is the ordering of the tables here vs the cascade attributes on the persisters ->
            //          the table info gotten here should really be self-contained (i.e., a class representation
            //          defining all the needed attributes), then we could then get an array of those
            currentDeletes.add( generateDelete( tableNames[i], columnNames[i], idSubselect, "bulk delete" ).toStatementString() );
        }

        // Start performing the deletes
        for ( String delete : currentDeletes ) {
            if ( delete == null) {
                continue;
            }

            try {
                try ( PreparedStatement ps = session
                        .getJdbcCoordinator().getStatementPreparer()
                        .prepareStatement( delete, false ) ) {
                    session
                            .getJdbcCoordinator().getResultSetReturn()
                            .executeUpdate( ps );
                }
            }
            catch ( SQLException e ) {
                throw convert( e, "error performing bulk delete", delete );
            }
        }

        //deletes.addAll( currentDeletes );
    }

    return values.getIds().size();
}
 
Example 19
@Override
public int execute(
		SharedSessionContractImplementor session,
		QueryParameters queryParameters) {

	IdsClauseBuilder values = prepareInlineStatement( session, queryParameters );

	if ( !values.getIds().isEmpty() ) {
		final String idSubselect = values.toStatement();

		for ( Type type : getTargetedQueryable().getPropertyTypes() ) {
			if ( type.isCollectionType() ) {
				CollectionType cType = (CollectionType) type;
				AbstractCollectionPersister cPersister = (AbstractCollectionPersister) factory().getMetamodel().collectionPersister( cType.getRole() );
				if ( cPersister.isManyToMany() ) {
					deletes.add( generateDelete(
							cPersister.getTableName(),
							cPersister.getKeyColumnNames(),
							idSubselect,
							"bulk delete - m2m join table cleanup"
					).toStatementString() );
				}
			}
		}

		String[] tableNames = getTargetedQueryable().getConstraintOrderedTableNameClosure();
		String[][] columnNames = getTargetedQueryable().getContraintOrderedTableKeyColumnClosure();
		for ( int i = 0; i < tableNames.length; i++ ) {
			// TODO : an optimization here would be to consider cascade deletes and not gen those delete statements;
			//      the difficulty is the ordering of the tables here vs the cascade attributes on the persisters ->
			//          the table info gotten here should really be self-contained (i.e., a class representation
			//          defining all the needed attributes), then we could then get an array of those
			deletes.add( generateDelete( tableNames[i], columnNames[i], idSubselect, "bulk delete" ).toStatementString() );
		}

		// Start performing the deletes
		for ( String delete : deletes ) {
			if ( delete == null) {
				continue;
			}

			try {
				try ( PreparedStatement ps = session
						.getJdbcCoordinator().getStatementPreparer()
						.prepareStatement( delete, false ) ) {
					session
							.getJdbcCoordinator().getResultSetReturn()
							.executeUpdate( ps );
				}
			}
			catch ( SQLException e ) {
				throw convert( e, "error performing bulk delete", delete );
			}
		}
	}

	return values.getIds().size();
}
 
Example 20
Source Project: lams   File: IndexNode.java    License: GNU General Public License v2.0 4 votes vote down vote up
@Override
public void resolve(boolean generateJoin, boolean implicitJoin, String classAlias, AST parent, AST parentPredicate)
		throws SemanticException {
	if ( isResolved() ) {
		return;
	}
	FromReferenceNode collectionNode = (FromReferenceNode) getFirstChild();
	SessionFactoryHelper sessionFactoryHelper = getSessionFactoryHelper();
	collectionNode.resolveIndex( this );        // Fully resolve the map reference, create implicit joins.

	Type type = collectionNode.getDataType();
	if ( !type.isCollectionType() ) {
		throw new SemanticException( "The [] operator cannot be applied to type " + type.toString() );
	}
	String collectionRole = ( (CollectionType) type ).getRole();
	QueryableCollection queryableCollection = sessionFactoryHelper.requireQueryableCollection( collectionRole );
	if ( !queryableCollection.hasIndex() ) {
		throw new QueryException( "unindexed fromElement before []: " + collectionNode.getPath() );
	}

	// Generate the inner join -- The elements need to be joined to the collection they are in.
	FromElement fromElement = collectionNode.getFromElement();
	String elementTable = fromElement.getTableAlias();
	FromClause fromClause = fromElement.getFromClause();
	String path = collectionNode.getPath();

	FromElement elem = fromClause.findCollectionJoin( path );
	if ( elem == null ) {
		FromElementFactory factory = new FromElementFactory( fromClause, fromElement, path );
		elem = factory.createCollectionElementsJoin( queryableCollection, elementTable );
		LOG.debugf( "No FROM element found for the elements of collection join path %s, created %s", path, elem );
	}
	else {
		LOG.debugf( "FROM element found for collection join path %s", path );
	}

	// The 'from element' that represents the elements of the collection.
	setFromElement( fromElement );

	// Add the condition to the join sequence that qualifies the indexed element.
	AST selector = collectionNode.getNextSibling();
	if ( selector == null ) {
		throw new QueryException( "No index value!" );
	}

	// Sometimes use the element table alias, sometimes use the... umm... collection table alias (many to many)
	String collectionTableAlias = elementTable;
	if ( elem.getCollectionTableAlias() != null ) {
		collectionTableAlias = elem.getCollectionTableAlias();
	}

	// TODO: get SQL rendering out of here, create an AST for the join expressions.
	// Use the SQL generator grammar to generate the SQL text for the index expression.
	JoinSequence joinSequence = fromElement.getJoinSequence();
	String[] indexCols = queryableCollection.getIndexColumnNames();
	if ( indexCols.length != 1 ) {
		throw new QueryException( "composite-index appears in []: " + collectionNode.getPath() );
	}
	SqlGenerator gen = new SqlGenerator( getSessionFactoryHelper().getFactory() );
	try {
		gen.simpleExpr( selector ); //TODO: used to be exprNoParens! was this needed?
	}
	catch (RecognitionException e) {
		throw new QueryException( e.getMessage(), e );
	}
	String selectorExpression = gen.getSQL();
	joinSequence.addCondition( collectionTableAlias + '.' + indexCols[0] + " = " + selectorExpression );
	List<ParameterSpecification> paramSpecs = gen.getCollectedParameters();
	if ( paramSpecs != null ) {
		switch ( paramSpecs.size() ) {
			case 0:
				// nothing to do
				break;
			case 1:
				ParameterSpecification paramSpec = paramSpecs.get( 0 );
				paramSpec.setExpectedType( queryableCollection.getIndexType() );
				fromElement.setIndexCollectionSelectorParamSpec( paramSpec );
				break;
			default:
				fromElement.setIndexCollectionSelectorParamSpec(
						new AggregatedIndexCollectionSelectorParameterSpecifications( paramSpecs )
				);
				break;
		}
	}

	// Now, set the text for this node.  It should be the element columns.
	String[] elementColumns = queryableCollection.getElementColumnNames( elementTable );
	setText( elementColumns[0] );
	setResolved();
}