Example #1
0
  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();
      }
    }
  }
Example #7
0
  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);
          }
        }
      }
    }
  }
Example #8
0
 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);
   }
 }
Example #9
0
 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();
 }
Example #23
0
  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);
    }
  }