private Queryable determineAppropriateOwnerPersister(NonScalarReturn ownerDescriptor) { String entityName = null; if (ownerDescriptor instanceof RootReturn) { entityName = ((RootReturn) ownerDescriptor).getEntityName(); } else if (ownerDescriptor instanceof CollectionReturn) { CollectionReturn collRtn = (CollectionReturn) ownerDescriptor; String role = collRtn.getOwnerEntityName() + "." + collRtn.getOwnerProperty(); CollectionPersister persister = getFactory().getCollectionPersister(role); EntityType ownerType = (EntityType) persister.getElementType(); entityName = ownerType.getAssociatedEntityName(getFactory()); } else if (ownerDescriptor instanceof FetchReturn) { FetchReturn fetchRtn = (FetchReturn) ownerDescriptor; Queryable persister = determineAppropriateOwnerPersister(fetchRtn.getOwner()); Type ownerType = persister.getPropertyType(fetchRtn.getOwnerProperty()); if (ownerType.isEntityType()) { entityName = ((EntityType) ownerType).getAssociatedEntityName(getFactory()); } else if (ownerType.isCollectionType()) { Type ownerCollectionElementType = ((CollectionType) ownerType).getElementType(getFactory()); if (ownerCollectionElementType.isEntityType()) { entityName = ((EntityType) ownerCollectionElementType).getAssociatedEntityName(getFactory()); } } } if (entityName == null) { throw new HibernateException("Could not determine fetch owner : " + ownerDescriptor); } return (Queryable) getFactory().getEntityPersister(entityName); }
public String addFromCollection(QueryTranslatorImpl q) throws QueryException { Type collectionElementType = getPropertyType(); if (collectionElementType == null) { throw new QueryException( "must specify 'elements' for collection valued property in from clause: " + path); } if (collectionElementType.isEntityType()) { // an association QueryableCollection collectionPersister = q.getCollectionPersister(collectionRole); Queryable entityPersister = (Queryable) collectionPersister.getElementPersister(); String clazz = entityPersister.getEntityName(); final String elementName; if (collectionPersister.isOneToMany()) { elementName = collectionName; // allow index() function: q.decoratePropertyMapping(elementName, collectionPersister); } else { // many-to-many q.addCollection(collectionName, collectionRole); elementName = q.createNameFor(clazz); addJoin(elementName, (AssociationType) collectionElementType); } q.addFrom(elementName, clazz, joinSequence); currentPropertyMapping = new CollectionPropertyMapping(collectionPersister); return elementName; } else { // collections of values q.addFromCollection(collectionName, collectionRole, joinSequence); return collectionName; } }
/** Get the a typed value for the given property value. */ @Override public TypedValue getTypedValue(Criteria subcriteria, String propertyName, Object value) throws HibernateException { // Detect discriminator values... if (value instanceof Class) { Class entityClass = (Class) value; Queryable q = SessionFactoryHelper.findQueryableUsingImports(sessionFactory, entityClass.getName()); if (q != null) { Type type = q.getDiscriminatorType(); String stringValue = q.getDiscriminatorSQLValue(); if (stringValue != null && stringValue.length() > 2 && stringValue.startsWith("'") && stringValue.endsWith("'")) { // remove the single // quotes stringValue = stringValue.substring(1, stringValue.length() - 1); } // Convert the string value into the proper type. if (type instanceof StringRepresentableType) { StringRepresentableType nullableType = (StringRepresentableType) type; value = nullableType.fromStringValue(stringValue); } else { throw new QueryException("Unsupported discriminator type " + type); } return new TypedValue(type, value); } } // Otherwise, this is an ordinary value. return new TypedValue(getTypeUsingProjection(subcriteria, propertyName), value); }
private AST generateVersionPropertyNode(Queryable persister) throws SemanticException { String versionPropertyName = persister.getPropertyNames()[persister.getVersionProperty()]; AST versionPropertyRef = getASTFactory().create(HqlSqlTokenTypes.IDENT, versionPropertyName); AST versionPropertyNode = lookupNonQualifiedProperty(versionPropertyRef); resolve(versionPropertyNode); return versionPropertyNode; }
protected AST createIntoClause(String path, AST propertySpec) throws SemanticException { Queryable persister = (Queryable) getSessionFactoryHelper().requireClassPersister(path); IntoClause intoClause = (IntoClause) getASTFactory().create(INTO, persister.getEntityName()); intoClause.setFirstChild(propertySpec); intoClause.initialize(persister); addQuerySpaces(persister.getQuerySpaces()); return intoClause; }
public AssignmentSpecification(AST eq, Queryable persister) { if (eq.getType() != HqlSqlTokenTypes.EQ) { throw new QueryException("assignment in set-clause not associated with equals"); } this.eq = eq; this.factory = persister.getFactory(); // Needed to bump this up to DotNode, because that is the only thing which currently // knows about the property-ref path in the correct format; it is either this, or // recurse over the DotNodes constructing the property path just like DotNode does // internally final PathSeparatorNode lhs = (PathSeparatorNode) eq.getFirstChild(); final SqlNode rhs = (SqlNode) lhs.getNextSibling(); validateLhs(lhs); final String propertyPath = lhs.getPropertyPath(); Set<String> temp = new HashSet<String>(); // yuck! if (persister instanceof UnionSubclassEntityPersister) { final String[] tables = persister.getConstraintOrderedTableNameClosure(); Collections.addAll(temp, tables); } else { temp.add( persister.getSubclassTableName(persister.getSubclassPropertyTableNumber(propertyPath))); } this.tableNames = Collections.unmodifiableSet(temp); if (rhs == null) { hqlParameters = new ParameterSpecification[0]; } else if (isParam(rhs)) { hqlParameters = new ParameterSpecification[] {((ParameterNode) rhs).getHqlParameterSpecification()}; } else { List parameterList = ASTUtil.collectChildren( rhs, new ASTUtil.IncludePredicate() { public boolean include(AST node) { return isParam(node); } }); hqlParameters = new ParameterSpecification[parameterList.size()]; Iterator itr = parameterList.iterator(); int i = 0; while (itr.hasNext()) { hqlParameters[i++] = ((ParameterNode) itr.next()).getHqlParameterSpecification(); } } }
private void doToken(String token, QueryTranslatorImpl q) throws QueryException { if (q.isName(StringHelper.root(token))) { // path expression doPathExpression(q.unalias(token), q); } else if (token.startsWith(ParserHelper.HQL_VARIABLE_PREFIX)) { // named query parameter q.addNamedParameter(token.substring(1)); appendToken(q, "?"); } else { Queryable persister = q.getEntityPersisterUsingImports(token); if (persister != null) { // the name of a class final String discrim = persister.getDiscriminatorSQLValue(); if (InFragment.NULL.equals(discrim) || InFragment.NOT_NULL.equals(discrim)) { throw new QueryException("subclass test not allowed for null or not null discriminator"); } else { appendToken(q, discrim); } } else { Object constant; if (token.indexOf('.') > -1 && (constant = ReflectHelper.getConstantValue( token, q.getFactory().getServiceRegistry().getService(ClassLoaderService.class))) != null) { Type type; try { type = q.getFactory().getTypeResolver().heuristicType(constant.getClass().getName()); } catch (MappingException me) { throw new QueryException(me); } if (type == null) { throw new QueryException(QueryTranslator.ERROR_CANNOT_DETERMINE_TYPE + token); } try { //noinspection unchecked appendToken( q, ((LiteralType) type).objectToSQLString(constant, q.getFactory().getDialect())); } catch (Exception e) { throw new QueryException(QueryTranslator.ERROR_CANNOT_FORMAT_LITERAL + token, e); } } else { // anything else String negatedToken = negated ? NEGATIONS.get(token.toLowerCase(Locale.ROOT)) : null; if (negatedToken != null && (!betweenSpecialCase || !"or".equals(negatedToken))) { appendToken(q, negatedToken); } else { appendToken(q, token); } } } } }
private void determineKeySelectExpressions( QueryableCollection collectionPersister, List selections) { AliasGenerator aliasGenerator = new LocalAliasGenerator(0); appendSelectExpressions(collectionPersister.getIndexColumnNames(), selections, aliasGenerator); Type keyType = collectionPersister.getIndexType(); if (keyType.isAssociationType()) { EntityType entityType = (EntityType) keyType; Queryable keyEntityPersister = (Queryable) sfi().getEntityPersister(entityType.getAssociatedEntityName(sfi())); SelectFragment fragment = keyEntityPersister.propertySelectFragmentFragment(collectionTableAlias(), null, false); appendSelectExpressions(fragment, selections, aliasGenerator); } }
private void determineValueSelectExpressions( QueryableCollection collectionPersister, List selections) { AliasGenerator aliasGenerator = new LocalAliasGenerator(1); appendSelectExpressions( collectionPersister.getElementColumnNames(), selections, aliasGenerator); Type valueType = collectionPersister.getElementType(); if (valueType.isAssociationType()) { EntityType valueEntityType = (EntityType) valueType; Queryable valueEntityPersister = (Queryable) sfi().getEntityPersister(valueEntityType.getAssociatedEntityName(sfi())); SelectFragment fragment = valueEntityPersister.propertySelectFragmentFragment(elementTableAlias(), null, false); appendSelectExpressions(fragment, selections, aliasGenerator); } }
private FromElement createEntityAssociation(String role, String roleAlias, int joinType) throws SemanticException { FromElement elem; Queryable entityPersister = (Queryable) queryableCollection.getElementPersister(); String associatedEntityName = entityPersister.getEntityName(); // Get the class name of the associated entity. if (queryableCollection.isOneToMany()) { if (log.isDebugEnabled()) { log.debug( "createEntityAssociation() : One to many - path = " + path + " role = " + role + " associatedEntityName = " + associatedEntityName); } JoinSequence joinSequence = createJoinSequence(roleAlias, joinType); elem = createJoin( associatedEntityName, roleAlias, joinSequence, (EntityType) queryableCollection.getElementType(), false); } else { if (log.isDebugEnabled()) { log.debug( "createManyToMany() : path = " + path + " role = " + role + " associatedEntityName = " + associatedEntityName); } elem = createManyToMany( role, associatedEntityName, roleAlias, entityPersister, (EntityType) queryableCollection.getElementType(), joinType); fromClause.getWalker().addQuerySpaces(queryableCollection.getCollectionSpaces()); } elem.setCollectionTableAlias(roleAlias); return elem; }
protected void postProcessDML(RestrictableStatement statement) throws SemanticException { statement.getFromClause().resolve(); FromElement fromElement = (FromElement) statement.getFromClause().getFromElements().get(0); Queryable persister = fromElement.getQueryable(); // Make #@%$^#^&# sure no alias is applied to the table name fromElement.setText(persister.getTableName()); // append any filter fragments; the EMPTY_MAP is used under the assumption that // currently enabled filters should not affect this process if (persister.getDiscriminatorType() != null) { new SyntheticAndFactory(getASTFactory()) .addDiscriminatorWhereFragment( statement, persister, java.util.Collections.EMPTY_MAP, fromElement.getTableAlias()); } }
private FromElement createManyToMany( String role, String associatedEntityName, String roleAlias, Queryable entityPersister, EntityType type, int joinType) throws SemanticException { FromElement elem; SessionFactoryHelper sfh = fromClause.getSessionFactoryHelper(); if (inElementsFunction /*implied*/) { // For implied many-to-many, just add the end join. JoinSequence joinSequence = createJoinSequence(roleAlias, joinType); elem = createJoin(associatedEntityName, roleAlias, joinSequence, type, true); } else { // For an explicit many-to-many relationship, add a second join from the intermediate // (many-to-many) table to the destination table. Also, make sure that the from element's // idea of the destination is the destination table. String tableAlias = fromClause.getAliasGenerator().createName(entityPersister.getEntityName()); String[] secondJoinColumns = sfh.getCollectionElementColumns(role, roleAlias); // Add the second join, the one that ends in the destination table. JoinSequence joinSequence = createJoinSequence(roleAlias, joinType); joinSequence.addJoin( sfh.getElementAssociationType(collectionType), tableAlias, joinType, secondJoinColumns); elem = createJoin(associatedEntityName, tableAlias, joinSequence, type, false); elem.setUseFromFragment(true); } return elem; }
protected void prepareVersioned(AST updateNode, AST versioned) throws SemanticException { UpdateStatement updateStatement = (UpdateStatement) updateNode; FromClause fromClause = updateStatement.getFromClause(); if (versioned != null) { // Make sure that the persister is versioned Queryable persister = fromClause.getFromElement().getQueryable(); if (!persister.isVersioned()) { throw new SemanticException( "increment option specified for update of non-versioned entity"); } VersionType versionType = persister.getVersionType(); if (versionType instanceof UserVersionType) { throw new SemanticException( "user-defined version types not supported for increment option"); } AST eq = getASTFactory().create(HqlSqlTokenTypes.EQ, "="); AST versionPropertyNode = generateVersionPropertyNode(persister); eq.setFirstChild(versionPropertyNode); AST versionIncrementNode = null; if (Date.class.isAssignableFrom(versionType.getReturnedClass())) { versionIncrementNode = getASTFactory().create(HqlSqlTokenTypes.PARAM, "?"); ParameterSpecification paramSpec = new VersionTypeSeedParameterSpecification(versionType); ((ParameterNode) versionIncrementNode).setHqlParameterSpecification(paramSpec); parameters.add(0, paramSpec); } else { // Not possible to simply re-use the versionPropertyNode here as it causes // OOM errors due to circularity :( versionIncrementNode = getASTFactory().create(HqlSqlTokenTypes.PLUS, "+"); versionIncrementNode.setFirstChild(generateVersionPropertyNode(persister)); versionIncrementNode.addChild(getASTFactory().create(HqlSqlTokenTypes.IDENT, "1")); } eq.addChild(versionIncrementNode); evaluateAssignment(eq, persister, 0); AST setClause = updateStatement.getSetClause(); AST currentFirstSetElement = setClause.getFirstChild(); setClause.setFirstChild(eq); eq.setNextSibling(currentFirstSetElement); } }
protected void dropTemporaryTableIfNecessary( final Queryable persister, final SessionImplementor session) { if (getFactory().getDialect().dropTemporaryTableAfterUse()) { IsolatedWork work = new IsolatedWork() { public void doWork(Connection connection) throws HibernateException { Statement stmnt = null; try { stmnt = connection.createStatement(); stmnt.executeUpdate("drop table " + persister.getTemporaryIdTableName()); } catch (Throwable t) { log.warn("unable to drop temporary id table after use [" + t.getMessage() + "]"); } finally { if (stmnt != null) { try { stmnt.close(); } catch (Throwable ignore) { // ignore } } } } }; if (shouldIsolateTemporaryTableDDL()) { if (getFactory().getSettings().isDataDefinitionInTransactionSupported()) { Isolater.doIsolatedWork(work, session); } else { Isolater.doNonTransactedWork(work, session); } } else { work.doWork(session.getJDBCContext().getConnectionManager().getConnection()); session.getJDBCContext().getConnectionManager().afterStatement(); } } else { // at the very least cleanup the data :) PreparedStatement ps = null; try { ps = session .getBatcher() .prepareStatement("delete from " + persister.getTemporaryIdTableName()); ps.executeUpdate(); } catch (Throwable t) { log.warn("unable to cleanup temporary id table after use [" + t + "]"); } finally { if (ps != null) { try { session.getBatcher().closeStatement(ps); } catch (Throwable ignore) { // ignore } } } } }
private void evaluateAssignment(AST eq, Queryable persister, int targetIndex) { if (persister.isMultiTable()) { // no need to even collect this information if the persister is considered multi-table AssignmentSpecification specification = new AssignmentSpecification(eq, persister); if (targetIndex >= 0) { assignmentSpecifications.add(targetIndex, specification); } else { assignmentSpecifications.add(specification); } numberOfParametersInSetClause += specification.getParameters().length; } }
private String getPathEntityName(String path) { Queryable persister = (Queryable) sessionFactory.getEntityPersister(rootEntityName); StringTokenizer tokens = new StringTokenizer(path, "."); String componentPath = ""; while (tokens.hasMoreTokens()) { componentPath += tokens.nextToken(); Type type = persister.toType(componentPath); if (type.isAssociationType()) { AssociationType atype = (AssociationType) type; persister = (Queryable) sessionFactory.getEntityPersister(atype.getAssociatedEntityName(sessionFactory)); componentPath = ""; } else if (type.isComponentType()) { componentPath += '.'; } else { throw new QueryException("not an association: " + componentPath); } } return persister.getEntityName(); }
@Override public void execute(Connection connection) { try { Statement statement = connection.createStatement(); try { statement.executeUpdate(persister.getTemporaryIdTableDDL()); persister .getFactory() .getServiceRegistry() .getService(JdbcServices.class) .getSqlExceptionHelper() .handleAndClearWarnings(statement, CREATION_WARNING_HANDLER); } finally { try { statement.close(); } catch (Throwable ignore) { // ignore } } } catch (Exception e) { log.debug("unable to create temporary id table [" + e.getMessage() + "]"); } }
protected void releaseTempTable(Queryable persister, SessionImplementor session) { if (session.getFactory().getDialect().dropTemporaryTableAfterUse()) { TemporaryTableDropWork work = new TemporaryTableDropWork(persister, session); if (shouldIsolateTemporaryTableDDL(session)) { session .getTransactionCoordinator() .getTransaction() .createIsolationDelegate() .delegateWork( work, session.getFactory().getSettings().isDataDefinitionInTransactionSupported()); } else { final Connection connection = session .getTransactionCoordinator() .getJdbcCoordinator() .getLogicalConnection() .getShareableConnectionProxy(); work.execute(connection); session .getTransactionCoordinator() .getJdbcCoordinator() .getLogicalConnection() .afterStatementExecution(); } } else { // at the very least cleanup the data :) PreparedStatement ps = null; try { final String sql = "delete from " + persister.getTemporaryIdTableName(); ps = session .getTransactionCoordinator() .getJdbcCoordinator() .getStatementPreparer() .prepareStatement(sql, false); ps.executeUpdate(); } catch (Throwable t) { log.unableToCleanupTemporaryIdTable(t); } finally { if (ps != null) { try { ps.close(); } catch (Throwable ignore) { // ignore } } } } }
protected String generateIdInsertSelect(Queryable persister, String tableAlias, AST whereClause) { Select select = new Select(getFactory().getDialect()); SelectFragment selectFragment = new SelectFragment() .addColumns( tableAlias, persister.getIdentifierColumnNames(), persister.getIdentifierColumnNames()); select.setSelectClause(selectFragment.toFragmentString().substring(2)); String rootTableName = persister.getTableName(); String fromJoinFragment = persister.fromJoinFragment(tableAlias, true, false); String whereJoinFragment = persister.whereJoinFragment(tableAlias, true, false); select.setFromClause(rootTableName + ' ' + tableAlias + fromJoinFragment); if (whereJoinFragment == null) { whereJoinFragment = ""; } else { whereJoinFragment = whereJoinFragment.trim(); if (whereJoinFragment.startsWith("and")) { whereJoinFragment = whereJoinFragment.substring(4); } } String userWhereClause = ""; if (whereClause.getNumberOfChildren() != 0) { // If a where clause was specified in the update/delete query, use it to limit the // returned ids here... try { SqlGenerator sqlGenerator = new SqlGenerator(getFactory()); sqlGenerator.whereClause(whereClause); userWhereClause = sqlGenerator.getSQL().substring(7); // strip the " where " } catch (RecognitionException e) { throw new HibernateException("Unable to generate id select for DML operation", e); } if (whereJoinFragment.length() > 0) { whereJoinFragment += " and "; } } select.setWhereClause(whereJoinFragment + userWhereClause); InsertSelect insert = new InsertSelect(getFactory().getDialect()); if (getFactory().getSettings().isCommentsEnabled()) { insert.setComment("insert-select for " + persister.getEntityName() + " ids"); } insert.setTableName(persister.getTemporaryIdTableName()); insert.setSelect(select); return insert.toStatementString(); }
/** * Return the names of all persistent (mapped) classes that extend or implement the given class or * interface, accounting for implicit/explicit polymorphism settings and excluding mapped * subclasses/joined-subclasses of other classes in the result. */ public String[] getImplementors(String className) throws MappingException { final Class clazz; try { clazz = ReflectHelper.classForName(className); } catch (ClassNotFoundException cnfe) { return new String[] {className}; // for a dynamic-class } ArrayList results = new ArrayList(); Iterator iter = entityPersisters.values().iterator(); while (iter.hasNext()) { // test this entity to see if we must query it EntityPersister testPersister = (EntityPersister) iter.next(); if (testPersister instanceof Queryable) { Queryable testQueryable = (Queryable) testPersister; String testClassName = testQueryable.getEntityName(); boolean isMappedClass = className.equals(testClassName); if (testQueryable.isExplicitPolymorphism()) { if (isMappedClass) { return new String[] {className}; // NOTE EARLY EXIT } } else { if (isMappedClass) { results.add(testClassName); } else { final Class mappedClass = testQueryable.getMappedClass(EntityMode.POJO); if (mappedClass != null && clazz.isAssignableFrom(mappedClass)) { final boolean assignableSuperclass; if (testQueryable.isInherited()) { Class mappedSuperclass = getEntityPersister(testQueryable.getMappedSuperclass()) .getMappedClass(EntityMode.POJO); assignableSuperclass = clazz.isAssignableFrom(mappedSuperclass); } else { assignableSuperclass = false; } if (!assignableSuperclass) { results.add(testClassName); } } } } } } return (String[]) results.toArray(new String[results.size()]); }
@Override public void execute(Connection connection) { final String command = session.getFactory().getDialect().getDropTemporaryTableString() + ' ' + persister.getTemporaryIdTableName(); try { Statement statement = connection.createStatement(); try { statement = connection.createStatement(); statement.executeUpdate(command); } finally { try { statement.close(); } catch (Throwable ignore) { // ignore } } } catch (Exception e) { log.warn("unable to drop temporary id table after use [" + e.getMessage() + "]"); } }
protected String generateIdSubselect(Queryable persister) { return "select " + StringHelper.join(", ", persister.getIdentifierColumnNames()) + " from " + persister.getTemporaryIdTableName(); }
public CustomLoader(CustomQuery customQuery, SessionFactoryImplementor factory) { super(factory); this.sql = customQuery.getSQL(); this.querySpaces.addAll(customQuery.getQuerySpaces()); this.namedParameterBindPoints = customQuery.getNamedParameterBindPoints(); List entityPersisters = new ArrayList(); List entityOwners = new ArrayList(); List entityAliases = new ArrayList(); List collectionPersisters = new ArrayList(); List collectionOwners = new ArrayList(); List collectionAliases = new ArrayList(); List lockModes = new ArrayList(); List resultColumnProcessors = new ArrayList(); List nonScalarReturnList = new ArrayList(); List resultTypes = new ArrayList(); List specifiedAliases = new ArrayList(); int returnableCounter = 0; boolean hasScalars = false; List includeInResultRowList = new ArrayList(); Iterator itr = customQuery.getCustomQueryReturns().iterator(); while (itr.hasNext()) { final Return rtn = (Return) itr.next(); if (rtn instanceof ScalarReturn) { ScalarReturn scalarRtn = (ScalarReturn) rtn; resultTypes.add(scalarRtn.getType()); specifiedAliases.add(scalarRtn.getColumnAlias()); resultColumnProcessors.add( new ScalarResultColumnProcessor( StringHelper.unquote(scalarRtn.getColumnAlias(), factory.getDialect()), scalarRtn.getType())); includeInResultRowList.add(true); hasScalars = true; } else if (ConstructorReturn.class.isInstance(rtn)) { final ConstructorReturn constructorReturn = (ConstructorReturn) rtn; resultTypes.add(null); // this bit makes me nervous includeInResultRowList.add(true); hasScalars = true; ScalarResultColumnProcessor[] scalarProcessors = new ScalarResultColumnProcessor[constructorReturn.getScalars().length]; int i = 0; for (ScalarReturn scalarReturn : constructorReturn.getScalars()) { scalarProcessors[i++] = new ScalarResultColumnProcessor( StringHelper.unquote(scalarReturn.getColumnAlias(), factory.getDialect()), scalarReturn.getType()); } resultColumnProcessors.add( new ConstructorResultColumnProcessor( constructorReturn.getTargetClass(), scalarProcessors)); } else if (rtn instanceof RootReturn) { RootReturn rootRtn = (RootReturn) rtn; Queryable persister = (Queryable) factory.getEntityPersister(rootRtn.getEntityName()); entityPersisters.add(persister); lockModes.add((rootRtn.getLockMode())); resultColumnProcessors.add(new NonScalarResultColumnProcessor(returnableCounter++)); nonScalarReturnList.add(rtn); entityOwners.add(-1); resultTypes.add(persister.getType()); specifiedAliases.add(rootRtn.getAlias()); entityAliases.add(rootRtn.getEntityAliases()); ArrayHelper.addAll(querySpaces, persister.getQuerySpaces()); includeInResultRowList.add(true); } else if (rtn instanceof CollectionReturn) { CollectionReturn collRtn = (CollectionReturn) rtn; String role = collRtn.getOwnerEntityName() + "." + collRtn.getOwnerProperty(); QueryableCollection persister = (QueryableCollection) factory.getCollectionPersister(role); collectionPersisters.add(persister); lockModes.add(collRtn.getLockMode()); resultColumnProcessors.add(new NonScalarResultColumnProcessor(returnableCounter++)); nonScalarReturnList.add(rtn); collectionOwners.add(-1); resultTypes.add(persister.getType()); specifiedAliases.add(collRtn.getAlias()); collectionAliases.add(collRtn.getCollectionAliases()); // determine if the collection elements are entities... Type elementType = persister.getElementType(); if (elementType.isEntityType()) { Queryable elementPersister = (Queryable) ((EntityType) elementType).getAssociatedJoinable(factory); entityPersisters.add(elementPersister); entityOwners.add(-1); entityAliases.add(collRtn.getElementEntityAliases()); ArrayHelper.addAll(querySpaces, elementPersister.getQuerySpaces()); } includeInResultRowList.add(true); } else if (rtn instanceof EntityFetchReturn) { EntityFetchReturn fetchRtn = (EntityFetchReturn) rtn; NonScalarReturn ownerDescriptor = fetchRtn.getOwner(); int ownerIndex = nonScalarReturnList.indexOf(ownerDescriptor); entityOwners.add(ownerIndex); lockModes.add(fetchRtn.getLockMode()); Queryable ownerPersister = determineAppropriateOwnerPersister(ownerDescriptor); EntityType fetchedType = (EntityType) ownerPersister.getPropertyType(fetchRtn.getOwnerProperty()); String entityName = fetchedType.getAssociatedEntityName(getFactory()); Queryable persister = (Queryable) factory.getEntityPersister(entityName); entityPersisters.add(persister); nonScalarReturnList.add(rtn); specifiedAliases.add(fetchRtn.getAlias()); entityAliases.add(fetchRtn.getEntityAliases()); ArrayHelper.addAll(querySpaces, persister.getQuerySpaces()); includeInResultRowList.add(false); } else if (rtn instanceof CollectionFetchReturn) { CollectionFetchReturn fetchRtn = (CollectionFetchReturn) rtn; NonScalarReturn ownerDescriptor = fetchRtn.getOwner(); int ownerIndex = nonScalarReturnList.indexOf(ownerDescriptor); collectionOwners.add(ownerIndex); lockModes.add(fetchRtn.getLockMode()); Queryable ownerPersister = determineAppropriateOwnerPersister(ownerDescriptor); String role = ownerPersister.getEntityName() + '.' + fetchRtn.getOwnerProperty(); QueryableCollection persister = (QueryableCollection) factory.getCollectionPersister(role); collectionPersisters.add(persister); nonScalarReturnList.add(rtn); specifiedAliases.add(fetchRtn.getAlias()); collectionAliases.add(fetchRtn.getCollectionAliases()); // determine if the collection elements are entities... Type elementType = persister.getElementType(); if (elementType.isEntityType()) { Queryable elementPersister = (Queryable) ((EntityType) elementType).getAssociatedJoinable(factory); entityPersisters.add(elementPersister); entityOwners.add(ownerIndex); entityAliases.add(fetchRtn.getElementEntityAliases()); ArrayHelper.addAll(querySpaces, elementPersister.getQuerySpaces()); } includeInResultRowList.add(false); } else { throw new HibernateException( "unexpected custom query return type : " + rtn.getClass().getName()); } } this.entityPersisters = new Queryable[entityPersisters.size()]; for (int i = 0; i < entityPersisters.size(); i++) { this.entityPersisters[i] = (Queryable) entityPersisters.get(i); } this.entiytOwners = ArrayHelper.toIntArray(entityOwners); this.entityAliases = new EntityAliases[entityAliases.size()]; for (int i = 0; i < entityAliases.size(); i++) { this.entityAliases[i] = (EntityAliases) entityAliases.get(i); } this.collectionPersisters = new QueryableCollection[collectionPersisters.size()]; for (int i = 0; i < collectionPersisters.size(); i++) { this.collectionPersisters[i] = (QueryableCollection) collectionPersisters.get(i); } this.collectionOwners = ArrayHelper.toIntArray(collectionOwners); this.collectionAliases = new CollectionAliases[collectionAliases.size()]; for (int i = 0; i < collectionAliases.size(); i++) { this.collectionAliases[i] = (CollectionAliases) collectionAliases.get(i); } this.lockModes = new LockMode[lockModes.size()]; for (int i = 0; i < lockModes.size(); i++) { this.lockModes[i] = (LockMode) lockModes.get(i); } this.resultTypes = ArrayHelper.toTypeArray(resultTypes); this.transformerAliases = ArrayHelper.toStringArray(specifiedAliases); this.rowProcessor = new ResultRowProcessor( hasScalars, (ResultColumnProcessor[]) resultColumnProcessors.toArray( new ResultColumnProcessor[resultColumnProcessors.size()])); this.includeInResultRow = ArrayHelper.toBooleanArray(includeInResultRowList); }
private void renderSQL() throws QueryException, MappingException { final int rtsize; if (returnedTypes.size() == 0 && scalarTypes.size() == 0) { // ie no select clause in HQL returnedTypes = fromTypes; rtsize = returnedTypes.size(); } else { rtsize = returnedTypes.size(); Iterator iter = entitiesToFetch.iterator(); while (iter.hasNext()) { returnedTypes.add(iter.next()); } } int size = returnedTypes.size(); persisters = new Queryable[size]; names = new String[size]; owners = new int[size]; ownerAssociationTypes = new EntityType[size]; suffixes = new String[size]; includeInSelect = new boolean[size]; for (int i = 0; i < size; i++) { String name = (String) returnedTypes.get(i); // if ( !isName(name) ) throw new QueryException("unknown type: " + name); persisters[i] = getEntityPersisterForName(name); // TODO: cannot use generateSuffixes() - it handles the initial suffix differently. suffixes[i] = (size == 1) ? "" : Integer.toString(i) + '_'; names[i] = name; includeInSelect[i] = !entitiesToFetch.contains(name); if (includeInSelect[i]) selectLength++; if (name.equals(collectionOwnerName)) collectionOwnerColumn = i; String oneToOneOwner = (String) oneToOneOwnerNames.get(name); owners[i] = (oneToOneOwner == null) ? -1 : returnedTypes.indexOf(oneToOneOwner); ownerAssociationTypes[i] = (EntityType) uniqueKeyOwnerReferences.get(name); } if (ArrayHelper.isAllNegative(owners)) owners = null; String scalarSelect = renderScalarSelect(); // Must be done here because of side-effect! yuck... int scalarSize = scalarTypes.size(); hasScalars = scalarTypes.size() != rtsize; returnTypes = new Type[scalarSize]; for (int i = 0; i < scalarSize; i++) { returnTypes[i] = (Type) scalarTypes.get(i); } QuerySelect sql = new QuerySelect(getFactory().getDialect()); sql.setDistinct(distinct); if (!shallowQuery) { renderIdentifierSelect(sql); renderPropertiesSelect(sql); } if (collectionPersister != null) { sql.addSelectFragmentString(collectionPersister.selectFragment(fetchName, "__")); } if (hasScalars || shallowQuery) sql.addSelectFragmentString(scalarSelect); // TODO: for some dialects it would be appropriate to add the renderOrderByPropertiesSelect() to // other select strings mergeJoins(sql.getJoinFragment()); sql.setWhereTokens(whereTokens.iterator()); sql.setGroupByTokens(groupByTokens.iterator()); sql.setHavingTokens(havingTokens.iterator()); sql.setOrderByTokens(orderByTokens.iterator()); if (collectionPersister != null && collectionPersister.hasOrdering()) { sql.addOrderBy(collectionPersister.getSQLOrderByString(fetchName)); } scalarColumnNames = NameGenerator.generateColumnNames(returnTypes, getFactory()); // initialize the Set of queried identifier spaces (ie. tables) Iterator iter = collections.values().iterator(); while (iter.hasNext()) { CollectionPersister p = getCollectionPersister((String) iter.next()); addQuerySpaces(p.getCollectionSpaces()); } iter = typeMap.keySet().iterator(); while (iter.hasNext()) { Queryable p = getEntityPersisterForName((String) iter.next()); addQuerySpaces(p.getQuerySpaces()); } sqlString = sql.toQueryString(); if (holderClass != null) holderConstructor = ReflectHelper.getConstructor(holderClass, returnTypes); if (hasScalars) { actualReturnTypes = returnTypes; } else { actualReturnTypes = new Type[selectLength]; int j = 0; for (int i = 0; i < persisters.length; i++) { if (includeInSelect[i]) { actualReturnTypes[j++] = getFactory() .getTypeResolver() .getTypeFactory() .manyToOne(persisters[i].getEntityName(), shallowQuery); } } } }
void addFromClass(String name, Queryable classPersister) throws QueryException { JoinSequence joinSequence = new JoinSequence(getFactory()).setRoot(classPersister, name); // crossJoins.add(name); addFrom(name, classPersister.getEntityName(), joinSequence); }
protected void postProcessInsert(AST insert) throws SemanticException, QueryException { InsertStatement insertStatement = (InsertStatement) insert; insertStatement.validate(); SelectClause selectClause = insertStatement.getSelectClause(); Queryable persister = insertStatement.getIntoClause().getQueryable(); if (!insertStatement.getIntoClause().isExplicitIdInsertion()) { // We need to generate ids as part of this bulk insert. // // Note that this is only supported for sequence-style generators and // post-insert-style generators; basically, only in-db generators IdentifierGenerator generator = persister.getIdentifierGenerator(); if (!supportsIdGenWithBulkInsertion(generator)) { throw new QueryException( "can only generate ids as part of bulk insert with either sequence or post-insert style generators"); } AST idSelectExprNode = null; if (SequenceGenerator.class.isAssignableFrom(generator.getClass())) { String seqName = (String) ((SequenceGenerator) generator).generatorKey(); String nextval = sessionFactoryHelper.getFactory().getDialect().getSelectSequenceNextValString(seqName); idSelectExprNode = getASTFactory().create(HqlSqlTokenTypes.SQL_TOKEN, nextval); } else { // Don't need this, because we should never ever be selecting no columns in an insert ... // select... // and because it causes a bug on DB2 /*String idInsertString = sessionFactoryHelper.getFactory().getDialect().getIdentityInsertString(); if ( idInsertString != null ) { idSelectExprNode = getASTFactory().create( HqlSqlTokenTypes.SQL_TOKEN, idInsertString ); }*/ } if (idSelectExprNode != null) { AST currentFirstSelectExprNode = selectClause.getFirstChild(); selectClause.setFirstChild(idSelectExprNode); idSelectExprNode.setNextSibling(currentFirstSelectExprNode); insertStatement.getIntoClause().prependIdColumnSpec(); } } final boolean includeVersionProperty = persister.isVersioned() && !insertStatement.getIntoClause().isExplicitVersionInsertion() && persister.isVersionPropertyInsertable(); if (includeVersionProperty) { // We need to seed the version value as part of this bulk insert VersionType versionType = persister.getVersionType(); AST versionValueNode = null; if (sessionFactoryHelper.getFactory().getDialect().supportsParametersInInsertSelect()) { versionValueNode = getASTFactory().create(HqlSqlTokenTypes.PARAM, "?"); ParameterSpecification paramSpec = new VersionTypeSeedParameterSpecification(versionType); ((ParameterNode) versionValueNode).setHqlParameterSpecification(paramSpec); parameters.add(0, paramSpec); } else { if (isIntegral(versionType)) { try { Object seedValue = versionType.seed(null); versionValueNode = getASTFactory().create(HqlSqlTokenTypes.SQL_TOKEN, seedValue.toString()); } catch (Throwable t) { throw new QueryException( "could not determine seed value for version on bulk insert [" + versionType + "]"); } } else if (isDatabaseGeneratedTimestamp(versionType)) { String functionName = sessionFactoryHelper.getFactory().getDialect().getCurrentTimestampSQLFunctionName(); versionValueNode = getASTFactory().create(HqlSqlTokenTypes.SQL_TOKEN, functionName); } else { throw new QueryException( "cannot handle version type [" + versionType + "] on bulk inserts with dialects not supporting parameters in insert-select statements"); } } AST currentFirstSelectExprNode = selectClause.getFirstChild(); selectClause.setFirstChild(versionValueNode); versionValueNode.setNextSibling(currentFirstSelectExprNode); insertStatement.getIntoClause().prependVersionColumnSpec(); } if (insertStatement.getIntoClause().isDiscriminated()) { String sqlValue = insertStatement.getIntoClause().getQueryable().getDiscriminatorSQLValue(); AST discrimValue = getASTFactory().create(HqlSqlTokenTypes.SQL_TOKEN, sqlValue); insertStatement.getSelectClause().addChild(discrimValue); } }