Search in sources :

Example 6 with TableReferenceFactory

use of org.sql.generation.api.grammar.factories.TableReferenceFactory in project qi4j-sdk by Qi4j.

the class AbstractSQLQuerying method modifyFromClauseAndWhereClauseToGetValue.

// TODO refactor this monster of a method to something more understandable
protected Integer modifyFromClauseAndWhereClauseToGetValue(final QualifiedName qName, Object value, final Specification<Composite> predicate, final Boolean negationActive, final Integer currentTableIndex, final ModifiableInt maxTableIndex, final String columnName, final String collectionPath, final SQLVendor vendor, final BooleanBuilder whereClause, final BooleanBuilder afterWhere, final TableReferenceBuilder fromClause, final GroupByBuilder groupBy, final BooleanBuilder having, final List<QNameJoin> qNameJoins, Map<String, Object> variables, final List<Object> values, final List<Integer> valueSQLTypes) {
    if (value instanceof Variable) {
        value = variables.get(((Variable) value).variableName());
    }
    final String schemaName = this._state.schemaName().get();
    Integer result = 1;
    final BooleanFactory b = vendor.getBooleanFactory();
    final LiteralFactory l = vendor.getLiteralFactory();
    final ColumnsFactory c = vendor.getColumnsFactory();
    final QueryFactory q = vendor.getQueryFactory();
    final TableReferenceFactory t = vendor.getTableReferenceFactory();
    if (value instanceof Collection<?>) {
        // Collection
        Integer collectionIndex = 0;
        Boolean collectionIsSet = value instanceof Set<?>;
        Boolean topLevel = collectionPath.equals(DBNames.QNAME_TABLE_COLLECTION_PATH_TOP_LEVEL_NAME);
        String collTable = TABLE_NAME_PREFIX + currentTableIndex;
        String collCol = DBNames.QNAME_TABLE_COLLECTION_PATH_COLUMN_NAME;
        ColumnReferenceByName collColExp = c.colName(collTable, collCol);
        BooleanBuilder collectionCondition = b.booleanBuilder();
        if (topLevel && negationActive) {
            afterWhere.and(b.booleanBuilder(b.neq(collColExp, l.s(DBNames.QNAME_TABLE_COLLECTION_PATH_TOP_LEVEL_NAME))).or(b.isNull(collColExp)).createExpression());
        }
        Integer totalItemsProcessed = 0;
        for (Object item : (Collection<?>) value) {
            String path = collectionPath + DBNames.QNAME_TABLE_COLLECTION_PATH_SEPARATOR + (collectionIsSet ? "*{1,}" : collectionIndex);
            Boolean isCollection = (item instanceof Collection<?>);
            BooleanBuilder newWhere = b.booleanBuilder();
            if (!isCollection) {
                newWhere.reset(b.regexp(collColExp, l.s(path)));
            }
            totalItemsProcessed = totalItemsProcessed + modifyFromClauseAndWhereClauseToGetValue(qName, item, predicate, negationActive, currentTableIndex, maxTableIndex, columnName, path, vendor, newWhere, afterWhere, fromClause, groupBy, having, qNameJoins, variables, values, valueSQLTypes);
            ++collectionIndex;
            collectionCondition.or(newWhere.createExpression());
        }
        result = totalItemsProcessed;
        if (topLevel) {
            if (totalItemsProcessed == 0) {
                collectionCondition.and(b.isNotNull(collColExp)).and(b.eq(collColExp, l.l(DBNames.QNAME_TABLE_COLLECTION_PATH_TOP_LEVEL_NAME)));
            } else if (!negationActive) {
                groupBy.addGroupingElements(q.groupingElement(c.colName(TABLE_NAME_PREFIX + currentTableIndex, DBNames.ENTITY_TABLE_PK_COLUMN_NAME)));
                having.and(b.eq(l.func(SQLFunctions.COUNT, c.colName(TABLE_NAME_PREFIX + currentTableIndex, DBNames.QNAME_TABLE_VALUE_COLUMN_NAME)), l.n(totalItemsProcessed)));
            }
        }
        whereClause.and(collectionCondition.createExpression());
    } else if (value instanceof ValueComposite) {
        // @formatter:off
        for (Property<?> property : Qi4j.FUNCTION_COMPOSITE_INSTANCE_OF.map((ValueComposite) value).state().properties()) {
            Boolean qNameJoinDone = false;
            Integer sourceIndex = maxTableIndex.getInt();
            Integer targetIndex = sourceIndex + 1;
            for (QNameJoin join : qNameJoins) {
                if (join.getSourceQName().equals(qName)) {
                    sourceIndex = join.getSourceTableIndex();
                    if (join.getTargetQName().equals(spi.propertyDescriptorFor(property).qualifiedName())) {
                        // This join has already been done once
                        qNameJoinDone = true;
                        targetIndex = join.getTargetTableIndex();
                        break;
                    }
                }
            }
            if (!qNameJoinDone) {
                // @formatter:off
                QNameInfo info = _state.qNameInfos().get().get(spi.propertyDescriptorFor(property).qualifiedName());
                String prevTableName = TABLE_NAME_PREFIX + sourceIndex;
                String nextTableName = TABLE_NAME_PREFIX + targetIndex;
                fromClause.addQualifiedJoin(JoinType.LEFT_OUTER, t.table(t.tableName(schemaName, info.getTableName()), t.tableAlias(TABLE_NAME_PREFIX + targetIndex)), t.jc(b.booleanBuilder(b.eq(c.colName(prevTableName, DBNames.ALL_QNAMES_TABLE_PK_COLUMN_NAME), c.colName(nextTableName, DBNames.QNAME_TABLE_PARENT_QNAME_COLUMN_NAME))).and(b.eq(c.colName(prevTableName, DBNames.ENTITY_TABLE_PK_COLUMN_NAME), c.colName(nextTableName, DBNames.ENTITY_TABLE_PK_COLUMN_NAME))).createExpression()));
                // @formatter:on
                qNameJoins.add(new QNameJoin(qName, spi.propertyDescriptorFor(property).qualifiedName(), sourceIndex, targetIndex));
                maxTableIndex.setInt(maxTableIndex.getInt() + 1);
            }
            modifyFromClauseAndWhereClauseToGetValue(spi.propertyDescriptorFor(property).qualifiedName(), property.get(), predicate, negationActive, targetIndex, maxTableIndex, columnName, collectionPath, vendor, whereClause, afterWhere, fromClause, groupBy, having, qNameJoins, variables, values, valueSQLTypes);
        }
    // @formatter:on
    } else {
        // Primitive
        ColumnReferenceByName valueCol = c.colName(TABLE_NAME_PREFIX + currentTableIndex, columnName);
        if (value == null) {
            whereClause.and(b.isNull(valueCol));
        } else {
            Object dbValue = value;
            if (Enum.class.isAssignableFrom(value.getClass())) {
                dbValue = this._state.enumPKs().get().get(value.getClass().getName());
            }
            whereClause.and(b.and(b.isNotNull(valueCol), this.getOperator(predicate).getExpression(b, valueCol, l.param())));
            values.add(dbValue);
            valueSQLTypes.add(_typeHelper.getSQLType(value));
            _log.info(TABLE_NAME_PREFIX + currentTableIndex + "." + columnName + " is " + dbValue);
        }
    }
    return result;
}
Also used : QueryFactory(org.sql.generation.api.grammar.factories.QueryFactory) Variable(org.qi4j.api.query.grammar.Variable) ResultSet(java.sql.ResultSet) Set(java.util.Set) ColumnsFactory(org.sql.generation.api.grammar.factories.ColumnsFactory) ValueComposite(org.qi4j.api.value.ValueComposite) BooleanFactory(org.sql.generation.api.grammar.factories.BooleanFactory) LiteralFactory(org.sql.generation.api.grammar.factories.LiteralFactory) TableReferenceFactory(org.sql.generation.api.grammar.factories.TableReferenceFactory) ColumnReferenceByName(org.sql.generation.api.grammar.query.ColumnReferenceByName) BooleanBuilder(org.sql.generation.api.grammar.builders.booleans.BooleanBuilder) Collection(java.util.Collection) AccessibleObject(java.lang.reflect.AccessibleObject) QNameInfo(org.qi4j.index.sql.support.common.QNameInfo) Property(org.qi4j.api.property.Property)

Example 7 with TableReferenceFactory

use of org.sql.generation.api.grammar.factories.TableReferenceFactory in project qi4j-sdk by Qi4j.

the class AbstractSQLQuerying method selectAllEntitiesOfCorrectType.

protected QuerySpecificationBuilder selectAllEntitiesOfCorrectType(SQLVendor vendor, org.sql.generation.api.grammar.booleans.BooleanExpression entityTypeCondition) {
    TableReferenceFactory t = vendor.getTableReferenceFactory();
    String tableAlias = TABLE_NAME_PREFIX + "0";
    TableReferenceBuilder from = t.tableBuilder(t.table(t.tableName(this._state.schemaName().get(), DBNames.ENTITY_TABLE_NAME), t.tableAlias(tableAlias)));
    this.addTypeJoin(vendor, from, 0);
    QuerySpecificationBuilder query = this.getBuilderForPredicate(vendor, tableAlias);
    query.getFrom().addTableReferences(from);
    query.getWhere().reset(entityTypeCondition);
    return query;
}
Also used : TableReferenceFactory(org.sql.generation.api.grammar.factories.TableReferenceFactory) QuerySpecificationBuilder(org.sql.generation.api.grammar.builders.query.QuerySpecificationBuilder) TableReferenceBuilder(org.sql.generation.api.grammar.builders.query.TableReferenceBuilder)

Example 8 with TableReferenceFactory

use of org.sql.generation.api.grammar.factories.TableReferenceFactory in project qi4j-sdk by Qi4j.

the class AbstractSQLQuerying method traversePropertyPath.

protected Integer traversePropertyPath(PropertyFunction<?> reference, Integer lastTableIndex, Integer nextAvailableIndex, SQLVendor vendor, TableReferenceBuilder builder, JoinType joinStyle) {
    Stack<QualifiedName> qNameStack = new Stack<QualifiedName>();
    Stack<PropertyFunction<?>> refStack = new Stack<PropertyFunction<?>>();
    while (reference != null) {
        qNameStack.add(QualifiedName.fromAccessor(reference.accessor()));
        refStack.add(reference);
        if (reference.traversedProperty() == null && (reference.traversedAssociation() != null || reference.traversedManyAssociation() != null)) {
            Integer lastAssoTableIndex = this.traverseAssociationPath(new TraversedAssoOrManyAssoRef(reference), lastTableIndex, nextAvailableIndex, vendor, builder, joinStyle, true);
            if (lastAssoTableIndex > lastTableIndex) {
                lastTableIndex = lastAssoTableIndex;
                nextAvailableIndex = lastTableIndex + 1;
            }
        }
        reference = reference.traversedProperty();
    }
    PropertyFunction<?> prevRef = null;
    String schemaName = this._state.schemaName().get();
    TableReferenceFactory t = vendor.getTableReferenceFactory();
    BooleanFactory b = vendor.getBooleanFactory();
    ColumnsFactory c = vendor.getColumnsFactory();
    while (!qNameStack.isEmpty()) {
        QualifiedName qName = qNameStack.pop();
        PropertyFunction<?> ref = refStack.pop();
        if (!qName.type().equals(Identity.class.getName())) {
            QNameInfo info = this._state.qNameInfos().get().get(qName);
            if (info == null) {
                throw new InternalError("No qName info found for qName [" + qName + "].");
            }
            String prevTableAlias = TABLE_NAME_PREFIX + lastTableIndex;
            String nextTableAlias = TABLE_NAME_PREFIX + nextAvailableIndex;
            TableReferenceByName nextTable = t.table(t.tableName(schemaName, info.getTableName()), t.tableAlias(nextTableAlias));
            // @formatter:off
            if (prevRef == null) {
                builder.addQualifiedJoin(joinStyle, nextTable, t.jc(b.booleanBuilder(b.eq(c.colName(prevTableAlias, DBNames.ENTITY_TABLE_PK_COLUMN_NAME), c.colName(nextTableAlias, DBNames.ENTITY_TABLE_PK_COLUMN_NAME))).and(b.isNull(c.colName(nextTableAlias, DBNames.QNAME_TABLE_PARENT_QNAME_COLUMN_NAME))).createExpression()));
            } else {
                builder.addQualifiedJoin(joinStyle, nextTable, t.jc(b.booleanBuilder(b.eq(c.colName(prevTableAlias, DBNames.ALL_QNAMES_TABLE_PK_COLUMN_NAME), c.colName(nextTableAlias, DBNames.QNAME_TABLE_PARENT_QNAME_COLUMN_NAME))).and(b.eq(c.colName(prevTableAlias, DBNames.ENTITY_TABLE_PK_COLUMN_NAME), c.colName(nextTableAlias, DBNames.ENTITY_TABLE_PK_COLUMN_NAME))).createExpression()));
            }
            // @formatter:on
            lastTableIndex = nextAvailableIndex;
            ++nextAvailableIndex;
            prevRef = ref;
        }
    }
    return lastTableIndex;
}
Also used : TableReferenceByName(org.sql.generation.api.grammar.query.TableReferenceByName) QualifiedName(org.qi4j.api.common.QualifiedName) ColumnsFactory(org.sql.generation.api.grammar.factories.ColumnsFactory) BooleanFactory(org.sql.generation.api.grammar.factories.BooleanFactory) Stack(java.util.Stack) TableReferenceFactory(org.sql.generation.api.grammar.factories.TableReferenceFactory) PropertyFunction(org.qi4j.api.query.grammar.PropertyFunction) QNameInfo(org.qi4j.index.sql.support.common.QNameInfo)

Example 9 with TableReferenceFactory

use of org.sql.generation.api.grammar.factories.TableReferenceFactory in project qi4j-sdk by Qi4j.

the class AbstractSQLQuerying method addTypeJoin.

protected void addTypeJoin(SQLVendor vendor, TableReferenceBuilder from, int startingIndex) {
    TableReferenceFactory t = vendor.getTableReferenceFactory();
    BooleanFactory b = vendor.getBooleanFactory();
    ColumnsFactory c = vendor.getColumnsFactory();
    from.addQualifiedJoin(JoinType.INNER, t.table(t.tableName(this._state.schemaName().get(), DBNames.ENTITY_TYPES_JOIN_TABLE_NAME), t.tableAlias(TABLE_NAME_PREFIX + TYPE_TABLE_SUFFIX)), t.jc(b.eq(c.colName(TABLE_NAME_PREFIX + startingIndex, DBNames.ENTITY_TABLE_PK_COLUMN_NAME), c.colName(TABLE_NAME_PREFIX + TYPE_TABLE_SUFFIX, DBNames.ENTITY_TABLE_PK_COLUMN_NAME))));
}
Also used : TableReferenceFactory(org.sql.generation.api.grammar.factories.TableReferenceFactory) ColumnsFactory(org.sql.generation.api.grammar.factories.ColumnsFactory) BooleanFactory(org.sql.generation.api.grammar.factories.BooleanFactory)

Example 10 with TableReferenceFactory

use of org.sql.generation.api.grammar.factories.TableReferenceFactory in project qi4j-sdk by Qi4j.

the class GenericDatabaseExplorer method visitDatabaseTables.

public static void visitDatabaseTables(Connection connection, String catalogName, String schemaNamePattern, String tableNamePattern, DatabaseProcessor processor, SQLVendor sqlSyntaxVendor) throws SQLException {
    DatabaseMetaData metaData = connection.getMetaData();
    connection.setReadOnly(true);
    ResultSet rs = metaData.getTables(catalogName, schemaNamePattern, tableNamePattern, new String[] { "TABLE" });
    try {
        while (rs.next()) {
            String schemaName = rs.getString(2);
            try {
                processor.beginProcessSchemaInfo(schemaName);
                String tableName = rs.getString(3);
                String tableRemarks = rs.getString(5);
                try {
                    processor.beginProcessTableInfo(schemaName, tableName, tableRemarks);
                    List<ColumnInfo> colInfos = new ArrayList<ColumnInfo>();
                    ResultSet rsCols = metaData.getColumns(null, schemaName, tableName, null);
                    try {
                        while (rsCols.next()) {
                            String nullable = rsCols.getString(18);
                            colInfos.add(new ColumnInfo(rsCols.getString(4), rsCols.getInt(5), rsCols.getString(6), rsCols.getInt(7), rsCols.getInt(9), nullable.length() > 0 ? Boolean.toString(nullable.equals("YES")) : "unknown", rsCols.getString(13), rsCols.getString(12)));
                        }
                    } finally {
                        rsCols.close();
                    }
                    rsCols = metaData.getImportedKeys(null, schemaName, tableName);
                    Map<String, ForeignKeyInfo> fkInfos = new HashMap<String, ForeignKeyInfo>();
                    try {
                        while (rsCols.next()) {
                            fkInfos.put(// 
                            rsCols.getString(8), new ForeignKeyInfo(rsCols.getString(2), rsCols.getString(3), rsCols.getString(4), rsCols.getShort(10), rsCols.getShort(11), rsCols.getShort(14)));
                        }
                    } finally {
                        rsCols.close();
                    }
                    try {
                        processor.beginProcessColumns(schemaName, tableName, tableRemarks);
                        for (ColumnInfo colInfo : colInfos) {
                            try {
                                processor.beginProcessColumnInfo(schemaName, tableName, colInfo, fkInfos.get(colInfo._name));
                            } finally {
                                processor.endProcessColumnInfo(schemaName, tableName, colInfo, fkInfos.get(colInfo._name));
                            }
                        }
                    } finally {
                        processor.endProcessColumns(schemaName, tableName, tableRemarks);
                    }
                    QueryFactory q = sqlSyntaxVendor.getQueryFactory();
                    TableReferenceFactory t = sqlSyntaxVendor.getTableReferenceFactory();
                    QuerySpecificationBuilder builda = q.querySpecificationBuilder();
                    builda.getSelect().selectAll();
                    builda.getFrom().addTableReferences(t.tableBuilder(t.table(t.tableName(schemaName, tableName))));
                    String sql = sqlSyntaxVendor.toString(q.createQuery(builda.createExpression()));
                    Statement stmt = connection.createStatement();
                    ResultSet rowsRs = null;
                    try {
                        rowsRs = stmt.executeQuery(sql);
                        processor.beginProcessRows(schemaName, tableName, tableRemarks);
                        while (rowsRs.next()) {
                            Object[] rowContents = new Object[colInfos.size()];
                            for (Integer x = 0; x < rowContents.length; ++x) {
                                rowContents[x] = rowsRs.getObject(x + 1);
                            }
                            try {
                                processor.beginProcessRowInfo(schemaName, tableName, rowContents);
                            } finally {
                                processor.endProcessRowInfo(schemaName, tableName, rowContents);
                            }
                        }
                    } finally {
                        processor.endProcessRows(schemaName, tableName, tableRemarks);
                        if (rowsRs != null) {
                            rowsRs.close();
                        }
                        stmt.close();
                    }
                } finally {
                    processor.endProcessTableInfo(schemaName, tableName, tableRemarks);
                }
            } finally {
                processor.endProcessSchemaInfo(schemaName);
            }
        }
    } finally {
        SQLUtil.closeQuietly(rs);
    }
}
Also used : QueryFactory(org.sql.generation.api.grammar.factories.QueryFactory) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) QuerySpecificationBuilder(org.sql.generation.api.grammar.builders.query.QuerySpecificationBuilder) TableReferenceFactory(org.sql.generation.api.grammar.factories.TableReferenceFactory)

Aggregations

TableReferenceFactory (org.sql.generation.api.grammar.factories.TableReferenceFactory)21 LiteralFactory (org.sql.generation.api.grammar.factories.LiteralFactory)11 ColumnsFactory (org.sql.generation.api.grammar.factories.ColumnsFactory)10 ModificationFactory (org.sql.generation.api.grammar.factories.ModificationFactory)9 BooleanFactory (org.sql.generation.api.grammar.factories.BooleanFactory)8 QuerySpecificationBuilder (org.sql.generation.api.grammar.builders.query.QuerySpecificationBuilder)6 QueryFactory (org.sql.generation.api.grammar.factories.QueryFactory)6 SQLVendor (org.sql.generation.api.vendor.SQLVendor)5 Statement (java.sql.Statement)4 QNameInfo (org.qi4j.index.sql.support.common.QNameInfo)4 DefinitionFactory (org.sql.generation.api.grammar.factories.DefinitionFactory)4 BigInteger (java.math.BigInteger)3 PreparedStatement (java.sql.PreparedStatement)3 ResultSet (java.sql.ResultSet)3 ColumnSourceByValuesBuilder (org.sql.generation.api.grammar.builders.modification.ColumnSourceByValuesBuilder)3 InsertStatement (org.sql.generation.api.grammar.modification.InsertStatement)3 Stack (java.util.Stack)2 QualifiedName (org.qi4j.api.common.QualifiedName)2 QNameType (org.qi4j.index.sql.support.common.QNameInfo.QNameType)2 BooleanBuilder (org.sql.generation.api.grammar.builders.booleans.BooleanBuilder)2