Search in sources :

Example 1 with EJBQLException

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

the class EJBQLPathAnaliserTranslator method visitSize.

@Override
public boolean visitSize(EJBQLExpression expression) {
    if (expression.getChildrenCount() != 1) {
        throw new EJBQLException("SIZE must have exactly one child, got: " + expression.getChildrenCount());
    }
    if (!(expression.getChild(0) instanceof EJBQLPath)) {
        throw new EJBQLException("First child of SIZE must be a collection path, got: " + expression.getChild(1));
    }
    QuotingStrategy quoter = context.getQuotingStrategy();
    EJBQLPath path = (EJBQLPath) expression.getChild(0);
    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);
    Iterator<DbJoin> it = correlatedJoinRelationship.getJoins().iterator();
    while (it.hasNext()) {
        DbJoin join = it.next();
        context.append(' ').append(subqueryRootAlias).append('.').append(join.getTargetName()).append(" = ");
        context.append(correlatedTableAlias).append('.').append(quoter.quotedSourceName(join));
        if (it.hasNext()) {
            context.append(" AND");
        }
    }
    context.append(")");
    return false;
}
Also used : ObjRelationship(org.apache.cayenne.map.ObjRelationship) 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)

Example 2 with EJBQLException

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

the class EJBQLPathAnaliserTranslator method visitDecimalLiteral.

@Override
public boolean visitDecimalLiteral(EJBQLDecimalLiteral 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;
            }
        }
        Object value;
        try {
            value = new BigDecimal(text);
        } catch (NumberFormatException nfex) {
            throw new EJBQLException("Invalid decimal: " + expression.getText());
        }
        String var = context.bindParameter(value);
        context.append(" #bind($").append(var).append(" 'DECIMAL')");
    }
    return true;
}
Also used : EJBQLException(org.apache.cayenne.ejbql.EJBQLException) BigDecimal(java.math.BigDecimal)

Example 3 with EJBQLException

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

the class EJBQLPathAnaliserTranslator method processParameter.

private void processParameter(String boundName, EJBQLExpression expression) {
    Object object = context.getBoundParameter(boundName);
    Map<?, ?> map = null;
    if (object instanceof Persistent) {
        map = ((Persistent) object).getObjectId().getIdSnapshot();
    } else if (object instanceof ObjectId) {
        map = ((ObjectId) object).getIdSnapshot();
    } else if (object instanceof Map) {
        map = (Map<?, ?>) object;
    }
    if (map != null) {
        if (map.size() == 1) {
            context.rebindParameter(boundName, map.values().iterator().next());
        } else {
            addMultiColumnOperand(EJBQLMultiColumnOperand.getObjectOperand(context, map));
            return;
        }
    }
    if (object != null) {
        context.append(" #bind($").append(boundName).append(")");
    } else {
        String type = null;
        Node parent = ((SimpleNode) expression).jjtGetParent();
        context.pushMarker("@processParameter", true);
        EJBQLPathAnaliserTranslator translator = new EJBQLPathAnaliserTranslator(context);
        parent.visit(translator);
        translator.visitPath(parent, parent.getChildrenCount());
        String id = translator.idPath;
        if (id != null) {
            ClassDescriptor descriptor = context.getEntityDescriptor(id);
            if (descriptor == null) {
                throw new EJBQLException("Unmapped id variable: " + id);
            }
            String pathChunk = translator.lastPathComponent;
            PropertyDescriptor property = descriptor.getProperty(pathChunk);
            if (property instanceof AttributeProperty) {
                String atrType = ((AttributeProperty) property).getAttribute().getType();
                type = TypesMapping.getSqlNameByType(TypesMapping.getSqlTypeByJava(atrType));
            }
        }
        context.popMarker();
        if (type == null) {
            type = "VARCHAR";
        }
        // this is a hack to prevent execptions on DB's like Derby for
        // expressions
        // "X = NULL". The 'VARCHAR' parameter is totally bogus, but seems
        // to work on
        // all tested DB's... Also note what JPA spec, chapter 4.11 says:
        // "Comparison
        // or arithmetic operations with a NULL value always yield an
        // unknown value."
        // TODO: andrus 6/28/2007 Ideally we should track the type of the
        // current
        // expression to provide a meaningful type.
        context.append(" #bind($").append(boundName).append(" '" + type + "')");
    }
}
Also used : ClassDescriptor(org.apache.cayenne.reflect.ClassDescriptor) PropertyDescriptor(org.apache.cayenne.reflect.PropertyDescriptor) ObjectId(org.apache.cayenne.ObjectId) SimpleNode(org.apache.cayenne.ejbql.parser.SimpleNode) Node(org.apache.cayenne.ejbql.parser.Node) AggregateConditionNode(org.apache.cayenne.ejbql.parser.AggregateConditionNode) EJBQLException(org.apache.cayenne.ejbql.EJBQLException) Persistent(org.apache.cayenne.Persistent) AttributeProperty(org.apache.cayenne.reflect.AttributeProperty) SimpleNode(org.apache.cayenne.ejbql.parser.SimpleNode) Map(java.util.Map)

Example 4 with EJBQLException

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

the class EJBQLDbPathTranslator method processIntermediatePathComponent.

private void processIntermediatePathComponent() {
    DbRelationship relationship = currentEntity.getRelationship(lastPathComponent);
    if (relationship == null) {
        throw new EJBQLException("Unknown relationship '" + lastPathComponent + "' for entity '" + currentEntity.getName() + "'");
    }
    this.currentEntity = (DbEntity) relationship.getTargetEntity();
}
Also used : DbRelationship(org.apache.cayenne.map.DbRelationship) EJBQLException(org.apache.cayenne.ejbql.EJBQLException)

Example 5 with EJBQLException

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

the class EJBQLDbPathTranslator method processTerminatingRelationship.

protected void processTerminatingRelationship(DbRelationship relationship) {
    if (relationship.isToMany()) {
        // use an outer join for to-many matches
        resolveJoin(false);
        DbEntity table = (DbEntity) relationship.getTargetEntity();
        String alias = this.lastAlias != null ? lastAlias : context.getTableAlias(idPath, context.getQuotingStrategy().quotedFullyQualifiedName(table));
        Collection<DbAttribute> pks = table.getPrimaryKeys();
        if (pks.size() == 1) {
            DbAttribute pk = pks.iterator().next();
            context.append(' ');
            if (isUsingAliases()) {
                context.append(alias).append('.');
            }
            context.append(context.getQuotingStrategy().quotedName(pk));
        } else {
            throw new EJBQLException("Multi-column PK to-many matches are not yet supported.");
        }
    } else {
        // match FK against the target object
        DbEntity table = (DbEntity) relationship.getSourceEntity();
        String alias = this.lastAlias != null ? lastAlias : context.getTableAlias(idPath, context.getQuotingStrategy().quotedFullyQualifiedName(table));
        List<DbJoin> joins = relationship.getJoins();
        if (joins.size() == 1) {
            DbJoin join = joins.get(0);
            context.append(' ');
            if (isUsingAliases()) {
                context.append(alias).append('.');
            }
            context.append(context.getQuotingStrategy().quotedName(join.getSource()));
        } else {
            Map<String, String> multiColumnMatch = new HashMap<>(joins.size() + 2);
            for (DbJoin join : joins) {
                String column = isUsingAliases() ? alias + "." + join.getSourceName() : join.getSourceName();
                multiColumnMatch.put(join.getTargetName(), column);
            }
            appendMultiColumnPath(EJBQLMultiColumnOperand.getPathOperand(context, multiColumnMatch));
        }
    }
}
Also used : DbEntity(org.apache.cayenne.map.DbEntity) HashMap(java.util.HashMap) DbAttribute(org.apache.cayenne.map.DbAttribute) EJBQLException(org.apache.cayenne.ejbql.EJBQLException) DbJoin(org.apache.cayenne.map.DbJoin)

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