Search in sources :

Example 1 with MapTable

use of org.datanucleus.store.rdbms.table.MapTable in project datanucleus-rdbms by datanucleus.

the class QueryToSQLMapper method processFromClauseSubquery.

/**
 * Method to process a ClassExpression where it represents a subquery.
 * User defined the candidate of the subquery as an implied join to the outer query, for example "SELECT c FROM Customer c WHERE EXISTS (SELECT o FROM c.orders o ...)"
 * so this method will add the join(s) to the outer query.
 * @param clsExpr The ClassExpression
 * @param candSqlTbl Candidate SQL Table
 * @param mmgr MetaData Manager
 */
protected void processFromClauseSubquery(ClassExpression clsExpr, SQLTable candSqlTbl, MetaDataManager mmgr) {
    String[] tokens = StringUtils.split(clsExpr.getCandidateExpression(), ".");
    String leftAlias = tokens[0];
    SQLTableMapping outerSqlTblMapping = parentMapper.getSQLTableMappingForAlias(leftAlias);
    AbstractClassMetaData leftCmd = outerSqlTblMapping.cmd;
    // Get array of the left-right sides of this expression so we can work back from the subquery candidate
    AbstractMemberMetaData[] leftMmds = new AbstractMemberMetaData[tokens.length - 1];
    AbstractMemberMetaData[] rightMmds = new AbstractMemberMetaData[tokens.length - 1];
    for (int i = 0; i < tokens.length - 1; i++) {
        String joinedField = tokens[i + 1];
        AbstractMemberMetaData leftMmd = leftCmd.getMetaDataForMember(joinedField);
        AbstractMemberMetaData rightMmd = null;
        AbstractClassMetaData rightCmd = null;
        RelationType relationType = leftMmd.getRelationType(clr);
        if (RelationType.isBidirectional(relationType)) {
            // Take first possible
            rightMmd = leftMmd.getRelatedMemberMetaData(clr)[0];
            rightCmd = rightMmd.getAbstractClassMetaData();
        } else if (relationType == RelationType.ONE_TO_ONE_UNI) {
            rightCmd = mmgr.getMetaDataForClass(leftMmd.getType(), clr);
        } else if (relationType == RelationType.ONE_TO_MANY_UNI) {
            if (leftMmd.hasCollection()) {
                rightCmd = mmgr.getMetaDataForClass(leftMmd.getCollection().getElementType(), clr);
            } else if (leftMmd.hasMap()) {
                rightCmd = mmgr.getMetaDataForClass(leftMmd.getMap().getValueType(), clr);
            }
        } else {
            throw new NucleusUserException("Subquery has been specified with a candidate-expression that includes \"" + tokens[i] + "\" that isnt a relation field!!");
        }
        leftMmds[i] = leftMmd;
        rightMmds[i] = rightMmd;
        leftCmd = rightCmd;
    }
    // Work from subquery candidate back to outer query table, adding joins and where clause as appropriate
    SQLTable rSqlTbl = candSqlTbl;
    SQLTable outerSqlTbl = outerSqlTblMapping.table;
    JoinType joinType = JoinType.INNER_JOIN;
    for (int i = leftMmds.length - 1; i >= 0; i--) {
        AbstractMemberMetaData leftMmd = leftMmds[i];
        AbstractMemberMetaData rightMmd = rightMmds[i];
        DatastoreClass leftTbl = storeMgr.getDatastoreClass(leftMmd.getClassName(true), clr);
        SQLTable lSqlTbl = null;
        RelationType relationType = leftMmd.getRelationType(clr);
        if (relationType == RelationType.ONE_TO_ONE_UNI) {
            // 1-1 with FK in left table
            if (i == 0) {
                // Add where clause right table to outer table
                SQLExpression outerExpr = exprFactory.newExpression(outerSqlTbl.getSQLStatement(), outerSqlTbl, outerSqlTbl.getTable().getMemberMapping(leftMmd));
                SQLExpression rightExpr = exprFactory.newExpression(stmt, rSqlTbl, rSqlTbl.getTable().getIdMapping());
                stmt.whereAnd(outerExpr.eq(rightExpr), false);
            } else {
                // Join to left table
                JavaTypeMapping leftMapping = leftTbl.getMemberMapping(leftMmd);
                lSqlTbl = stmt.join(joinType, rSqlTbl, rSqlTbl.getTable().getIdMapping(), leftTbl, null, leftMapping, null, null, true);
            }
        } else if (relationType == RelationType.ONE_TO_ONE_BI) {
            if (leftMmd.getMappedBy() != null) {
                // 1-1 with FK in right table
                JavaTypeMapping rightMapping = rSqlTbl.getTable().getMemberMapping(rightMmd);
                if (i == 0) {
                    // Add where clause right table to outer table
                    SQLExpression outerExpr = exprFactory.newExpression(outerSqlTbl.getSQLStatement(), outerSqlTbl, outerSqlTbl.getTable().getIdMapping());
                    SQLExpression rightExpr = exprFactory.newExpression(stmt, rSqlTbl, rightMapping);
                    stmt.whereAnd(outerExpr.eq(rightExpr), false);
                } else {
                    // Join to left table
                    lSqlTbl = stmt.join(joinType, rSqlTbl, rightMapping, leftTbl, null, leftTbl.getIdMapping(), null, null, true);
                }
            } else {
                // 1-1 with FK in left table
                if (i == 0) {
                    // Add where clause right table to outer table
                    SQLExpression outerExpr = exprFactory.newExpression(outerSqlTbl.getSQLStatement(), outerSqlTbl, outerSqlTbl.getTable().getMemberMapping(leftMmd));
                    SQLExpression rightExpr = exprFactory.newExpression(stmt, rSqlTbl, rSqlTbl.getTable().getIdMapping());
                    stmt.whereAnd(outerExpr.eq(rightExpr), false);
                } else {
                    // Join to left table
                    lSqlTbl = stmt.join(joinType, rSqlTbl, rSqlTbl.getTable().getIdMapping(), leftTbl, null, leftTbl.getMemberMapping(leftMmd), null, null, true);
                }
            }
        } else if (relationType == RelationType.ONE_TO_MANY_UNI) {
            if (leftMmd.getJoinMetaData() != null || rightMmd.getJoinMetaData() != null) {
                // 1-N with join table to right table, so join from right to join table
                JoinTable joinTbl = (JoinTable) storeMgr.getTable(leftMmd);
                SQLTable joinSqlTbl = null;
                if (leftMmd.hasCollection()) {
                    joinSqlTbl = stmt.join(joinType, rSqlTbl, rSqlTbl.getTable().getIdMapping(), joinTbl, null, ((ElementContainerTable) joinTbl).getElementMapping(), null, null, true);
                } else if (leftMmd.hasMap()) {
                    joinSqlTbl = stmt.join(joinType, rSqlTbl, rSqlTbl.getTable().getIdMapping(), joinTbl, null, ((MapTable) joinTbl).getValueMapping(), null, null, true);
                }
                if (i == 0) {
                    // Add where clause join table (owner) to outer table (id)
                    SQLExpression outerExpr = exprFactory.newExpression(outerSqlTbl.getSQLStatement(), outerSqlTbl, outerSqlTbl.getTable().getIdMapping());
                    SQLExpression joinExpr = exprFactory.newExpression(stmt, joinSqlTbl, joinTbl.getOwnerMapping());
                    stmt.whereAnd(outerExpr.eq(joinExpr), false);
                } else {
                    // Join to left table
                    lSqlTbl = stmt.join(joinType, joinSqlTbl, joinTbl.getOwnerMapping(), leftTbl, null, leftTbl.getIdMapping(), null, null, true);
                }
            } else {
                // 1-N with FK in right table
                if (i == 0) {
                    // Add where clause right table to outer table
                    SQLExpression outerExpr = exprFactory.newExpression(outerSqlTbl.getSQLStatement(), outerSqlTbl, outerSqlTbl.getTable().getMemberMapping(leftMmd));
                    SQLExpression rightExpr = exprFactory.newExpression(stmt, rSqlTbl, rSqlTbl.getTable().getMemberMapping(rightMmd));
                    stmt.whereAnd(outerExpr.eq(rightExpr), false);
                } else {
                    // Join to left table
                    lSqlTbl = stmt.join(joinType, rSqlTbl, rSqlTbl.getTable().getMemberMapping(rightMmd), leftTbl, null, leftTbl.getIdMapping(), null, null, true);
                }
            }
        } else if (relationType == RelationType.ONE_TO_MANY_BI) {
            if (leftMmd.getJoinMetaData() != null || rightMmd.getJoinMetaData() != null) {
                // 1-N with join table to right table, so join from right to join table
                JoinTable joinTbl = (JoinTable) storeMgr.getTable(leftMmd);
                SQLTable joinSqlTbl = null;
                if (leftMmd.hasCollection()) {
                    joinSqlTbl = stmt.join(joinType, rSqlTbl, rSqlTbl.getTable().getIdMapping(), joinTbl, null, ((ElementContainerTable) joinTbl).getElementMapping(), null, null, true);
                } else if (leftMmd.hasMap()) {
                    joinSqlTbl = stmt.join(joinType, rSqlTbl, rSqlTbl.getTable().getIdMapping(), joinTbl, null, ((MapTable) joinTbl).getValueMapping(), null, null, true);
                }
                if (i == 0) {
                    // Add where clause join table (owner) to outer table (id)
                    SQLExpression outerExpr = exprFactory.newExpression(outerSqlTbl.getSQLStatement(), outerSqlTbl, outerSqlTbl.getTable().getIdMapping());
                    SQLExpression joinExpr = exprFactory.newExpression(stmt, joinSqlTbl, joinTbl.getOwnerMapping());
                    stmt.whereAnd(outerExpr.eq(joinExpr), false);
                } else {
                    // Join to left table
                    lSqlTbl = stmt.join(joinType, joinSqlTbl, joinTbl.getOwnerMapping(), leftTbl, null, leftTbl.getIdMapping(), null, null, true);
                }
            } else {
                // 1-N with FK in right table
                if (i == 0) {
                    // Add where clause right table to outer table
                    SQLExpression outerExpr = exprFactory.newExpression(outerSqlTbl.getSQLStatement(), outerSqlTbl, outerSqlTbl.getTable().getIdMapping());
                    SQLExpression rightExpr = exprFactory.newExpression(stmt, rSqlTbl, rSqlTbl.getTable().getMemberMapping(rightMmd));
                    stmt.whereAnd(outerExpr.eq(rightExpr), false);
                } else {
                    // Join to left table
                    lSqlTbl = stmt.join(joinType, rSqlTbl, rSqlTbl.getTable().getMemberMapping(rightMmd), leftTbl, null, leftTbl.getIdMapping(), null, null, true);
                }
            }
        } else if (relationType == RelationType.MANY_TO_ONE_BI) {
            if (leftMmd.getJoinMetaData() != null || rightMmd.getJoinMetaData() != null) {
                // 1-N with join table to right table, so join from right to join table
                JoinTable joinTbl = (JoinTable) storeMgr.getTable(leftMmd);
                SQLTable joinSqlTbl = stmt.join(joinType, rSqlTbl, rSqlTbl.getTable().getIdMapping(), joinTbl, null, joinTbl.getOwnerMapping(), null, null, true);
                if (leftMmd.hasCollection()) {
                    if (i == 0) {
                        // Add where clause join table (element) to outer table (id)
                        SQLExpression outerExpr = exprFactory.newExpression(outerSqlTbl.getSQLStatement(), outerSqlTbl, outerSqlTbl.getTable().getIdMapping());
                        SQLExpression joinExpr = exprFactory.newExpression(stmt, joinSqlTbl, ((ElementContainerTable) joinTbl).getElementMapping());
                        stmt.whereAnd(outerExpr.eq(joinExpr), false);
                    } else {
                        // Join to left table
                        lSqlTbl = stmt.join(joinType, joinSqlTbl, ((ElementContainerTable) joinTbl).getElementMapping(), leftTbl, null, leftTbl.getIdMapping(), null, null, true);
                    }
                } else if (leftMmd.hasMap()) {
                    if (i == 0) {
                        // Add where clause join table (value) to outer table (id)
                        SQLExpression outerExpr = exprFactory.newExpression(outerSqlTbl.getSQLStatement(), outerSqlTbl, outerSqlTbl.getTable().getIdMapping());
                        SQLExpression joinExpr = exprFactory.newExpression(stmt, joinSqlTbl, ((MapTable) joinTbl).getValueMapping());
                        stmt.whereAnd(outerExpr.eq(joinExpr), false);
                    } else {
                        // Join to left table
                        lSqlTbl = stmt.join(joinType, joinSqlTbl, ((MapTable) joinTbl).getValueMapping(), leftTbl, null, leftTbl.getIdMapping(), null, null, true);
                    }
                }
            } else {
                if (i == 0) {
                    // Add where clause right table to outer table
                    SQLExpression outerExpr = exprFactory.newExpression(outerSqlTbl.getSQLStatement(), outerSqlTbl, outerSqlTbl.getTable().getMemberMapping(leftMmd));
                    SQLExpression rightExpr = exprFactory.newExpression(stmt, rSqlTbl, rSqlTbl.getTable().getIdMapping());
                    stmt.whereAnd(outerExpr.eq(rightExpr), false);
                } else {
                    // Join to left table
                    lSqlTbl = stmt.join(joinType, rSqlTbl, rSqlTbl.getTable().getIdMapping(), leftTbl, null, leftTbl.getMemberMapping(leftMmd), null, null, true);
                }
            }
        }
        rSqlTbl = lSqlTbl;
    }
}
Also used : SQLExpression(org.datanucleus.store.rdbms.sql.expression.SQLExpression) JavaTypeMapping(org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping) NucleusUserException(org.datanucleus.exceptions.NucleusUserException) JoinType(org.datanucleus.store.rdbms.sql.SQLJoin.JoinType) AbstractClassMetaData(org.datanucleus.metadata.AbstractClassMetaData) MapTable(org.datanucleus.store.rdbms.table.MapTable) RelationType(org.datanucleus.metadata.RelationType) SQLTable(org.datanucleus.store.rdbms.sql.SQLTable) DatastoreClass(org.datanucleus.store.rdbms.table.DatastoreClass) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData) ElementContainerTable(org.datanucleus.store.rdbms.table.ElementContainerTable) JoinTable(org.datanucleus.store.rdbms.table.JoinTable)

Example 2 with MapTable

use of org.datanucleus.store.rdbms.table.MapTable in project datanucleus-rdbms by datanucleus.

the class QueryToSQLMapper method getSQLTableMappingForPrimaryExpression.

/**
 * Method to take in a PrimaryExpression and return the SQLTable mapping info that it signifies.
 * If the primary expression implies joining to other objects then adds the joins to the statement.
 * Only adds joins if necessary; so if there is a further component after the required join, or if
 * the "forceJoin" flag is set.
 * @param theStmt SQLStatement to use when looking for tables etc
 * @param exprName Name for an expression that this primary is relative to (optional)
 *                 If not specified then the tuples are relative to the candidate.
 *                 If specified then should have an entry in sqlTableByPrimary under this name.
 * @param primExpr The primary expression
 * @param forceJoin Whether to force a join if a relation member (or null if leaving to this method to decide)
 * @return The SQL table mapping information for the specified primary
 */
private SQLTableMapping getSQLTableMappingForPrimaryExpression(SQLStatement theStmt, String exprName, PrimaryExpression primExpr, Boolean forceJoin) {
    if (forceJoin == null && primExpr.getParent() != null) {
        if (primExpr.getParent().getOperator() == Expression.OP_IS || primExpr.getParent().getOperator() == Expression.OP_ISNOT) {
            // "instanceOf" needs to be in the table of the primary expression
            forceJoin = Boolean.TRUE;
        }
    }
    SQLTableMapping sqlMapping = null;
    List<String> tuples = primExpr.getTuples();
    // Find source object
    ListIterator<String> iter = tuples.listIterator();
    String first = tuples.get(0);
    boolean mapKey = false;
    boolean mapValue = false;
    if (first.endsWith("#KEY")) {
        first = first.substring(0, first.length() - 4);
        mapKey = true;
    } else if (first.endsWith("#VALUE")) {
        first = first.substring(0, first.length() - 6);
        mapValue = true;
    }
    String primaryName = null;
    if (exprName != null) {
        // Primary relative to some object etc
        sqlMapping = getSQLTableMappingForAlias(exprName);
        primaryName = exprName;
    } else {
        if (hasSQLTableMappingForAlias(first)) {
            // Start from a candidate (e.g JPQL alias)
            sqlMapping = getSQLTableMappingForAlias(first);
            primaryName = first;
            // Skip first tuple
            iter.next();
        }
        if (sqlMapping != null && first.equals(candidateAlias) && candidateCmd.getInheritanceMetaData().getStrategy() == InheritanceStrategy.COMPLETE_TABLE) {
            // Special case of using COMPLETE_TABLE for candidate and picked wrong table
            // TODO Use OPTION_CASE_INSENSITIVE
            SQLTable firstSqlTbl = stmt.getTable(first.toUpperCase());
            if (firstSqlTbl != null && firstSqlTbl.getTable() != sqlMapping.table.getTable()) {
                // Cached the SQLTableMapping for one of the other inherited classes, so create our own
                sqlMapping = new SQLTableMapping(firstSqlTbl, sqlMapping.cmd, firstSqlTbl.getTable().getIdMapping());
            }
        }
        if (sqlMapping == null) {
            if (parentMapper != null) {
                QueryToSQLMapper theParentMapper = parentMapper;
                while (theParentMapper != null) {
                    if (theParentMapper.hasSQLTableMappingForAlias(first)) {
                        // Try parent query
                        sqlMapping = theParentMapper.getSQLTableMappingForAlias(first);
                        primaryName = first;
                        // Skip first tuple
                        iter.next();
                        // This expression is for the parent statement so any joins need to go on that statement
                        theStmt = sqlMapping.table.getSQLStatement();
                        break;
                    }
                    theParentMapper = theParentMapper.parentMapper;
                }
            }
        }
        if (sqlMapping == null) {
            // Field of candidate, so use candidate
            sqlMapping = getSQLTableMappingForAlias(candidateAlias);
            primaryName = candidateAlias;
        }
    }
    AbstractClassMetaData cmd = sqlMapping.cmd;
    JavaTypeMapping mapping = sqlMapping.mapping;
    if (sqlMapping.mmd != null && (mapKey || mapValue)) {
        // Special case of MAP#KEY or MAP#VALUE, so navigate from the Map "table" to the key or value
        SQLTable sqlTbl = sqlMapping.table;
        AbstractMemberMetaData mmd = sqlMapping.mmd;
        MapMetaData mapmd = mmd.getMap();
        // Find the table forming the Map. This may be a join table, or the key or value depending on the type
        if (mapKey) {
            // Cater for all case possibilities of table name/alias
            // TODO Use OPTION_CASE_INSENSITIVE
            SQLTable mapSqlTbl = stmt.getTable(first + "_MAP");
            if (mapSqlTbl == null) {
                mapSqlTbl = stmt.getTable((first + "_MAP").toUpperCase());
                if (mapSqlTbl == null) {
                    mapSqlTbl = stmt.getTable((first + "_MAP").toLowerCase());
                }
            }
            if (mapSqlTbl != null) {
                sqlTbl = mapSqlTbl;
            }
        }
        if (mapmd.getMapType() == MapType.MAP_TYPE_JOIN) {
            if (sqlTbl.getTable() instanceof MapTable) {
                MapTable mapTable = (MapTable) sqlTbl.getTable();
                if (mapKey) {
                    cmd = mapmd.getKeyClassMetaData(clr);
                    if (!mapmd.isEmbeddedKey() && !mapmd.isSerializedKey()) {
                        // Join to key table
                        DatastoreClass keyTable = storeMgr.getDatastoreClass(mapmd.getKeyType(), clr);
                        sqlTbl = stmt.join(getDefaultJoinTypeForNavigation(), sqlMapping.table, mapTable.getKeyMapping(), keyTable, null, keyTable.getIdMapping(), null, null, true);
                        mapping = keyTable.getIdMapping();
                    } else {
                        mapping = mapTable.getKeyMapping();
                    }
                } else {
                    cmd = mapmd.getValueClassMetaData(clr);
                    if (!mapmd.isEmbeddedValue() && !mapmd.isSerializedValue()) {
                        // Join to value table
                        DatastoreClass valueTable = storeMgr.getDatastoreClass(mapmd.getValueType(), clr);
                        sqlTbl = stmt.join(getDefaultJoinTypeForNavigation(), sqlMapping.table, mapTable.getValueMapping(), valueTable, null, valueTable.getIdMapping(), null, null, true);
                        mapping = valueTable.getIdMapping();
                    } else {
                        mapping = mapTable.getValueMapping();
                    }
                }
            } else {
                // TODO Document exactly which situation this is
                if (!mapmd.isEmbeddedValue() && !mapmd.isSerializedValue()) {
                    mapping = sqlTbl.getTable().getIdMapping();
                }
            }
        } else if (mapmd.getMapType() == MapType.MAP_TYPE_KEY_IN_VALUE) {
            if (mapKey) {
                AbstractClassMetaData keyCmd = mapmd.getKeyClassMetaData(clr);
                String keyMappedBy = mmd.getKeyMetaData().getMappedBy();
                mapping = ((DatastoreClass) sqlTbl.getTable()).getMemberMapping(keyMappedBy);
                if (keyCmd != null) {
                    // Join to key table
                    DatastoreClass keyTable = storeMgr.getDatastoreClass(mapmd.getKeyType(), clr);
                    sqlTbl = stmt.join(getDefaultJoinTypeForNavigation(), sqlMapping.table, mapping, keyTable, null, keyTable.getIdMapping(), null, null, true);
                    mapping = keyTable.getIdMapping();
                }
            } else {
            }
        } else if (mapmd.getMapType() == MapType.MAP_TYPE_VALUE_IN_KEY) {
            // TODO We maybe already have the VALUE TABLE from the original join
            if (!mapKey) {
                AbstractClassMetaData valCmd = mapmd.getValueClassMetaData(clr);
                String valMappedBy = mmd.getValueMetaData().getMappedBy();
                mapping = ((DatastoreClass) sqlTbl.getTable()).getMemberMapping(valMappedBy);
                if (valCmd != null) {
                    // Join to value table
                    DatastoreClass valueTable = storeMgr.getDatastoreClass(mapmd.getValueType(), clr);
                    sqlTbl = stmt.join(getDefaultJoinTypeForNavigation(), sqlMapping.table, mapping, valueTable, null, valueTable.getIdMapping(), null, null, true);
                    mapping = valueTable.getIdMapping();
                }
            }
        }
        sqlMapping = new SQLTableMapping(sqlTbl, cmd, mapping);
    }
    while (iter.hasNext()) {
        String component = iter.next();
        // fully-qualified primary name
        primaryName += "." + component;
        // Derive SQLTableMapping for this component
        SQLTableMapping sqlMappingNew = getSQLTableMappingForAlias(primaryName);
        if (sqlMappingNew == null) {
            // Table not present for this primary
            AbstractMemberMetaData mmd = cmd.getMetaDataForMember(component);
            if (mmd == null) {
                // Not valid member name
                throw new NucleusUserException(Localiser.msg("021062", component, cmd.getFullClassName()));
            } else if (mmd.getPersistenceModifier() != FieldPersistenceModifier.PERSISTENT) {
                throw new NucleusUserException("Field " + mmd.getFullFieldName() + " is not marked as persistent so cannot be queried");
            }
            RelationType relationType = mmd.getRelationType(clr);
            // Find the table and the mapping for this field in the table
            SQLTable sqlTbl = null;
            if (mapping instanceof EmbeddedMapping) {
                // Embedded into the current table
                sqlTbl = sqlMapping.table;
                mapping = ((EmbeddedMapping) mapping).getJavaTypeMapping(component);
            } else if (mapping instanceof PersistableMapping && cmd.isEmbeddedOnly()) {
                // JPA EmbeddedId into current table
                sqlTbl = sqlMapping.table;
                JavaTypeMapping[] subMappings = ((PersistableMapping) mapping).getJavaTypeMapping();
                if (subMappings.length == 1 && subMappings[0] instanceof EmbeddedPCMapping) {
                    mapping = ((EmbeddedPCMapping) subMappings[0]).getJavaTypeMapping(component);
                } else {
                // TODO What situation is this?
                }
            } else {
                DatastoreClass table = storeMgr.getDatastoreClass(cmd.getFullClassName(), clr);
                if (table == null) {
                    if (cmd.getInheritanceMetaData().getStrategy() == InheritanceStrategy.COMPLETE_TABLE && candidateCmd.getFullClassName().equals(cmd.getFullClassName())) {
                        // Special case of a candidate having no table of its own and using COMPLETE_TABLE, so we use the candidate class for this statement (or UNION)
                        table = storeMgr.getDatastoreClass(stmt.getCandidateClassName(), clr);
                    }
                }
                if (table == null) {
                    AbstractClassMetaData[] subCmds = storeMgr.getClassesManagingTableForClass(cmd, clr);
                    if (subCmds.length == 1) {
                        table = storeMgr.getDatastoreClass(subCmds[0].getFullClassName(), clr);
                    } else {
                        // all of UNIONs, and this primary expression refers to a mapping in each of subclass tables
                        throw new NucleusUserException("Unable to find table for primary " + primaryName + " since the class " + cmd.getFullClassName() + " is managed in multiple tables");
                    }
                }
                if (table == null) {
                    throw new NucleusUserException("Unable to find table for primary " + primaryName + ". Table for class=" + cmd.getFullClassName() + " is null : is the field correct? or using some inheritance pattern?");
                }
                mapping = table.getMemberMapping(mmd);
                sqlTbl = SQLStatementHelper.getSQLTableForMappingOfTable(theStmt, sqlMapping.table, mapping);
            }
            if (relationType == RelationType.NONE) {
                sqlMappingNew = new SQLTableMapping(sqlTbl, cmd, mapping);
                cmd = sqlMappingNew.cmd;
                setSQLTableMappingForAlias(primaryName, sqlMappingNew);
            } else if (relationType == RelationType.ONE_TO_ONE_UNI || relationType == RelationType.ONE_TO_ONE_BI) {
                if (mmd.getMappedBy() != null) {
                    // FK in other table so join to that first
                    AbstractMemberMetaData relMmd = mmd.getRelatedMemberMetaData(clr)[0];
                    if (relMmd.getAbstractClassMetaData().isEmbeddedOnly()) {
                        // Member is embedded, so keep same SQL table mapping
                        sqlMappingNew = sqlMapping;
                        cmd = relMmd.getAbstractClassMetaData();
                    } else {
                        // Member is in own table, so move to that SQL table mapping
                        DatastoreClass relTable = storeMgr.getDatastoreClass(mmd.getTypeName(), clr);
                        JavaTypeMapping relMapping = relTable.getMemberMapping(relMmd);
                        // Join to related table unless we already have the join in place
                        sqlTbl = theStmt.getTable(relTable, primaryName);
                        if (sqlTbl == null) {
                            sqlTbl = SQLStatementHelper.addJoinForOneToOneRelation(theStmt, sqlMapping.table.getTable().getIdMapping(), sqlMapping.table, relMapping, relTable, null, null, primaryName, getDefaultJoinTypeForNavigation());
                        }
                        if (iter.hasNext()) {
                            sqlMappingNew = new SQLTableMapping(sqlTbl, relMmd.getAbstractClassMetaData(), relTable.getIdMapping());
                            cmd = sqlMappingNew.cmd;
                        } else {
                            sqlMappingNew = new SQLTableMapping(sqlTbl, cmd, relTable.getIdMapping());
                            cmd = sqlMappingNew.cmd;
                        }
                    }
                } else {
                    // FK is at this side
                    if (forceJoin == null) {
                        if (!iter.hasNext()) {
                            // Further component provided, so check if we should force a join to the other side
                            if (primExpr.getParent() != null && primExpr.getParent().getOperator() == Expression.OP_CAST) {
                                // Cast and not an interface field, so do a join to the table of the persistable object
                                if (mapping instanceof ReferenceMapping) {
                                // Don't join with interface field since represents multiple implementations
                                // and the cast will be a restrict on which implementation to join to
                                } else {
                                    AbstractClassMetaData relCmd = ec.getMetaDataManager().getMetaDataForClass(mmd.getType(), clr);
                                    if (relCmd != null && !relCmd.isEmbeddedOnly()) {
                                        DatastoreClass relTable = storeMgr.getDatastoreClass(relCmd.getFullClassName(), clr);
                                        if (relTable == null) {
                                        } else {
                                            forceJoin = Boolean.TRUE;
                                        }
                                    } else {
                                        forceJoin = Boolean.TRUE;
                                    }
                                }
                            }
                        } else {
                            // TODO Add optimisation to omit join if the FK is at this side and only selecting PK of the related object
                            if (iter.hasNext()) {
                                // Peek ahead to see if just selecting "id" of the related (i.e candidate.related.id with related FK in candidate table, so don't join)
                                String next = iter.next();
                                if (!iter.hasNext()) {
                                    AbstractClassMetaData relCmd = storeMgr.getMetaDataManager().getMetaDataForClass(mmd.getType(), clr);
                                    if (relCmd != null) {
                                        AbstractMemberMetaData mmdOfRelCmd = relCmd.getMetaDataForMember(next);
                                        if (mmdOfRelCmd != null && mmdOfRelCmd.isPrimaryKey() && relCmd.getNoOfPrimaryKeyMembers() == 1 && !storeMgr.getMetaDataManager().isClassPersistable(mmdOfRelCmd.getTypeName())) {
                                            // We have something like "a.b.id" and have the FK to the "B" table in the "A" table, so just refer to A.FK rather than joining and using B.ID
                                            NucleusLogger.QUERY.debug("Found implicit join to member=" + mmdOfRelCmd.getFullFieldName() + " which is PK of the other type but FK is in this table so avoiding the join");
                                            JavaTypeMapping subMapping = ((PersistableMapping) mapping).getJavaTypeMapping()[0];
                                            // Component mappings of a PersistableMapping sometimes don't have table set, so fix it
                                            subMapping.setTable(mapping.getTable());
                                            return new SQLTableMapping(sqlMapping.table, relCmd, subMapping);
                                        }
                                    }
                                }
                                iter.previous();
                            }
                        }
                    }
                    if (iter.hasNext() || Boolean.TRUE.equals(forceJoin)) {
                        AbstractClassMetaData relCmd = null;
                        JavaTypeMapping relMapping = null;
                        DatastoreClass relTable = null;
                        if (relationType == RelationType.ONE_TO_ONE_BI) {
                            AbstractMemberMetaData relMmd = mmd.getRelatedMemberMetaData(clr)[0];
                            relCmd = relMmd.getAbstractClassMetaData();
                        } else {
                            String typeName = mmd.isSingleCollection() ? mmd.getCollection().getElementType() : mmd.getTypeName();
                            relCmd = ec.getMetaDataManager().getMetaDataForClass(typeName, clr);
                        }
                        if (relCmd != null && relCmd.isEmbeddedOnly()) {
                            // Member is embedded so use same table but embedded mapping
                            sqlMappingNew = new SQLTableMapping(sqlTbl, relCmd, mapping);
                            cmd = relCmd;
                        } else {
                            // Member is in own table, so move to that SQL table mapping
                            relTable = storeMgr.getDatastoreClass(relCmd.getFullClassName(), clr);
                            if (relTable == null) {
                                // No table for the related type (subclass-table), so see if this class has a single subclass with its own table
                                Collection<String> relSubclassNames = storeMgr.getSubClassesForClass(relCmd.getFullClassName(), false, clr);
                                if (relSubclassNames != null && relSubclassNames.size() == 1) {
                                    String relSubclassName = relSubclassNames.iterator().next();
                                    relTable = storeMgr.getDatastoreClass(relSubclassName, clr);
                                    // TODO Cater for this having no table and next level yes etc
                                    if (relTable != null) {
                                        relCmd = ec.getMetaDataManager().getMetaDataForClass(relSubclassName, clr);
                                    }
                                }
                                if (relTable == null) {
                                    // No table as such, so likely using subclass-table at other side and we don't know where to join to
                                    throw new NucleusUserException("Reference to PrimaryExpression " + primExpr + " yet this needs to join relation " + mmd.getFullFieldName() + " and the other type has no table (subclass-table?). Maybe use a CAST to the appropriate subclass?");
                                }
                            }
                            relMapping = relTable.getIdMapping();
                            // Join to other table unless we already have the join in place
                            sqlTbl = theStmt.getTable(relTable, primaryName);
                            if (sqlTbl == null) {
                                sqlTbl = SQLStatementHelper.addJoinForOneToOneRelation(theStmt, mapping, sqlMapping.table, relMapping, relTable, null, null, primaryName, getDefaultJoinTypeForNavigation());
                            }
                            sqlMappingNew = new SQLTableMapping(sqlTbl, relCmd, relMapping);
                            cmd = sqlMappingNew.cmd;
                            setSQLTableMappingForAlias(primaryName, sqlMappingNew);
                        }
                    } else {
                        sqlMappingNew = new SQLTableMapping(sqlTbl, cmd, mapping);
                        cmd = sqlMappingNew.cmd;
                    // Don't register the SQLTableMapping for this alias since only using FK
                    }
                }
            } else if (relationType == RelationType.MANY_TO_ONE_BI) {
                AbstractMemberMetaData relMmd = mmd.getRelatedMemberMetaData(clr)[0];
                DatastoreClass relTable = storeMgr.getDatastoreClass(mmd.getTypeName(), clr);
                if (mmd.getJoinMetaData() != null || relMmd.getJoinMetaData() != null) {
                    // Has join table so use that
                    sqlTbl = theStmt.getTable(relTable, primaryName);
                    if (sqlTbl == null) {
                        // Join to the join table
                        CollectionTable joinTbl = (CollectionTable) storeMgr.getTable(relMmd);
                        JoinType defJoinType = getDefaultJoinTypeForNavigation();
                        if (defJoinType == JoinType.INNER_JOIN) {
                            SQLTable joinSqlTbl = theStmt.join(JoinType.INNER_JOIN, sqlMapping.table, sqlMapping.table.getTable().getIdMapping(), joinTbl, null, joinTbl.getElementMapping(), null, null, true);
                            sqlTbl = theStmt.join(JoinType.INNER_JOIN, joinSqlTbl, joinTbl.getOwnerMapping(), relTable, null, relTable.getIdMapping(), null, primaryName, true);
                        } else if (defJoinType == JoinType.LEFT_OUTER_JOIN || defJoinType == null) {
                            SQLTable joinSqlTbl = theStmt.join(JoinType.LEFT_OUTER_JOIN, sqlMapping.table, sqlMapping.table.getTable().getIdMapping(), joinTbl, null, joinTbl.getElementMapping(), null, null, true);
                            sqlTbl = theStmt.join(JoinType.LEFT_OUTER_JOIN, joinSqlTbl, joinTbl.getOwnerMapping(), relTable, null, relTable.getIdMapping(), null, primaryName, true);
                        }
                    }
                    sqlMappingNew = new SQLTableMapping(sqlTbl, relMmd.getAbstractClassMetaData(), relTable.getIdMapping());
                    cmd = sqlMappingNew.cmd;
                    setSQLTableMappingForAlias(primaryName, sqlMappingNew);
                } else {
                    // FK in this table
                    sqlTbl = theStmt.getTable(relTable, primaryName);
                    if (sqlTbl == null) {
                        if (mmd.getMappedBy() == null) {
                            // FK at this side so check for optimisations
                            if (iter.hasNext()) {
                                // Peek ahead to see if just selecting "id" of the related (i.e candidate.related.id with related FK in candidate table, so don't join)
                                String next = iter.next();
                                if (!iter.hasNext()) {
                                    AbstractClassMetaData relCmd = relMmd.getAbstractClassMetaData();
                                    AbstractMemberMetaData mmdOfRelCmd = relCmd.getMetaDataForMember(next);
                                    if (mmdOfRelCmd != null && mmdOfRelCmd.isPrimaryKey() && relCmd.getNoOfPrimaryKeyMembers() == 1 && !storeMgr.getMetaDataManager().isClassPersistable(mmdOfRelCmd.getTypeName())) {
                                        // We have something like "a.b.id" and have the FK to the "B" table in the "A" table, so just refer to A.FK rather than joining and using B.ID
                                        NucleusLogger.QUERY.debug("Found implicit join to member=" + mmdOfRelCmd.getFullFieldName() + " which is PK of the other type but FK is in this table so avoiding the join");
                                        JavaTypeMapping subMapping = ((PersistableMapping) mapping).getJavaTypeMapping()[0];
                                        // Component mappings of a PersistableMapping sometimes don't have table set, so fix it
                                        subMapping.setTable(mapping.getTable());
                                        return new SQLTableMapping(sqlMapping.table, relCmd, subMapping);
                                    }
                                }
                                iter.previous();
                            }
                        }
                        Operator op = (primExpr.getParent() != null ? primExpr.getParent().getOperator() : null);
                        if (!iter.hasNext() && (op == Expression.OP_EQ || op == Expression.OP_GT || op == Expression.OP_LT || op == Expression.OP_GTEQ || op == Expression.OP_LTEQ || op == Expression.OP_NOTEQ)) {
                            // Just return the FK mapping since in a "a.b == c.d" type expression and not needing to go further than the FK
                            sqlMappingNew = new SQLTableMapping(sqlMapping.table, relMmd.getAbstractClassMetaData(), mapping);
                        } else {
                            // Join to the related table
                            JoinType defJoinType = getDefaultJoinTypeForNavigation();
                            if (defJoinType == JoinType.INNER_JOIN) {
                                sqlTbl = theStmt.join(JoinType.INNER_JOIN, sqlMapping.table, mapping, relTable, null, relTable.getIdMapping(), null, primaryName, true);
                            } else if (defJoinType == JoinType.LEFT_OUTER_JOIN || defJoinType == null) {
                                sqlTbl = theStmt.join(JoinType.LEFT_OUTER_JOIN, sqlMapping.table, mapping, relTable, null, relTable.getIdMapping(), null, primaryName, true);
                            }
                            sqlMappingNew = new SQLTableMapping(sqlTbl, relMmd.getAbstractClassMetaData(), relTable.getIdMapping());
                            cmd = sqlMappingNew.cmd;
                            setSQLTableMappingForAlias(primaryName, sqlMappingNew);
                        }
                    } else {
                        sqlMappingNew = new SQLTableMapping(sqlTbl, relMmd.getAbstractClassMetaData(), relTable.getIdMapping());
                        cmd = sqlMappingNew.cmd;
                        setSQLTableMappingForAlias(primaryName, sqlMappingNew);
                    }
                }
            } else if (RelationType.isRelationMultiValued(relationType)) {
                // Can't reference further than a collection/map so just return its mapping here
                sqlMappingNew = new SQLTableMapping(sqlTbl, cmd, mapping);
                cmd = sqlMappingNew.cmd;
                setSQLTableMappingForAlias(primaryName, sqlMappingNew);
            }
        } else {
            cmd = sqlMappingNew.cmd;
        }
        sqlMapping = sqlMappingNew;
    }
    return sqlMapping;
}
Also used : Operator(org.datanucleus.query.expression.Expression.Operator) JavaTypeMapping(org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping) NucleusUserException(org.datanucleus.exceptions.NucleusUserException) EmbeddedPCMapping(org.datanucleus.store.rdbms.mapping.java.EmbeddedPCMapping) JoinType(org.datanucleus.store.rdbms.sql.SQLJoin.JoinType) MapMetaData(org.datanucleus.metadata.MapMetaData) AbstractClassMetaData(org.datanucleus.metadata.AbstractClassMetaData) MapTable(org.datanucleus.store.rdbms.table.MapTable) PersistableMapping(org.datanucleus.store.rdbms.mapping.java.PersistableMapping) ReferenceMapping(org.datanucleus.store.rdbms.mapping.java.ReferenceMapping) CollectionTable(org.datanucleus.store.rdbms.table.CollectionTable) EmbeddedMapping(org.datanucleus.store.rdbms.mapping.java.EmbeddedMapping) SQLTable(org.datanucleus.store.rdbms.sql.SQLTable) RelationType(org.datanucleus.metadata.RelationType) Collection(java.util.Collection) DatastoreClass(org.datanucleus.store.rdbms.table.DatastoreClass) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData)

Example 3 with MapTable

use of org.datanucleus.store.rdbms.table.MapTable in project datanucleus-rdbms by datanucleus.

the class MapContainsKeyMethod method containsAsSubquery.

/**
 * Method to return an expression for Map.containsKey using a subquery "EXISTS".
 * This is for use when there are "!contains" or "OR" operations in the filter.
 * Creates the following SQL,
 * <ul>
 * <li><b>Map using join table</b>
 * <pre>
 * SELECT 1 FROM JOIN_TBL A0_SUB
 * WHERE A0_SUB.JOIN_OWN_ID = A0.ID AND A0_SUB.JOIN_KEY_ID = {keyExpr}
 * </pre>
 * </li>
 * <li><b>Map with key stored in value</b>
 * <pre>
 * SELECT 1 FROM KEY_TABLE A0_SUB INNER JOIN VALUE_TBL B0 ON ...
 * WHERE B0.JOIN_OWN_ID = A0.ID AND A0_SUB.ID = {keyExpr}
 * </pre>
 * </li>
 * <li><b>Map of value stored in key</b>
 * <pre>
 * SELECT 1 FROM KEY_TABLE A0_SUB
 * WHERE A0_SUB.OWN_ID = A0.ID AND A0_SUB.ID = {keyExpr}
 * </pre>
 * </li>
 * </ul>
 * and returns a BooleanSubqueryExpression ("EXISTS (subquery)")
 * @param stmt SQLStatement
 * @param mapExpr Map expression
 * @param keyExpr Expression for the key
 * @return Contains expression
 */
protected SQLExpression containsAsSubquery(SQLStatement stmt, MapExpression mapExpr, SQLExpression keyExpr) {
    boolean keyIsUnbound = (keyExpr instanceof UnboundExpression);
    String varName = null;
    if (keyIsUnbound) {
        varName = ((UnboundExpression) keyExpr).getVariableName();
        NucleusLogger.QUERY.debug("map.containsKey binding unbound variable " + varName + " using SUBQUERY");
    // TODO What if the variable is declared as a subtype, handle this see CollectionContainsMethod
    }
    RDBMSStoreManager storeMgr = stmt.getRDBMSManager();
    SQLExpressionFactory exprFactory = stmt.getSQLExpressionFactory();
    ClassLoaderResolver clr = stmt.getQueryGenerator().getClassLoaderResolver();
    AbstractMemberMetaData mmd = mapExpr.getJavaTypeMapping().getMemberMetaData();
    AbstractClassMetaData keyCmd = mmd.getMap().getKeyClassMetaData(clr);
    MapTable joinTbl = (MapTable) storeMgr.getTable(mmd);
    SelectStatement subStmt = null;
    if (mmd.getMap().getMapType() == MapType.MAP_TYPE_JOIN) {
        // JoinTable Map
        if (keyCmd == null) {
            // Map<Non-PC, ?>
            subStmt = new SelectStatement(stmt, storeMgr, joinTbl, null, null);
            subStmt.setClassLoaderResolver(clr);
            JavaTypeMapping oneMapping = storeMgr.getMappingManager().getMapping(Integer.class);
            subStmt.select(exprFactory.newLiteral(subStmt, oneMapping, 1), null);
            // Restrict to map owner
            JavaTypeMapping ownerMapping = ((JoinTable) joinTbl).getOwnerMapping();
            SQLExpression ownerExpr = exprFactory.newExpression(subStmt, subStmt.getPrimaryTable(), ownerMapping);
            SQLExpression ownerIdExpr = exprFactory.newExpression(stmt, mapExpr.getSQLTable(), mapExpr.getSQLTable().getTable().getIdMapping());
            subStmt.whereAnd(ownerExpr.eq(ownerIdExpr), true);
            if (keyIsUnbound) {
                // Bind the variable in the QueryGenerator
                keyExpr = exprFactory.newExpression(subStmt, subStmt.getPrimaryTable(), joinTbl.getKeyMapping());
                stmt.getQueryGenerator().bindVariable(varName, null, keyExpr.getSQLTable(), keyExpr.getJavaTypeMapping());
            } else {
                // Add restrict to key
                SQLExpression elemIdExpr = exprFactory.newExpression(subStmt, subStmt.getPrimaryTable(), joinTbl.getKeyMapping());
                subStmt.whereAnd(elemIdExpr.eq(keyExpr), true);
            }
        } else {
            // Map<PC, ?>
            DatastoreClass keyTbl = storeMgr.getDatastoreClass(mmd.getMap().getKeyType(), clr);
            subStmt = new SelectStatement(stmt, storeMgr, keyTbl, null, null);
            subStmt.setClassLoaderResolver(clr);
            JavaTypeMapping oneMapping = storeMgr.getMappingManager().getMapping(Integer.class);
            subStmt.select(exprFactory.newLiteral(subStmt, oneMapping, 1), null);
            // Join to join table
            SQLTable joinSqlTbl = subStmt.join(JoinType.INNER_JOIN, subStmt.getPrimaryTable(), keyTbl.getIdMapping(), joinTbl, null, joinTbl.getKeyMapping(), null, null, true);
            // Restrict to map owner
            JavaTypeMapping ownerMapping = joinTbl.getOwnerMapping();
            SQLExpression ownerExpr = exprFactory.newExpression(subStmt, joinSqlTbl, ownerMapping);
            SQLExpression ownerIdExpr = exprFactory.newExpression(stmt, mapExpr.getSQLTable(), mapExpr.getSQLTable().getTable().getIdMapping());
            subStmt.whereAnd(ownerExpr.eq(ownerIdExpr), true);
            if (keyIsUnbound) {
                // Bind the variable in the QueryGenerator
                keyExpr = exprFactory.newExpression(subStmt, subStmt.getPrimaryTable(), keyTbl.getIdMapping());
                stmt.getQueryGenerator().bindVariable(varName, keyCmd, keyExpr.getSQLTable(), keyExpr.getJavaTypeMapping());
            } else {
                // Add restrict to key
                SQLExpression keyIdExpr = exprFactory.newExpression(subStmt, subStmt.getPrimaryTable(), keyTbl.getIdMapping());
                subStmt.whereAnd(keyIdExpr.eq(keyExpr), true);
            }
        }
    } else if (mmd.getMap().getMapType() == MapType.MAP_TYPE_KEY_IN_VALUE) {
        // Key stored in value table
        AbstractClassMetaData valCmd = mmd.getMap().getValueClassMetaData(clr);
        DatastoreClass valTbl = storeMgr.getDatastoreClass(mmd.getMap().getValueType(), clr);
        JavaTypeMapping ownerMapping = null;
        if (mmd.getMappedBy() != null) {
            ownerMapping = valTbl.getMemberMapping(valCmd.getMetaDataForMember(mmd.getMappedBy()));
        } else {
            ownerMapping = valTbl.getExternalMapping(mmd, MappingType.EXTERNAL_FK);
        }
        AbstractMemberMetaData valKeyMmd = valCmd.getMetaDataForMember(mmd.getKeyMetaData().getMappedBy());
        if (keyCmd == null) {
            subStmt = new SelectStatement(stmt, storeMgr, valTbl, null, null);
            subStmt.setClassLoaderResolver(clr);
            JavaTypeMapping oneMapping = storeMgr.getMappingManager().getMapping(Integer.class);
            subStmt.select(exprFactory.newLiteral(subStmt, oneMapping, 1), null);
            // Restrict to map owner (on value table)
            SQLExpression ownerExpr = exprFactory.newExpression(subStmt, subStmt.getPrimaryTable(), ownerMapping);
            SQLExpression ownerIdExpr = exprFactory.newExpression(stmt, mapExpr.getSQLTable(), mapExpr.getSQLTable().getTable().getIdMapping());
            subStmt.whereAnd(ownerExpr.eq(ownerIdExpr), true);
            if (keyIsUnbound) {
                // Bind the variable in the QueryGenerator
                keyExpr = exprFactory.newExpression(subStmt, subStmt.getPrimaryTable(), valTbl.getMemberMapping(valKeyMmd));
                stmt.getQueryGenerator().bindVariable(varName, null, keyExpr.getSQLTable(), keyExpr.getJavaTypeMapping());
            } else {
                // Add restrict to key
                JavaTypeMapping keyMapping = valTbl.getMemberMapping(valKeyMmd);
                SQLExpression elemIdExpr = exprFactory.newExpression(subStmt, subStmt.getPrimaryTable(), keyMapping);
                subStmt.whereAnd(elemIdExpr.eq(keyExpr), true);
            }
        } else {
            DatastoreClass keyTbl = storeMgr.getDatastoreClass(mmd.getMap().getKeyType(), clr);
            subStmt = new SelectStatement(stmt, storeMgr, keyTbl, null, null);
            subStmt.setClassLoaderResolver(clr);
            JavaTypeMapping oneMapping = storeMgr.getMappingManager().getMapping(Integer.class);
            subStmt.select(exprFactory.newLiteral(subStmt, oneMapping, 1), null);
            // Join to value table
            SQLTable valSqlTbl = subStmt.join(JoinType.INNER_JOIN, subStmt.getPrimaryTable(), keyTbl.getIdMapping(), valTbl, null, valTbl.getMemberMapping(valKeyMmd), null, null, true);
            // Restrict to map owner (on value table)
            SQLExpression ownerExpr = exprFactory.newExpression(subStmt, valSqlTbl, ownerMapping);
            SQLExpression ownerIdExpr = exprFactory.newExpression(stmt, mapExpr.getSQLTable(), mapExpr.getSQLTable().getTable().getIdMapping());
            subStmt.whereAnd(ownerExpr.eq(ownerIdExpr), true);
            if (keyIsUnbound) {
                // Bind the variable in the QueryGenerator
                keyExpr = exprFactory.newExpression(subStmt, subStmt.getPrimaryTable(), keyTbl.getIdMapping());
                stmt.getQueryGenerator().bindVariable(varName, keyCmd, keyExpr.getSQLTable(), keyExpr.getJavaTypeMapping());
            } else {
                // Add restrict to key
                SQLExpression keyIdExpr = exprFactory.newExpression(subStmt, subStmt.getPrimaryTable(), keyTbl.getIdMapping());
                subStmt.whereAnd(keyIdExpr.eq(keyExpr), true);
            }
        }
    } else if (mmd.getMap().getMapType() == MapType.MAP_TYPE_VALUE_IN_KEY) {
        DatastoreClass keyTbl = storeMgr.getDatastoreClass(mmd.getMap().getKeyType(), clr);
        JavaTypeMapping ownerMapping = null;
        if (mmd.getMappedBy() != null) {
            ownerMapping = keyTbl.getMemberMapping(keyCmd.getMetaDataForMember(mmd.getMappedBy()));
        } else {
            ownerMapping = keyTbl.getExternalMapping(mmd, MappingType.EXTERNAL_FK);
        }
        subStmt = new SelectStatement(stmt, storeMgr, keyTbl, null, null);
        subStmt.setClassLoaderResolver(clr);
        JavaTypeMapping oneMapping = storeMgr.getMappingManager().getMapping(Integer.class);
        subStmt.select(exprFactory.newLiteral(subStmt, oneMapping, 1), null);
        // Restrict to map owner (on key table)
        SQLExpression ownerExpr = exprFactory.newExpression(subStmt, subStmt.getPrimaryTable(), ownerMapping);
        SQLExpression ownerIdExpr = exprFactory.newExpression(stmt, mapExpr.getSQLTable(), mapExpr.getSQLTable().getTable().getIdMapping());
        subStmt.whereAnd(ownerExpr.eq(ownerIdExpr), true);
        if (keyIsUnbound) {
            // Bind the variable in the QueryGenerator
            keyExpr = exprFactory.newExpression(subStmt, subStmt.getPrimaryTable(), keyTbl.getIdMapping());
            stmt.getQueryGenerator().bindVariable(varName, keyCmd, keyExpr.getSQLTable(), keyExpr.getJavaTypeMapping());
        } else {
            // Add restrict to key
            JavaTypeMapping keyMapping = keyTbl.getIdMapping();
            SQLExpression keyIdExpr = exprFactory.newExpression(subStmt, subStmt.getPrimaryTable(), keyMapping);
            subStmt.whereAnd(keyIdExpr.eq(keyExpr), true);
        }
    }
    return new BooleanSubqueryExpression(stmt, "EXISTS", subStmt);
}
Also used : SQLExpressionFactory(org.datanucleus.store.rdbms.sql.expression.SQLExpressionFactory) SQLExpression(org.datanucleus.store.rdbms.sql.expression.SQLExpression) JavaTypeMapping(org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping) ClassLoaderResolver(org.datanucleus.ClassLoaderResolver) UnboundExpression(org.datanucleus.store.rdbms.sql.expression.UnboundExpression) AbstractClassMetaData(org.datanucleus.metadata.AbstractClassMetaData) RDBMSStoreManager(org.datanucleus.store.rdbms.RDBMSStoreManager) MapTable(org.datanucleus.store.rdbms.table.MapTable) SelectStatement(org.datanucleus.store.rdbms.sql.SelectStatement) BooleanSubqueryExpression(org.datanucleus.store.rdbms.sql.expression.BooleanSubqueryExpression) SQLTable(org.datanucleus.store.rdbms.sql.SQLTable) DatastoreClass(org.datanucleus.store.rdbms.table.DatastoreClass) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData) JoinTable(org.datanucleus.store.rdbms.table.JoinTable)

Example 4 with MapTable

use of org.datanucleus.store.rdbms.table.MapTable in project datanucleus-rdbms by datanucleus.

the class MapContainsValueMethod method containsAsSubquery.

/**
 * Method to return an expression for Map.containsValue using a subquery "EXISTS".
 * This is for use when there are "!contains" or "OR" operations in the filter.
 * Creates the following SQL,
 * <ul>
 * <li><b>Map using join table</b>
 * <pre>
 * SELECT 1 FROM JOIN_TBL A0_SUB
 * WHERE A0_SUB.JOIN_OWN_ID = A0.ID AND A0_SUB.JOIN_VAL_ID = {valExpr}
 * </pre>
 * </li>
 * <li><b>Map with key stored in value</b>
 * <pre>
 * SELECT 1 FROM VAL_TABLE A0_SUB INNER JOIN KEY_TBL B0 ON ...
 * WHERE B0.JOIN_OWN_ID = A0.ID AND A0_SUB.ID = {valExpr}
 * </pre>
 * </li>
 * <li><b>Map of value stored in key</b>
 * <pre>
 * SELECT 1 FROM VAL_TABLE A0_SUB
 * WHERE A0_SUB.OWN_ID = A0.ID AND A0_SUB.ID = {valExpr}
 * </pre>
 * </li>
 * </ul>
 * and returns a BooleanSubqueryExpression ("EXISTS (subquery)")
 * @param stmt SQLStatement
 * @param mapExpr Map expression
 * @param valExpr Expression for the value
 * @return Contains expression
 */
protected SQLExpression containsAsSubquery(SQLStatement stmt, MapExpression mapExpr, SQLExpression valExpr) {
    boolean valIsUnbound = (valExpr instanceof UnboundExpression);
    String varName = null;
    if (valIsUnbound) {
        varName = ((UnboundExpression) valExpr).getVariableName();
        NucleusLogger.QUERY.debug("map.containsValue binding unbound variable " + varName + " using SUBQUERY");
    // TODO What if the variable is declared as a subtype, handle this see CollectionContainsMethod
    }
    RDBMSStoreManager storeMgr = stmt.getRDBMSManager();
    SQLExpressionFactory exprFactory = stmt.getSQLExpressionFactory();
    ClassLoaderResolver clr = stmt.getQueryGenerator().getClassLoaderResolver();
    AbstractMemberMetaData mmd = mapExpr.getJavaTypeMapping().getMemberMetaData();
    AbstractClassMetaData valCmd = mmd.getMap().getValueClassMetaData(clr);
    MapTable joinTbl = (MapTable) storeMgr.getTable(mmd);
    SelectStatement subStmt = null;
    if (mmd.getMap().getMapType() == MapType.MAP_TYPE_JOIN) {
        // JoinTable Map
        if (valCmd == null) {
            // Map<?, Non-PC>
            subStmt = new SelectStatement(stmt, storeMgr, joinTbl, null, null);
            subStmt.setClassLoaderResolver(clr);
            JavaTypeMapping oneMapping = storeMgr.getMappingManager().getMapping(Integer.class);
            subStmt.select(exprFactory.newLiteral(subStmt, oneMapping, 1), null);
            // Restrict to map owner
            JavaTypeMapping ownerMapping = ((JoinTable) joinTbl).getOwnerMapping();
            SQLExpression ownerExpr = exprFactory.newExpression(subStmt, subStmt.getPrimaryTable(), ownerMapping);
            SQLExpression ownerIdExpr = exprFactory.newExpression(stmt, mapExpr.getSQLTable(), mapExpr.getSQLTable().getTable().getIdMapping());
            subStmt.whereAnd(ownerExpr.eq(ownerIdExpr), true);
            if (valIsUnbound) {
                // Bind the variable in the QueryGenerator
                valExpr = exprFactory.newExpression(subStmt, subStmt.getPrimaryTable(), joinTbl.getValueMapping());
                stmt.getQueryGenerator().bindVariable(varName, null, valExpr.getSQLTable(), valExpr.getJavaTypeMapping());
            } else {
                // Add restrict to value
                SQLExpression valIdExpr = exprFactory.newExpression(subStmt, subStmt.getPrimaryTable(), joinTbl.getValueMapping());
                subStmt.whereAnd(valIdExpr.eq(valExpr), true);
            }
        } else {
            // Map<?, PC>
            DatastoreClass valTbl = storeMgr.getDatastoreClass(mmd.getMap().getValueType(), clr);
            subStmt = new SelectStatement(stmt, storeMgr, valTbl, null, null);
            subStmt.setClassLoaderResolver(clr);
            JavaTypeMapping oneMapping = storeMgr.getMappingManager().getMapping(Integer.class);
            subStmt.select(exprFactory.newLiteral(subStmt, oneMapping, 1), null);
            // Join to join table
            SQLTable joinSqlTbl = subStmt.join(JoinType.INNER_JOIN, subStmt.getPrimaryTable(), valTbl.getIdMapping(), joinTbl, null, joinTbl.getValueMapping(), null, null, true);
            // Restrict to map owner
            JavaTypeMapping ownerMapping = joinTbl.getOwnerMapping();
            SQLExpression ownerExpr = exprFactory.newExpression(subStmt, joinSqlTbl, ownerMapping);
            SQLExpression ownerIdExpr = exprFactory.newExpression(stmt, mapExpr.getSQLTable(), mapExpr.getSQLTable().getTable().getIdMapping());
            subStmt.whereAnd(ownerExpr.eq(ownerIdExpr), true);
            if (valIsUnbound) {
                // Bind the variable in the QueryGenerator
                valExpr = exprFactory.newExpression(subStmt, subStmt.getPrimaryTable(), valTbl.getIdMapping());
                stmt.getQueryGenerator().bindVariable(varName, valCmd, valExpr.getSQLTable(), valExpr.getJavaTypeMapping());
            } else {
                // Add restrict to value
                SQLExpression valIdExpr = exprFactory.newExpression(subStmt, subStmt.getPrimaryTable(), valTbl.getIdMapping());
                subStmt.whereAnd(valIdExpr.eq(valExpr), true);
            }
        }
    } else if (mmd.getMap().getMapType() == MapType.MAP_TYPE_KEY_IN_VALUE) {
        // Key stored in value table
        DatastoreClass valTbl = storeMgr.getDatastoreClass(mmd.getMap().getValueType(), clr);
        JavaTypeMapping ownerMapping = null;
        if (mmd.getMappedBy() != null) {
            ownerMapping = valTbl.getMemberMapping(valCmd.getMetaDataForMember(mmd.getMappedBy()));
        } else {
            ownerMapping = valTbl.getExternalMapping(mmd, MappingType.EXTERNAL_FK);
        }
        subStmt = new SelectStatement(stmt, storeMgr, valTbl, null, null);
        subStmt.setClassLoaderResolver(clr);
        JavaTypeMapping oneMapping = storeMgr.getMappingManager().getMapping(Integer.class);
        subStmt.select(exprFactory.newLiteral(subStmt, oneMapping, 1), null);
        // Restrict to map owner (on value table)
        SQLExpression ownerExpr = exprFactory.newExpression(subStmt, subStmt.getPrimaryTable(), ownerMapping);
        SQLExpression ownerIdExpr = exprFactory.newExpression(stmt, mapExpr.getSQLTable(), mapExpr.getSQLTable().getTable().getIdMapping());
        subStmt.whereAnd(ownerExpr.eq(ownerIdExpr), true);
        if (valIsUnbound) {
            // Bind the variable in the QueryGenerator
            valExpr = exprFactory.newExpression(subStmt, subStmt.getPrimaryTable(), valTbl.getIdMapping());
            stmt.getQueryGenerator().bindVariable(varName, valCmd, valExpr.getSQLTable(), valExpr.getJavaTypeMapping());
        } else {
            // Add restrict to value
            JavaTypeMapping valMapping = valTbl.getIdMapping();
            SQLExpression valIdExpr = exprFactory.newExpression(subStmt, subStmt.getPrimaryTable(), valMapping);
            subStmt.whereAnd(valIdExpr.eq(valExpr), true);
        }
    } else if (mmd.getMap().getMapType() == MapType.MAP_TYPE_VALUE_IN_KEY) {
        AbstractClassMetaData keyCmd = mmd.getMap().getKeyClassMetaData(clr);
        DatastoreClass keyTbl = storeMgr.getDatastoreClass(mmd.getMap().getKeyType(), clr);
        JavaTypeMapping ownerMapping = null;
        if (mmd.getMappedBy() != null) {
            ownerMapping = keyTbl.getMemberMapping(keyCmd.getMetaDataForMember(mmd.getMappedBy()));
        } else {
            ownerMapping = keyTbl.getExternalMapping(mmd, MappingType.EXTERNAL_FK);
        }
        AbstractMemberMetaData keyValMmd = keyCmd.getMetaDataForMember(mmd.getValueMetaData().getMappedBy());
        if (valCmd == null) {
            subStmt = new SelectStatement(stmt, storeMgr, keyTbl, null, null);
            subStmt.setClassLoaderResolver(clr);
            JavaTypeMapping oneMapping = storeMgr.getMappingManager().getMapping(Integer.class);
            subStmt.select(exprFactory.newLiteral(subStmt, oneMapping, 1), null);
            // Restrict to map owner (on key table)
            SQLExpression ownerExpr = exprFactory.newExpression(subStmt, subStmt.getPrimaryTable(), ownerMapping);
            SQLExpression ownerIdExpr = exprFactory.newExpression(stmt, mapExpr.getSQLTable(), mapExpr.getSQLTable().getTable().getIdMapping());
            subStmt.whereAnd(ownerExpr.eq(ownerIdExpr), true);
            if (valIsUnbound) {
                // Bind the variable in the QueryGenerator
                valExpr = exprFactory.newExpression(subStmt, subStmt.getPrimaryTable(), keyTbl.getMemberMapping(keyValMmd));
                stmt.getQueryGenerator().bindVariable(varName, null, valExpr.getSQLTable(), valExpr.getJavaTypeMapping());
            } else {
                // Add restrict to value
                JavaTypeMapping valMapping = keyTbl.getMemberMapping(keyValMmd);
                SQLExpression valIdExpr = exprFactory.newExpression(subStmt, subStmt.getPrimaryTable(), valMapping);
                subStmt.whereAnd(valIdExpr.eq(valExpr), true);
            }
        } else {
            DatastoreClass valTbl = storeMgr.getDatastoreClass(mmd.getMap().getValueType(), clr);
            subStmt = new SelectStatement(stmt, storeMgr, valTbl, null, null);
            subStmt.setClassLoaderResolver(clr);
            JavaTypeMapping oneMapping = storeMgr.getMappingManager().getMapping(Integer.class);
            subStmt.select(exprFactory.newLiteral(subStmt, oneMapping, 1), null);
            // Join to key table
            SQLTable keySqlTbl = subStmt.join(JoinType.INNER_JOIN, subStmt.getPrimaryTable(), valTbl.getIdMapping(), keyTbl, null, keyTbl.getMemberMapping(keyValMmd), null, null, true);
            // Restrict to map owner (on key table)
            SQLExpression ownerExpr = exprFactory.newExpression(subStmt, keySqlTbl, ownerMapping);
            SQLExpression ownerIdExpr = exprFactory.newExpression(stmt, mapExpr.getSQLTable(), mapExpr.getSQLTable().getTable().getIdMapping());
            subStmt.whereAnd(ownerExpr.eq(ownerIdExpr), true);
            if (valIsUnbound) {
                // Bind the variable in the QueryGenerator
                valExpr = exprFactory.newExpression(subStmt, subStmt.getPrimaryTable(), valTbl.getIdMapping());
                stmt.getQueryGenerator().bindVariable(varName, valCmd, valExpr.getSQLTable(), valExpr.getJavaTypeMapping());
            } else {
                // Add restrict to value
                SQLExpression valIdExpr = exprFactory.newExpression(subStmt, subStmt.getPrimaryTable(), valTbl.getIdMapping());
                subStmt.whereAnd(valIdExpr.eq(valExpr), true);
            }
        }
    }
    return new BooleanSubqueryExpression(stmt, "EXISTS", subStmt);
}
Also used : SQLExpressionFactory(org.datanucleus.store.rdbms.sql.expression.SQLExpressionFactory) SQLExpression(org.datanucleus.store.rdbms.sql.expression.SQLExpression) JavaTypeMapping(org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping) ClassLoaderResolver(org.datanucleus.ClassLoaderResolver) UnboundExpression(org.datanucleus.store.rdbms.sql.expression.UnboundExpression) AbstractClassMetaData(org.datanucleus.metadata.AbstractClassMetaData) RDBMSStoreManager(org.datanucleus.store.rdbms.RDBMSStoreManager) MapTable(org.datanucleus.store.rdbms.table.MapTable) SelectStatement(org.datanucleus.store.rdbms.sql.SelectStatement) BooleanSubqueryExpression(org.datanucleus.store.rdbms.sql.expression.BooleanSubqueryExpression) SQLTable(org.datanucleus.store.rdbms.sql.SQLTable) DatastoreClass(org.datanucleus.store.rdbms.table.DatastoreClass) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData) JoinTable(org.datanucleus.store.rdbms.table.JoinTable)

Example 5 with MapTable

use of org.datanucleus.store.rdbms.table.MapTable in project datanucleus-rdbms by datanucleus.

the class MapContainsValueMethod method containsAsJoin.

/**
 * Method to return an expression for Map.containsValue using INNER JOIN to the element.
 * This is only for use when there are no "!containsValue" and no "OR" operations.
 * Creates SQL by adding INNER JOIN to the join table (where it exists), and also to the value table
 * adding an AND condition on the value (with value of the valueExpr).
 * Returns a BooleanExpression "TRUE" (since the INNER JOIN will guarantee if the value is contained of not).
 * @param stmt SQLStatement
 * @param mapExpr Map expression
 * @param valExpr Expression for the value
 * @param joinType Type of join
 * @return Contains expression
 */
protected SQLExpression containsAsJoin(SQLStatement stmt, MapExpression mapExpr, SQLExpression valExpr, JoinType joinType) {
    boolean valIsUnbound = (valExpr instanceof UnboundExpression);
    String varName = null;
    String valAlias = null;
    if (valIsUnbound) {
        varName = ((UnboundExpression) valExpr).getVariableName();
        NucleusLogger.QUERY.debug("map.containsValue(" + valExpr + ") binding unbound variable " + varName + " using INNER JOIN");
    // TODO What if the variable is declared as a subtype, handle this see CollectionContainsMethod
    } else if (!stmt.getQueryGenerator().hasExplicitJoins()) {
        if (stmt.getJoinTypeForTable(valExpr.getSQLTable()) == JoinType.CROSS_JOIN) {
            // Value is currently joined via CROSS JOIN, so remove it (and use INNER JOIN below)
            valAlias = stmt.removeCrossJoin(valExpr.getSQLTable());
            valIsUnbound = true;
            NucleusLogger.QUERY.debug("map.containsValue(" + valExpr + ") was previously bound as CROSS JOIN but changing to INNER JOIN");
        }
    // TODO If owner is joined via CROSS JOIN and value is already present then remove CROSS JOIN
    // and join via INNER JOIN
    }
    RDBMSStoreManager storeMgr = stmt.getRDBMSManager();
    SQLExpressionFactory exprFactory = stmt.getSQLExpressionFactory();
    ClassLoaderResolver clr = stmt.getQueryGenerator().getClassLoaderResolver();
    AbstractMemberMetaData mmd = mapExpr.getJavaTypeMapping().getMemberMetaData();
    AbstractClassMetaData valCmd = mmd.getMap().getValueClassMetaData(clr);
    if (mmd.getMap().getMapType() == MapType.MAP_TYPE_JOIN) {
        // Map formed in join table - add join to join table, then to value table (if present)
        MapTable mapTbl = (MapTable) storeMgr.getTable(mmd);
        SQLTable joinSqlTbl = stmt.join(joinType, mapExpr.getSQLTable(), mapExpr.getSQLTable().getTable().getIdMapping(), mapTbl, null, mapTbl.getOwnerMapping(), null, null);
        if (valCmd != null) {
            if (valIsUnbound) {
                DatastoreClass valTbl = storeMgr.getDatastoreClass(valCmd.getFullClassName(), clr);
                SQLTable valSqlTbl = stmt.join(joinType, joinSqlTbl, mapTbl.getValueMapping(), valTbl, valAlias, valTbl.getIdMapping(), null, null);
                // Bind the variable in the QueryGenerator
                valExpr = exprFactory.newExpression(stmt, valSqlTbl, valSqlTbl.getTable().getIdMapping());
                stmt.getQueryGenerator().bindVariable(varName, valCmd, valExpr.getSQLTable(), valExpr.getJavaTypeMapping());
            } else {
                // Add restrict to value
                SQLExpression valIdExpr = exprFactory.newExpression(stmt, joinSqlTbl, mapTbl.getValueMapping());
                stmt.whereAnd(valIdExpr.eq(valExpr), true);
            }
        } else {
            if (valIsUnbound) {
                // Bind the variable in the QueryGenerator
                valExpr = exprFactory.newExpression(stmt, joinSqlTbl, mapTbl.getValueMapping());
                stmt.getQueryGenerator().bindVariable(varName, null, valExpr.getSQLTable(), valExpr.getJavaTypeMapping());
            } else {
                // Add restrict to value
                SQLExpression valIdExpr = exprFactory.newExpression(stmt, joinSqlTbl, mapTbl.getValueMapping());
                stmt.whereAnd(valIdExpr.eq(valExpr), true);
            }
        }
    } else if (mmd.getMap().getMapType() == MapType.MAP_TYPE_KEY_IN_VALUE) {
        // Map formed in value table - add join to value table
        DatastoreClass valTbl = storeMgr.getDatastoreClass(valCmd.getFullClassName(), clr);
        JavaTypeMapping ownerMapping = null;
        if (mmd.getMappedBy() != null) {
            ownerMapping = valTbl.getMemberMapping(valCmd.getMetaDataForMember(mmd.getMappedBy()));
        } else {
            ownerMapping = valTbl.getExternalMapping(mmd, MappingType.EXTERNAL_FK);
        }
        SQLTable valSqlTbl = stmt.join(joinType, mapExpr.getSQLTable(), mapExpr.getSQLTable().getTable().getIdMapping(), valTbl, valAlias, ownerMapping, null, null);
        if (valIsUnbound) {
            // Bind the variable in the QueryGenerator
            valExpr = exprFactory.newExpression(stmt, valSqlTbl, valTbl.getIdMapping());
            stmt.getQueryGenerator().bindVariable(varName, valCmd, valExpr.getSQLTable(), valExpr.getJavaTypeMapping());
        } else {
            // Add restrict to value
            SQLExpression valIdExpr = exprFactory.newExpression(stmt, valSqlTbl, valTbl.getIdMapping());
            stmt.whereAnd(valIdExpr.eq(valExpr), true);
        }
    } else if (mmd.getMap().getMapType() == MapType.MAP_TYPE_VALUE_IN_KEY) {
        // Map formed in key table - add join to key table then to value table
        AbstractClassMetaData keyCmd = mmd.getMap().getKeyClassMetaData(clr);
        DatastoreClass keyTbl = storeMgr.getDatastoreClass(keyCmd.getFullClassName(), clr);
        AbstractMemberMetaData keyValMmd = keyCmd.getMetaDataForMember(mmd.getValueMetaData().getMappedBy());
        JavaTypeMapping ownerMapping = null;
        if (mmd.getMappedBy() != null) {
            ownerMapping = keyTbl.getMemberMapping(keyCmd.getMetaDataForMember(mmd.getMappedBy()));
        } else {
            ownerMapping = keyTbl.getExternalMapping(mmd, MappingType.EXTERNAL_FK);
        }
        SQLTable keySqlTbl = stmt.join(joinType, mapExpr.getSQLTable(), mapExpr.getSQLTable().getTable().getIdMapping(), keyTbl, null, ownerMapping, null, null);
        if (valCmd != null) {
            DatastoreClass valTbl = storeMgr.getDatastoreClass(valCmd.getFullClassName(), clr);
            SQLTable valSqlTbl = stmt.join(joinType, keySqlTbl, keyTbl.getMemberMapping(keyValMmd), valTbl, valAlias, valTbl.getIdMapping(), null, null);
            if (valIsUnbound) {
                // Bind the variable in the QueryGenerator
                valExpr = exprFactory.newExpression(stmt, valSqlTbl, valTbl.getIdMapping());
                stmt.getQueryGenerator().bindVariable(varName, valCmd, valExpr.getSQLTable(), valExpr.getJavaTypeMapping());
            } else {
                // Add restrict to value
                SQLExpression valIdExpr = exprFactory.newExpression(stmt, valSqlTbl, valTbl.getIdMapping());
                stmt.whereAnd(valIdExpr.eq(valExpr), true);
            }
        } else {
            if (valIsUnbound) {
                // Bind the variable in the QueryGenerator
                valExpr = exprFactory.newExpression(stmt, keySqlTbl, keyTbl.getMemberMapping(keyValMmd));
                stmt.getQueryGenerator().bindVariable(varName, null, valExpr.getSQLTable(), valExpr.getJavaTypeMapping());
            } else {
                // Add restrict to value
                SQLExpression valIdExpr = exprFactory.newExpression(stmt, keySqlTbl, keyTbl.getMemberMapping(keyValMmd));
                stmt.whereAnd(valIdExpr.eq(valExpr), true);
            }
        }
    }
    JavaTypeMapping m = exprFactory.getMappingForType(boolean.class, true);
    return exprFactory.newLiteral(stmt, m, true).eq(exprFactory.newLiteral(stmt, m, true));
}
Also used : SQLExpressionFactory(org.datanucleus.store.rdbms.sql.expression.SQLExpressionFactory) SQLExpression(org.datanucleus.store.rdbms.sql.expression.SQLExpression) JavaTypeMapping(org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping) ClassLoaderResolver(org.datanucleus.ClassLoaderResolver) UnboundExpression(org.datanucleus.store.rdbms.sql.expression.UnboundExpression) AbstractClassMetaData(org.datanucleus.metadata.AbstractClassMetaData) RDBMSStoreManager(org.datanucleus.store.rdbms.RDBMSStoreManager) MapTable(org.datanucleus.store.rdbms.table.MapTable) SQLTable(org.datanucleus.store.rdbms.sql.SQLTable) DatastoreClass(org.datanucleus.store.rdbms.table.DatastoreClass) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData)

Aggregations

JavaTypeMapping (org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping)18 DatastoreClass (org.datanucleus.store.rdbms.table.DatastoreClass)18 MapTable (org.datanucleus.store.rdbms.table.MapTable)18 AbstractClassMetaData (org.datanucleus.metadata.AbstractClassMetaData)17 AbstractMemberMetaData (org.datanucleus.metadata.AbstractMemberMetaData)17 SQLTable (org.datanucleus.store.rdbms.sql.SQLTable)14 ClassLoaderResolver (org.datanucleus.ClassLoaderResolver)13 SQLExpression (org.datanucleus.store.rdbms.sql.expression.SQLExpression)12 SQLExpressionFactory (org.datanucleus.store.rdbms.sql.expression.SQLExpressionFactory)12 RDBMSStoreManager (org.datanucleus.store.rdbms.RDBMSStoreManager)11 MapMetaData (org.datanucleus.metadata.MapMetaData)8 NucleusException (org.datanucleus.exceptions.NucleusException)7 SelectStatement (org.datanucleus.store.rdbms.sql.SelectStatement)7 UnboundExpression (org.datanucleus.store.rdbms.sql.expression.UnboundExpression)7 JoinTable (org.datanucleus.store.rdbms.table.JoinTable)6 Table (org.datanucleus.store.rdbms.table.Table)6 NucleusUserException (org.datanucleus.exceptions.NucleusUserException)4 BooleanSubqueryExpression (org.datanucleus.store.rdbms.sql.expression.BooleanSubqueryExpression)4 CollectionTable (org.datanucleus.store.rdbms.table.CollectionTable)4 RelationType (org.datanucleus.metadata.RelationType)3