Search in sources :

Example 11 with EJBQLException

use of org.apache.cayenne.ejbql.EJBQLException in project cayenne by apache.

the class Compiler method compileEntityResult.

private EntityResult compileEntityResult(EJBQLExpression expression, int position) {
    String id = expression.getText().toLowerCase();
    ClassDescriptor descriptor = descriptorsById.get(id);
    if (descriptor == null) {
        descriptor = descriptorsById.get(expression.getText());
    }
    if (descriptor == null) {
        throw new EJBQLException("the entity variable '" + id + "' does not refer to any entity in the FROM clause");
    }
    final EntityResult entityResult = new EntityResult(descriptor.getObjectClass());
    final String prefix = "ec" + position + "_";
    final int[] index = { 0 };
    final Set<String> visited = new HashSet<String>();
    PropertyVisitor visitor = new PropertyVisitor() {

        public boolean visitAttribute(AttributeProperty property) {
            ObjAttribute oa = property.getAttribute();
            if (visited.add(oa.getDbAttributePath())) {
                entityResult.addObjectField(oa.getEntity().getName(), oa.getName(), prefix + index[0]++);
            }
            return true;
        }

        public boolean visitToMany(ToManyProperty property) {
            return true;
        }

        public boolean visitToOne(ToOneProperty property) {
            ObjRelationship rel = property.getRelationship();
            DbRelationship dbRel = rel.getDbRelationships().get(0);
            for (DbJoin join : dbRel.getJoins()) {
                DbAttribute src = join.getSource();
                if (src.isForeignKey() && visited.add(src.getName())) {
                    entityResult.addDbField(src.getName(), prefix + index[0]++);
                }
            }
            return true;
        }
    };
    descriptor.visitAllProperties(visitor);
    // append id columns ... (some may have been appended already via relationships)
    for (String pkName : descriptor.getEntity().getPrimaryKeyNames()) {
        if (visited.add(pkName)) {
            entityResult.addDbField(pkName, prefix + index[0]++);
        }
    }
    // append inheritance discriminator columns...
    for (ObjAttribute column : descriptor.getDiscriminatorColumns()) {
        if (visited.add(column.getName())) {
            entityResult.addDbField(column.getDbAttributePath(), prefix + index[0]++);
        }
    }
    return entityResult;
}
Also used : ObjRelationship(org.apache.cayenne.map.ObjRelationship) ClassDescriptor(org.apache.cayenne.reflect.ClassDescriptor) ObjAttribute(org.apache.cayenne.map.ObjAttribute) EJBQLException(org.apache.cayenne.ejbql.EJBQLException) DbAttribute(org.apache.cayenne.map.DbAttribute) EntityResult(org.apache.cayenne.map.EntityResult) AttributeProperty(org.apache.cayenne.reflect.AttributeProperty) ToOneProperty(org.apache.cayenne.reflect.ToOneProperty) ToManyProperty(org.apache.cayenne.reflect.ToManyProperty) DbRelationship(org.apache.cayenne.map.DbRelationship) DbJoin(org.apache.cayenne.map.DbJoin) PropertyVisitor(org.apache.cayenne.reflect.PropertyVisitor) HashSet(java.util.HashSet)

Example 12 with EJBQLException

use of org.apache.cayenne.ejbql.EJBQLException in project cayenne by apache.

the class EJBQLPathAnaliserTranslator method visitMemberOf.

@Override
public boolean visitMemberOf(EJBQLExpression expression) {
    if (expression.getChildrenCount() != 2) {
        throw new EJBQLException("MEMBER OF must have exactly two children, got: " + expression.getChildrenCount());
    }
    if (!(expression.getChild(1) instanceof EJBQLPath)) {
        throw new EJBQLException("Second child of the MEMBER OF must be a collection path, got: " + expression.getChild(1));
    }
    QuotingStrategy quoter = context.getQuotingStrategy();
    EJBQLPath path = (EJBQLPath) expression.getChild(1);
    // make sure the ID for the path does not overlap with other condition
    // joins...
    String id = path.getAbsolutePath();
    String correlatedEntityId = path.getId();
    ClassDescriptor correlatedEntityDescriptor = context.getEntityDescriptor(correlatedEntityId);
    String correlatedTableName = quoter.quotedFullyQualifiedName(correlatedEntityDescriptor.getEntity().getDbEntity());
    String correlatedTableAlias = context.getTableAlias(correlatedEntityId, correlatedTableName);
    String subqueryId = context.createIdAlias(id);
    ClassDescriptor targetDescriptor = context.getEntityDescriptor(subqueryId);
    if (expression.isNegated()) {
        context.append(" NOT");
    }
    context.append(" EXISTS (SELECT 1 FROM ");
    String subqueryTableName = quoter.quotedFullyQualifiedName(targetDescriptor.getEntity().getDbEntity());
    String subqueryRootAlias = context.getTableAlias(subqueryId, subqueryTableName);
    ObjRelationship relationship = correlatedEntityDescriptor.getEntity().getRelationship(path.getRelativePath());
    if (relationship.getDbRelationshipPath().contains(".")) {
        // if the DbRelationshipPath contains '.', the relationship is
        // flattened
        subqueryRootAlias = processFlattenedRelationShip(subqueryRootAlias, relationship);
    } else {
        // not using "AS" to separate table name and alias name - OpenBase
        // doesn't
        // support "AS", and the rest of the databases do not care
        context.append(subqueryTableName).append(' ').append(subqueryRootAlias);
    }
    context.append(" WHERE");
    DbRelationship correlatedJoinRelationship = context.getIncomingRelationships(new EJBQLTableId(id)).get(0);
    for (DbJoin join : correlatedJoinRelationship.getJoins()) {
        context.append(' ').append(subqueryRootAlias).append('.').append(join.getTargetName()).append(" = ");
        context.append(correlatedTableAlias).append('.').append(quoter.quotedSourceName(join));
        context.append(" AND");
    }
    // translate subquery_root_id = LHS_of_memberof
    EJBQLEquals equals = new EJBQLEquals(-1);
    EJBQLIdentificationVariable identifier = new EJBQLIdentificationVariable(-1);
    identifier.setText(subqueryId);
    equals.jjtAddChild(identifier, 0);
    equals.jjtAddChild((Node) expression.getChild(0), 1);
    equals.visit(this);
    context.append(")");
    return false;
}
Also used : ObjRelationship(org.apache.cayenne.map.ObjRelationship) EJBQLIdentificationVariable(org.apache.cayenne.ejbql.parser.EJBQLIdentificationVariable) ClassDescriptor(org.apache.cayenne.reflect.ClassDescriptor) DbRelationship(org.apache.cayenne.map.DbRelationship) EJBQLException(org.apache.cayenne.ejbql.EJBQLException) DbJoin(org.apache.cayenne.map.DbJoin) QuotingStrategy(org.apache.cayenne.dba.QuotingStrategy) EJBQLPath(org.apache.cayenne.ejbql.parser.EJBQLPath) EJBQLEquals(org.apache.cayenne.ejbql.parser.EJBQLEquals)

Example 13 with EJBQLException

use of org.apache.cayenne.ejbql.EJBQLException in project cayenne by apache.

the class EJBQLPathAnaliserTranslator method visitIdentificationVariable.

@Override
public boolean visitIdentificationVariable(EJBQLExpression expression) {
    // this is a match on a variable, like "x = :x"
    ClassDescriptor descriptor = context.getEntityDescriptor(expression.getText());
    if (descriptor == null) {
        throw new EJBQLException("Invalid identification variable: " + expression.getText());
    }
    DbEntity table = descriptor.getEntity().getDbEntity();
    String alias = context.getTableAlias(expression.getText(), context.getQuotingStrategy().quotedFullyQualifiedName(table));
    Collection<DbAttribute> pks = table.getPrimaryKeys();
    if (pks.size() == 1) {
        DbAttribute pk = pks.iterator().next();
        context.append(' ').append(alias).append('.').append(context.getQuotingStrategy().quotedName(pk));
    } else {
        throw new EJBQLException("Multi-column PK to-many matches are not yet supported.");
    }
    return false;
}
Also used : ClassDescriptor(org.apache.cayenne.reflect.ClassDescriptor) DbEntity(org.apache.cayenne.map.DbEntity) EJBQLException(org.apache.cayenne.ejbql.EJBQLException) DbAttribute(org.apache.cayenne.map.DbAttribute)

Example 14 with EJBQLException

use of org.apache.cayenne.ejbql.EJBQLException in project cayenne by apache.

the class EJBQLPathAnaliserTranslator method visitIntegerLiteral.

@Override
public boolean visitIntegerLiteral(EJBQLIntegerLiteral expression) {
    if (expression.getText() == null) {
        context.append("null");
    } else {
        String text = expression.getText();
        if (expression.isNegative() && text != null) {
            if (text.startsWith("-")) {
                text = text.substring(1);
            } else {
                text = "-" + text;
            }
        }
        Long longValue;
        try {
            longValue = Long.valueOf(text);
        } catch (NumberFormatException nfex) {
            throw new EJBQLException("Invalid integer: " + expression.getText());
        }
        if (longValue > Integer.MAX_VALUE) {
            String var = context.bindParameter(longValue);
            context.append(" #bind($").append(var).append(" 'BIGINT')");
        } else {
            String var = context.bindParameter(longValue.intValue());
            context.append(" #bind($").append(var).append(" 'INTEGER')");
        }
    }
    return true;
}
Also used : EJBQLException(org.apache.cayenne.ejbql.EJBQLException)

Example 15 with EJBQLException

use of org.apache.cayenne.ejbql.EJBQLException in project cayenne by apache.

the class EJBQLJoinAppender method appendJoin.

protected void appendJoin(String marker, EJBQLTableId lhsId, EJBQLTableId rhsId, String semantics) {
    List<DbRelationship> joinRelationships = context.getIncomingRelationships(rhsId);
    if (joinRelationships.isEmpty()) {
        throw new EJBQLException("No join configured for id " + rhsId);
    }
    QuotingStrategy quoter = context.getQuotingStrategy();
    DbRelationship incomingDB = joinRelationships.get(0);
    // TODO: andrus, 1/6/2008 - move reusable join check here...
    DbEntity sourceEntity = incomingDB.getSourceEntity();
    String tableName = quoter.quotedFullyQualifiedName(sourceEntity);
    String sourceAlias = context.getTableAlias(lhsId.getEntityId(), tableName);
    if (marker != null) {
        context.pushMarker(marker, false);
    }
    try {
        context.append(" ").append(semantics);
        if (joinRelationships.size() > 1) {
            // if size of relationship list greater than 1,
            // it's a flattened relationship
            context.append(" ");
            for (int i = 1; i < joinRelationships.size(); i++) {
                DbRelationship dbRelationship = joinRelationships.get(i);
                String subquerySourceTableName = quoter.quotedFullyQualifiedName(dbRelationship.getSourceEntity());
                String subquerySourceAlias = context.getTableAlias(subquerySourceTableName, subquerySourceTableName);
                String subqueryTargetTableName = quoter.quotedFullyQualifiedName(dbRelationship.getTargetEntity());
                String subqueryTargetAlias;
                if (i == joinRelationships.size() - 1) {
                    // it's the last table alias
                    subqueryTargetAlias = context.getTableAlias(rhsId.getEntityId(), subqueryTargetTableName);
                } else {
                    subqueryTargetAlias = context.getTableAlias(subqueryTargetTableName, subqueryTargetTableName);
                }
                if (i == 1) {
                    // first apply the joins defined in query
                    context.append(subquerySourceTableName).append(' ').append(subquerySourceAlias);
                    generateJoiningExpression(incomingDB, sourceAlias, subquerySourceAlias);
                }
                context.append(" JOIN ");
                context.append(subqueryTargetTableName).append(' ').append(subqueryTargetAlias);
                generateJoiningExpression(dbRelationship, subquerySourceAlias, subqueryTargetAlias);
            }
        } else {
            // non-flattened relationship
            String targetAlias = appendTable(rhsId);
            // apply the joins defined in query
            generateJoiningExpression(incomingDB, sourceAlias, targetAlias);
        }
    } finally {
        if (marker != null) {
            context.popMarker();
        }
    }
}
Also used : DbEntity(org.apache.cayenne.map.DbEntity) DbRelationship(org.apache.cayenne.map.DbRelationship) EJBQLException(org.apache.cayenne.ejbql.EJBQLException) QuotingStrategy(org.apache.cayenne.dba.QuotingStrategy)

Aggregations

EJBQLException (org.apache.cayenne.ejbql.EJBQLException)19 DbRelationship (org.apache.cayenne.map.DbRelationship)9 ClassDescriptor (org.apache.cayenne.reflect.ClassDescriptor)9 DbAttribute (org.apache.cayenne.map.DbAttribute)7 DbEntity (org.apache.cayenne.map.DbEntity)7 ObjRelationship (org.apache.cayenne.map.ObjRelationship)7 DbJoin (org.apache.cayenne.map.DbJoin)5 HashMap (java.util.HashMap)3 QuotingStrategy (org.apache.cayenne.dba.QuotingStrategy)3 EJBQLExpression (org.apache.cayenne.ejbql.EJBQLExpression)2 EJBQLExpressionVisitor (org.apache.cayenne.ejbql.EJBQLExpressionVisitor)2 EJBQLPath (org.apache.cayenne.ejbql.parser.EJBQLPath)2 EntityResult (org.apache.cayenne.map.EntityResult)2 ObjAttribute (org.apache.cayenne.map.ObjAttribute)2 AttributeProperty (org.apache.cayenne.reflect.AttributeProperty)2 PropertyDescriptor (org.apache.cayenne.reflect.PropertyDescriptor)2 BigDecimal (java.math.BigDecimal)1 HashSet (java.util.HashSet)1 Map (java.util.Map)1 CayenneRuntimeException (org.apache.cayenne.CayenneRuntimeException)1