private void doPathExpression(String token, QueryTranslatorImpl q) throws QueryException { preprocess(token, q); StringTokenizer tokens = new StringTokenizer(token, ".", true); pathExpressionParser.start(q); while (tokens.hasMoreTokens()) { pathExpressionParser.token(tokens.nextToken(), q); } pathExpressionParser.end(q); if (pathExpressionParser.isCollectionValued()) { openExpression(q, ""); appendToken(q, pathExpressionParser.getCollectionSubquery(q.getEnabledFilters())); closeExpression(q, ""); // this is ugly here, but needed because its a subquery q.addQuerySpaces( q.getCollectionPersister(pathExpressionParser.getCollectionRole()).getCollectionSpaces()); } else { if (pathExpressionParser.isExpectingCollectionIndex()) { expectingIndex++; } else { addJoin(pathExpressionParser.getWhereJoin(), q); appendToken(q, pathExpressionParser.getWhereColumn()); } } }
private void prepareForIndex(QueryTranslatorImpl q) throws QueryException { QueryableCollection collPersister = q.getCollectionPersister(collectionRole); if (!collPersister.hasIndex()) throw new QueryException("unindexed collection before []: " + path); String[] indexCols = collPersister.getIndexColumnNames(); if (indexCols.length != 1) throw new QueryException("composite-index appears in []: " + path); // String[] keyCols = collPersister.getKeyColumnNames(); JoinSequence fromJoins = new JoinSequence(q.getFactory()) .setUseThetaStyle(useThetaStyleJoin) .setRoot(collPersister, collectionName) .setNext(joinSequence.copy()); if (!continuation) addJoin(collectionName, collPersister.getCollectionType()); joinSequence.addCondition( collectionName + '.' + indexCols[0] + " = "); // TODO: get SQL rendering out of here CollectionElement elem = new CollectionElement(); elem.elementColumns = collPersister.getElementColumnNames(collectionName); elem.elementType = collPersister.getElementType(); elem.isOneToMany = collPersister.isOneToMany(); elem.alias = collectionName; elem.joinSequence = joinSequence; collectionElements.addLast(elem); setExpectingCollectionIndex(); q.addCollection(collectionName, collectionRole); q.addFromJoinOnly(collectionName, fromJoins); }
public void fetch(QueryTranslatorImpl q, String entityName) throws QueryException { if (isCollectionValued()) { q.setCollectionToFetch( getCollectionRole(), getCollectionName(), getCollectionOwnerName(), entityName); } else { q.addEntityToFetch(entityName, getOneToOneOwnerName(), getOwnerAssociationType()); } }
private void addJoin(JoinSequence joinSequence, QueryTranslatorImpl q) throws QueryException { // JoinFragment fromClause = q.createJoinFragment(true); // fromClause.addJoins( join.toJoinFragment().toFromFragmentString(), StringHelper.EMPTY_STRING // ); q.addFromJoinOnly(pathExpressionParser.getName(), joinSequence); try { addToCurrentJoin( joinSequence.toJoinFragment(q.getEnabledFilters(), true).toWhereFragmentString()); } catch (MappingException me) { throw new QueryException(me); } }
private void dereferenceCollection(String propertyName, String role, QueryTranslatorImpl q) throws QueryException { collectionRole = role; QueryableCollection collPersister = q.getCollectionPersister(role); String name = q.createNameForCollection(role); addJoin(name, collPersister.getCollectionType()); // if ( collPersister.hasWhere() ) join.addCondition( collPersister.getSQLWhereString(name) ); collectionName = name; collectionOwnerName = currentName; currentName = name; currentProperty = propertyName; componentPath.setLength(0); currentPropertyMapping = new CollectionPropertyMapping(collPersister); }
String continueFromManyToMany(String entityName, String[] joinColumns, QueryTranslatorImpl q) throws QueryException { start(q); continuation = true; currentName = q.createNameFor(entityName); q.addType(currentName, entityName); Queryable classPersister = q.getEntityPersister(entityName); // QueryJoinFragment join = q.createJoinFragment(useThetaStyleJoin); addJoin( currentName, q.getFactory().getTypeResolver().getTypeFactory().manyToOne(entityName), joinColumns); currentPropertyMapping = classPersister; return currentName; }
private String getRole(String name) { String role = (String) collections.get(name); if (role == null && superQuery != null) { role = superQuery.getRole(name); } return role; }
void appendToken(QueryTranslatorImpl q, String token) { if (expectingIndex > 0) { pathExpressionParser.setLastCollectionElementIndexValue(token); } else { q.appendWhereToken(token); } }
private String getType(String name) { String type = (String) typeMap.get(name); if (type == null && superQuery != null) { type = superQuery.getType(name); } return type; }
/** * Compile a subquery. * * @param superquery The containing query of the query to be compiled. * @throws org.hibernate.MappingException Indicates problems resolving things referenced in the * query. * @throws org.hibernate.QueryException Generally some form of syntatic failure. */ void compile(QueryTranslatorImpl superquery) throws QueryException, MappingException { this.tokenReplacements = superquery.tokenReplacements; this.superQuery = superquery; this.shallowQuery = true; this.enabledFilters = superquery.getEnabledFilters(); compile(); }
public void start(QueryTranslatorImpl q) { if (!continuation) { reset(q); path.setLength(0); joinSequence = new JoinSequence(q.getFactory()).setUseThetaStyle(useThetaStyleJoin); } }
public String addFromAssociation(QueryTranslatorImpl q) throws QueryException { if (isCollectionValued()) { return addFromCollection(q); } else { q.addFrom(currentName, joinSequence); return currentName; } }
public String getAliasName(String alias) { String name = (String) aliasNames.get(alias); if (name == null) { if (superQuery != null) { name = superQuery.getAliasName(alias); } else { name = alias; } } return name; }
private void dereferenceEntity( String propertyName, EntityType propertyType, QueryTranslatorImpl q) throws QueryException { // NOTE: we avoid joining to the next table if the named property is just the foreign key value // if its "id" boolean isIdShortcut = EntityPersister.ENTITY_ID.equals(propertyName) && propertyType.isReferenceToPrimaryKey(); // or its the id property name final String idPropertyName; try { idPropertyName = propertyType.getIdentifierOrUniqueKeyPropertyName(q.getFactory()); } catch (MappingException me) { throw new QueryException(me); } boolean isNamedIdPropertyShortcut = idPropertyName != null && idPropertyName.equals(propertyName) && propertyType.isReferenceToPrimaryKey(); if (isIdShortcut || isNamedIdPropertyShortcut) { // special shortcut for id properties, skip the join! // this must only occur at the _end_ of a path expression if (componentPath.length() > 0) componentPath.append('.'); componentPath.append(propertyName); } else { String entityClass = propertyType.getAssociatedEntityName(); String name = q.createNameFor(entityClass); q.addType(name, entityClass); addJoin(name, propertyType); if (propertyType.isOneToOne()) oneToOneOwnerName = currentName; ownerAssociationType = propertyType; currentName = name; currentProperty = propertyName; q.addPathAliasAndJoin( path.substring(0, path.toString().lastIndexOf('.')), name, joinSequence.copy()); componentPath.setLength(0); currentPropertyMapping = q.getEntityPersister(entityClass); } }
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; } }
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); } } } } }
void addNamedParameter(String name) { if (superQuery != null) superQuery.addNamedParameter(name); Integer loc = parameterCount++; Object o = namedParameters.get(name); if (o == null) { namedParameters.put(name, loc); } else if (o instanceof Integer) { ArrayList list = new ArrayList(4); list.add(o); list.add(loc); namedParameters.put(name, list); } else { ((ArrayList) o).add(loc); } }
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; }
boolean isName(String name) { return aliasNames.containsKey(name) || typeMap.containsKey(name) || collections.containsKey(name) || (superQuery != null && superQuery.isName(name)); }
public void token(String token, QueryTranslatorImpl q) throws QueryException { if (token != null) path.append(token); String alias = q.getPathAlias(path.toString()); if (alias != null) { reset(q); // reset the dotcount (but not the path) currentName = alias; // after reset! currentPropertyMapping = q.getPropertyMapping(currentName); if (!ignoreInitialJoin) { JoinSequence ojf = q.getPathJoin(path.toString()); try { joinSequence.addCondition( ojf.toJoinFragment(q.getEnabledFilters(), true) .toWhereFragmentString()); // after reset! } catch (MappingException me) { throw new QueryException(me); } // we don't need to worry about any condition in the ON clause // here (toFromFragmentString), since anything in the ON condition // is already applied to the whole query } } else if (".".equals(token)) { dotcount++; } else { if (dotcount == 0) { if (!continuation) { if (!q.isName(token)) throw new QueryException("undefined alias: " + token); currentName = token; currentPropertyMapping = q.getPropertyMapping(currentName); } } else if (dotcount == 1) { if (currentName != null) { currentProperty = token; } else if (collectionName != null) { // processCollectionProperty(token, q.getCollectionPersister(collectionRole), // collectionName); continuation = false; } else { throw new QueryException("unexpected"); } } else { // dotcount>=2 // Do the corresponding RHS Type propertyType = getPropertyType(); if (propertyType == null) { throw new QueryException("unresolved property: " + path); } if (propertyType.isComponentType()) { dereferenceComponent(token); } else if (propertyType.isEntityType()) { if (!isCollectionValued()) dereferenceEntity(token, (EntityType) propertyType, q); } else if (propertyType.isCollectionType()) { dereferenceCollection(token, ((CollectionType) propertyType).getRole(), q); } else { if (token != null) throw new QueryException("dereferenced: " + path); } } } }
public void addAssociation(QueryTranslatorImpl q) throws QueryException { q.addJoin(getName(), joinSequence); }
void addQuerySpaces(Serializable[] spaces) { for (int i = 0; i < spaces.length; i++) { querySpaces.add(spaces[i]); } if (superQuery != null) superQuery.addQuerySpaces(spaces); }
public void token(String token, QueryTranslatorImpl q) throws QueryException { String lcToken = token.toLowerCase(Locale.ROOT); // Cope with [,] if (token.equals("[") && !expectingPathContinuation) { expectingPathContinuation = false; if (expectingIndex == 0) { throw new QueryException("unexpected ["); } return; } else if (token.equals("]")) { expectingIndex--; expectingPathContinuation = true; return; } // Cope with a continued path expression (ie. ].baz) if (expectingPathContinuation) { boolean pathExpressionContinuesFurther = continuePathExpression(token, q); if (pathExpressionContinuesFurther) { return; // NOTE: early return } } // Cope with a subselect if (!inSubselect && (lcToken.equals("select") || lcToken.equals("from"))) { inSubselect = true; subselect = new StringBuilder(20); } if (inSubselect && token.equals(")")) { bracketsSinceSelect--; if (bracketsSinceSelect == -1) { QueryTranslatorImpl subq = new QueryTranslatorImpl(subselect.toString(), q.getEnabledFilters(), q.getFactory()); try { subq.compile(q); } catch (MappingException me) { throw new QueryException("MappingException occurred compiling subquery", me); } appendToken(q, subq.getSQLString()); inSubselect = false; bracketsSinceSelect = 0; } } if (inSubselect) { if (token.equals("(")) { bracketsSinceSelect++; } subselect.append(token).append(' '); return; } // Cope with special cases of AND, NOT, () specialCasesBefore(lcToken); // Close extra brackets we opened if (!betweenSpecialCase && EXPRESSION_TERMINATORS.contains(lcToken)) { closeExpression(q, lcToken); } // take note when this is a boolean expression if (BOOLEAN_OPERATORS.contains(lcToken)) { booleanTests.removeLast(); booleanTests.addLast(Boolean.TRUE); } if (lcToken.equals("not")) { nots.addLast(!(nots.removeLast())); negated = !negated; return; // NOTE: early return } // process a token, mapping OO path expressions to SQL expressions doToken(token, q); // Open any extra brackets we might need. if (!betweenSpecialCase && EXPRESSION_OPENERS.contains(lcToken)) { openExpression(q, lcToken); } // Cope with special cases of AND, NOT, ) specialCasesAfter(lcToken); }