Search in sources :

Example 11 with ColumnDescriptor

use of org.apache.cayenne.access.jdbc.ColumnDescriptor in project cayenne by apache.

the class DefaultSelectTranslatorIT method testBuildResultColumns2.

/**
 * Tests columns generated for an object query with joint prefetch.
 */
@Test
public void testBuildResultColumns2() throws Exception {
    SelectQuery q = new SelectQuery(Painting.class);
    q.addPrefetch(Painting.TO_ARTIST.joint());
    DefaultSelectTranslator tr = new DefaultSelectTranslator(q, dataNode.getAdapter(), dataNode.getEntityResolver());
    List<?> columns = tr.buildResultColumns();
    // assert root entity columns
    DbEntity entity = context.getEntityResolver().getDbEntity("PAINTING");
    for (final DbAttribute a : entity.getAttributes()) {
        ColumnDescriptor c = new ColumnDescriptor(a, "t0");
        assertTrue("No descriptor for " + a + ", columns: " + columns, columns.contains(c));
    }
    // assert joined columns
    DbEntity joined = context.getEntityResolver().getDbEntity("ARTIST");
    for (final DbAttribute a : joined.getAttributes()) {
        // skip ARTIST PK, it is joined from painting
        if (Artist.ARTIST_ID_PK_COLUMN.equals(a.getName())) {
            continue;
        }
        ColumnDescriptor c = new ColumnDescriptor(a, "t1");
        c.setDataRowKey("toArtist." + a.getName());
        assertTrue("No descriptor for " + a + ", columns: " + columns, columns.contains(c));
    }
}
Also used : SelectQuery(org.apache.cayenne.query.SelectQuery) DbEntity(org.apache.cayenne.map.DbEntity) ColumnDescriptor(org.apache.cayenne.access.jdbc.ColumnDescriptor) DbAttribute(org.apache.cayenne.map.DbAttribute) Test(org.junit.Test)

Example 12 with ColumnDescriptor

use of org.apache.cayenne.access.jdbc.ColumnDescriptor in project cayenne by apache.

the class DefaultSelectTranslatorIT method testBuildResultColumns1.

/**
 * Tests columns generated for a simple object query.
 */
@Test
public void testBuildResultColumns1() throws Exception {
    SelectQuery q = new SelectQuery(Painting.class);
    DefaultSelectTranslator tr = new DefaultSelectTranslator(q, dataNode.getAdapter(), dataNode.getEntityResolver());
    List<?> columns = tr.buildResultColumns();
    // all DbAttributes must be included
    DbEntity entity = context.getEntityResolver().getDbEntity("PAINTING");
    for (final DbAttribute a : entity.getAttributes()) {
        ColumnDescriptor c = new ColumnDescriptor(a, "t0");
        assertTrue("No descriptor for " + a + ", columns: " + columns, columns.contains(c));
    }
}
Also used : SelectQuery(org.apache.cayenne.query.SelectQuery) DbEntity(org.apache.cayenne.map.DbEntity) ColumnDescriptor(org.apache.cayenne.access.jdbc.ColumnDescriptor) DbAttribute(org.apache.cayenne.map.DbAttribute) Test(org.junit.Test)

Example 13 with ColumnDescriptor

use of org.apache.cayenne.access.jdbc.ColumnDescriptor in project cayenne by apache.

the class DefaultSelectTranslator method appendColumn.

private void appendColumn(List<ColumnDescriptor> columns, ObjAttribute objAttribute, DbAttribute attribute, Set<ColumnTracker> skipSet, String label, String alias) {
    if (alias == null) {
        alias = getCurrentAlias();
    }
    if (skipSet.add(new ColumnTracker(alias, attribute))) {
        ColumnDescriptor column = (objAttribute != null) ? new ColumnDescriptor(objAttribute, attribute, alias) : new ColumnDescriptor(attribute, alias);
        if (label != null) {
            column.setDataRowKey(label);
        }
        columns.add(column);
        // TODO: andrus, 5/7/2006 - replace 'columns' collection with this map, as it is redundant
        defaultAttributesByColumn.put(column, objAttribute);
    } else if (objAttribute != null) {
        // record ObjAttribute override
        for (ColumnDescriptor column : columns) {
            if (attribute.getName().equals(column.getName())) {
                if (attributeOverrides == null) {
                    attributeOverrides = new HashMap<>();
                }
                // kick out the original attribute
                ObjAttribute original = defaultAttributesByColumn.remove(column);
                if (original != null) {
                    attributeOverrides.put(original, column);
                }
                attributeOverrides.put(objAttribute, column);
                column.setJavaClass(Void.TYPE.getName());
                break;
            }
        }
    }
}
Also used : ObjAttribute(org.apache.cayenne.map.ObjAttribute) HashMap(java.util.HashMap) ColumnDescriptor(org.apache.cayenne.access.jdbc.ColumnDescriptor)

Example 14 with ColumnDescriptor

use of org.apache.cayenne.access.jdbc.ColumnDescriptor in project cayenne by apache.

the class DefaultSelectTranslator method appendOverriddenColumns.

/**
 * If query contains explicit column list, use only them
 */
<T> List<ColumnDescriptor> appendOverriddenColumns(List<ColumnDescriptor> columns, SelectQuery<T> query) {
    groupByColumns = new HashMap<>();
    QualifierTranslator qualifierTranslator = adapter.getQualifierTranslator(this);
    AccumulatingBindingListener bindingListener = new AccumulatingBindingListener();
    final String[] joinTableAliasForProperty = { null };
    // capture last alias for joined table, will use it to resolve object columns
    joinListener = () -> joinTableAliasForProperty[0] = getCurrentAlias();
    setAddBindingListener(bindingListener);
    for (Property<?> property : query.getColumns()) {
        joinTableAliasForProperty[0] = null;
        int expressionType = property.getExpression().getType();
        // forbid direct selection of toMany relationships columns
        if (property.getType() != null && (expressionType == Expression.OBJ_PATH || expressionType == Expression.DB_PATH) && (Collection.class.isAssignableFrom(property.getType()) || Map.class.isAssignableFrom(property.getType()))) {
            throw new CayenneRuntimeException("Can't directly select toMany relationship columns. " + "Either select it with aggregate functions like count() or with flat() function to select full related objects.");
        }
        // evaluate ObjPath with Persistent type as toOne relations and use it as full object
        boolean objectProperty = expressionType == Expression.FULL_OBJECT || (property.getType() != null && expressionType == Expression.OBJ_PATH && Persistent.class.isAssignableFrom(property.getType()));
        // Qualifier Translator in case of Object Columns have side effect -
        // it will create required joins, that we catch with listener above.
        // And we force created join alias for all columns of Object we select.
        qualifierTranslator.setQualifier(property.getExpression());
        qualifierTranslator.setForceJoinForRelations(objectProperty);
        StringBuilder builder = qualifierTranslator.appendPart(new StringBuilder());
        if (objectProperty) {
            // If we want full object, use appendQueryColumns method, to fully process class descriptor
            List<ColumnDescriptor> classColumns = new ArrayList<>();
            ObjEntity entity = entityResolver.getObjEntity(property.getType());
            if (getQueryMetadata().getPageSize() > 0) {
                appendIdColumns(classColumns, entity);
            } else {
                ClassDescriptor classDescriptor = entityResolver.getClassDescriptor(entity.getName());
                appendQueryColumns(classColumns, query, classDescriptor, joinTableAliasForProperty[0]);
            }
            for (ColumnDescriptor descriptor : classColumns) {
                columns.add(descriptor);
                groupByColumns.put(descriptor, Collections.<DbAttributeBinding>emptyList());
            }
        } else {
            // This property will go as scalar value
            String alias = property.getAlias();
            if (alias != null) {
                builder.append(" AS ").append(alias);
            }
            int type = getJdbcTypeForProperty(property);
            ColumnDescriptor descriptor;
            if (property.getType() != null) {
                descriptor = new ColumnDescriptor(builder.toString(), type, property.getType().getCanonicalName());
            } else {
                descriptor = new ColumnDescriptor(builder.toString(), type);
            }
            descriptor.setDataRowKey(alias);
            descriptor.setIsExpression(true);
            columns.add(descriptor);
            if (isAggregate(property)) {
                haveAggregate = true;
            } else {
                groupByColumns.put(descriptor, bindingListener.getBindings());
            }
            bindingListener.reset();
        }
    }
    setAddBindingListener(null);
    qualifierTranslator.setForceJoinForRelations(false);
    joinListener = null;
    return columns;
}
Also used : ClassDescriptor(org.apache.cayenne.reflect.ClassDescriptor) ColumnDescriptor(org.apache.cayenne.access.jdbc.ColumnDescriptor) CayenneRuntimeException(org.apache.cayenne.CayenneRuntimeException) ArrayList(java.util.ArrayList) Persistent(org.apache.cayenne.Persistent) ObjEntity(org.apache.cayenne.map.ObjEntity) Collection(java.util.Collection) Map(java.util.Map) HashMap(java.util.HashMap) DataMap(org.apache.cayenne.map.DataMap)

Example 15 with ColumnDescriptor

use of org.apache.cayenne.access.jdbc.ColumnDescriptor in project cayenne by apache.

the class DefaultSelectTranslator method doTranslate.

@Override
protected void doTranslate() {
    checkLimitAndJointPrefetch();
    DataMap dataMap = queryMetadata.getDataMap();
    JoinStack joins = getJoinStack();
    QuotingStrategy strategy = getAdapter().getQuotingStrategy();
    forcingDistinct = false;
    // build column list
    this.resultColumns = buildResultColumns();
    // build qualifier
    QualifierTranslator qualifierTranslator = adapter.getQualifierTranslator(this);
    StringBuilder whereQualifierBuffer = qualifierTranslator.appendPart(new StringBuilder());
    // build having qualifier
    Expression havingQualifier = getSelectQuery().getHavingQualifier();
    StringBuilder havingQualifierBuffer = null;
    if (havingQualifier != null) {
        haveAggregate = true;
        QualifierTranslator havingQualifierTranslator = adapter.getQualifierTranslator(this);
        havingQualifierTranslator.setQualifier(havingQualifier);
        havingQualifierBuffer = havingQualifierTranslator.appendPart(new StringBuilder());
    }
    if (!haveAggregate && groupByColumns != null) {
        // if no expression with aggregation function found
        // in select columns and there is no having clause
        groupByColumns.clear();
    }
    // build ORDER BY
    OrderingTranslator orderingTranslator = new OrderingTranslator(this);
    StringBuilder orderingBuffer = orderingTranslator.appendPart(new StringBuilder());
    // assemble
    StringBuilder queryBuf = new StringBuilder();
    queryBuf.append("SELECT ");
    // side effect: "suppressingDistinct" flag may end up being flipped here
    if (forcingDistinct || getSelectQuery().isDistinct()) {
        suppressingDistinct = queryMetadata.isSuppressingDistinct();
        if (!suppressingDistinct) {
            for (ColumnDescriptor column : resultColumns) {
                if (isUnsupportedForDistinct(column.getJdbcType())) {
                    suppressingDistinct = true;
                    break;
                }
            }
        }
        if (!suppressingDistinct) {
            queryBuf.append(buildDistinctStatement()).append(" ");
        }
    }
    // convert ColumnDescriptors to column names
    List<String> selectColumnExpList = new ArrayList<>();
    for (ColumnDescriptor column : resultColumns) {
        String fullName;
        if (column.isExpression()) {
            fullName = column.getName();
        } else {
            fullName = strategy.quotedIdentifier(dataMap, column.getNamePrefix(), column.getName());
        }
        selectColumnExpList.add(fullName);
    }
    // uses the DISTINCT modifier
    if (forcingDistinct || getSelectQuery().isDistinct()) {
        List<String> orderByColumnList = orderingTranslator.getOrderByColumnList();
        for (String orderByColumnExp : orderByColumnList) {
            // Convert to ColumnDescriptors??
            if (!selectColumnExpList.contains(orderByColumnExp)) {
                selectColumnExpList.add(orderByColumnExp);
            }
        }
    }
    appendSelectColumns(queryBuf, selectColumnExpList);
    // append from clause
    queryBuf.append(" FROM ");
    // append tables and joins
    joins.appendRootWithQuoteSqlIdentifiers(queryBuf, getQueryMetadata().getDbEntity());
    joins.appendJoins(queryBuf);
    joins.appendQualifier(whereQualifierBuffer, whereQualifierBuffer.length() == 0);
    // append qualifier
    if (whereQualifierBuffer.length() > 0) {
        queryBuf.append(" WHERE ");
        queryBuf.append(whereQualifierBuffer);
    }
    if (groupByColumns != null && !groupByColumns.isEmpty()) {
        queryBuf.append(" GROUP BY ");
        appendGroupByColumns(queryBuf, groupByColumns);
    }
    // append HAVING qualifier
    if (havingQualifierBuffer != null && havingQualifierBuffer.length() > 0) {
        queryBuf.append(" HAVING ");
        queryBuf.append(havingQualifierBuffer);
    }
    // append prebuilt ordering
    if (orderingBuffer.length() > 0) {
        queryBuf.append(" ORDER BY ").append(orderingBuffer);
    }
    if (!isSuppressingDistinct()) {
        appendLimitAndOffsetClauses(queryBuf);
    }
    this.sql = queryBuf.toString();
}
Also used : Expression(org.apache.cayenne.exp.Expression) ColumnDescriptor(org.apache.cayenne.access.jdbc.ColumnDescriptor) ArrayList(java.util.ArrayList) QuotingStrategy(org.apache.cayenne.dba.QuotingStrategy) DataMap(org.apache.cayenne.map.DataMap)

Aggregations

ColumnDescriptor (org.apache.cayenne.access.jdbc.ColumnDescriptor)17 DbAttribute (org.apache.cayenne.map.DbAttribute)5 Test (org.junit.Test)5 DataRow (org.apache.cayenne.DataRow)4 ArrayList (java.util.ArrayList)3 ClassDescriptor (org.apache.cayenne.reflect.ClassDescriptor)3 HashMap (java.util.HashMap)2 Map (java.util.Map)2 CayenneRuntimeException (org.apache.cayenne.CayenneRuntimeException)2 RowDescriptor (org.apache.cayenne.access.jdbc.RowDescriptor)2 SQLStatement (org.apache.cayenne.access.jdbc.SQLStatement)2 ExtendedType (org.apache.cayenne.access.types.ExtendedType)2 Expression (org.apache.cayenne.exp.Expression)2 DataMap (org.apache.cayenne.map.DataMap)2 DbEntity (org.apache.cayenne.map.DbEntity)2 ObjAttribute (org.apache.cayenne.map.ObjAttribute)2 ObjEntity (org.apache.cayenne.map.ObjEntity)2 SelectQuery (org.apache.cayenne.query.SelectQuery)2 ResultSet (java.sql.ResultSet)1 Collection (java.util.Collection)1