Search in sources :

Example 46 with JavaTypeMapping

use of org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping in project datanucleus-rdbms by datanucleus.

the class DiscriminatorStatementGenerator method getStatement.

/**
 * Accessor for the SelectStatement.
 * @param ec ExecutionContext
 * @return The SelectStatement for iterating through objects with a discriminator column
 */
public SelectStatement getStatement(ExecutionContext ec) {
    SelectStatement stmt = null;
    SQLTable discrimSqlTbl = null;
    if (joinTable == null) {
        // Select of candidate table
        stmt = new SelectStatement(parentStmt, storeMgr, candidateTable, candidateTableAlias, candidateTableGroupName);
        stmt.setClassLoaderResolver(clr);
        discrimSqlTbl = stmt.getPrimaryTable();
    } else {
        // Select of join table, with join to element table
        stmt = new SelectStatement(parentStmt, storeMgr, joinTable, joinTableAlias, candidateTableGroupName);
        stmt.setClassLoaderResolver(clr);
        JavaTypeMapping candidateIdMapping = candidateTable.getIdMapping();
        if (hasOption(OPTION_ALLOW_NULLS)) {
            // Put element table in same table group since all relates to the elements
            discrimSqlTbl = stmt.join(JoinType.LEFT_OUTER_JOIN, null, joinElementMapping, candidateTable, null, candidateIdMapping, null, stmt.getPrimaryTable().getGroupName(), true);
        } else {
            // Put element table in same table group since all relates to the elements
            discrimSqlTbl = stmt.join(JoinType.INNER_JOIN, null, joinElementMapping, candidateTable, null, candidateIdMapping, null, stmt.getPrimaryTable().getGroupName(), true);
        }
    }
    JavaTypeMapping discMapping = candidateTable.getSurrogateMapping(SurrogateColumnType.DISCRIMINATOR, true);
    if (discMapping != null) {
        // Allow for discriminator being in super-table of the candidate table
        discrimSqlTbl = SQLStatementHelper.getSQLTableForMappingOfTable(stmt, discrimSqlTbl, discMapping);
    }
    DiscriminatorMetaData dismd = discrimSqlTbl.getTable().getDiscriminatorMetaData();
    boolean hasDiscriminator = (discMapping != null && dismd != null && dismd.getStrategy() != DiscriminatorStrategy.NONE);
    // Check if we can omit the discriminator restriction
    boolean restrictDiscriminator = hasOption(OPTION_RESTRICT_DISCRIM);
    if (hasDiscriminator && restrictDiscriminator) {
        // Add the discriminator expression to restrict accepted values
        boolean multipleCandidates = false;
        BooleanExpression discExpr = null;
        if (candidates != null) {
            // Multiple candidates
            if (candidates.length > 1) {
                multipleCandidates = true;
            }
            for (int i = 0; i < candidates.length; i++) {
                if (Modifier.isAbstract(candidates[i].getModifiers())) {
                    // No point selecting this candidate since can't be instantiated
                    continue;
                }
                BooleanExpression discExprCandidate = SQLStatementHelper.getExpressionForDiscriminatorForClass(stmt, candidates[i].getName(), dismd, discMapping, discrimSqlTbl, clr);
                if (discExpr != null) {
                    discExpr = discExpr.ior(discExprCandidate);
                } else {
                    discExpr = discExprCandidate;
                }
                if (includeSubclasses) {
                    Collection<String> subclassNames = storeMgr.getSubClassesForClass(candidateType.getName(), true, clr);
                    Iterator<String> subclassIter = subclassNames.iterator();
                    if (!multipleCandidates) {
                        multipleCandidates = (subclassNames.size() > 0);
                    }
                    while (subclassIter.hasNext()) {
                        String subclassName = subclassIter.next();
                        BooleanExpression discExprSub = SQLStatementHelper.getExpressionForDiscriminatorForClass(stmt, subclassName, dismd, discMapping, discrimSqlTbl, clr);
                        discExpr = discExpr.ior(discExprSub);
                    }
                }
            }
        } else {
            // Single candidate
            if (!Modifier.isAbstract(candidateType.getModifiers())) {
                discExpr = SQLStatementHelper.getExpressionForDiscriminatorForClass(stmt, candidateType.getName(), dismd, discMapping, discrimSqlTbl, clr);
            }
            if (includeSubclasses) {
                Collection<String> subclassNames = storeMgr.getSubClassesForClass(candidateType.getName(), true, clr);
                Iterator<String> subclassIter = subclassNames.iterator();
                multipleCandidates = (subclassNames.size() > 0);
                while (subclassIter.hasNext()) {
                    String subclassName = subclassIter.next();
                    Class subclass = clr.classForName(subclassName);
                    if ((Modifier.isAbstract(subclass.getModifiers()))) {
                        continue;
                    }
                    BooleanExpression discExprCandidate = SQLStatementHelper.getExpressionForDiscriminatorForClass(stmt, subclassName, dismd, discMapping, discrimSqlTbl, clr);
                    if (discExpr == null) {
                        discExpr = discExprCandidate;
                    } else {
                        discExpr = discExpr.ior(discExprCandidate);
                    }
                }
            }
            if (discExpr == null) {
                // No possible candidates, so set expression as "1=0"
                SQLExpressionFactory exprFactory = stmt.getSQLExpressionFactory();
                JavaTypeMapping m = exprFactory.getMappingForType(boolean.class, true);
                discExpr = exprFactory.newLiteral(stmt, m, true).eq(exprFactory.newLiteral(stmt, m, false));
            }
        }
        if (discExpr != null) {
            if (hasOption(OPTION_ALLOW_NULLS)) {
                // Allow for null value of discriminator
                SQLExpression expr = stmt.getSQLExpressionFactory().newExpression(stmt, discrimSqlTbl, discMapping);
                SQLExpression val = new NullLiteral(stmt, null, null, null);
                BooleanExpression nullDiscExpr = expr.eq(val);
                discExpr = discExpr.ior(nullDiscExpr);
                if (!multipleCandidates) {
                    multipleCandidates = true;
                }
            }
            // Apply the discriminator to the query statement
            if (multipleCandidates) {
                discExpr.encloseInParentheses();
            }
            stmt.whereAnd(discExpr, true);
        }
    }
    JavaTypeMapping multitenancyMapping = candidateTable.getSurrogateMapping(SurrogateColumnType.MULTITENANCY, false);
    if (multitenancyMapping != null) {
        // Multi-tenancy restriction
        AbstractClassMetaData cmd = candidateTable.getClassMetaData();
        SQLTable tenantSqlTbl = stmt.getTable(multitenancyMapping.getTable(), discrimSqlTbl.getGroupName());
        SQLExpression tenantExpr = stmt.getSQLExpressionFactory().newExpression(stmt, tenantSqlTbl, multitenancyMapping);
        SQLExpression tenantVal = stmt.getSQLExpressionFactory().newLiteral(stmt, multitenancyMapping, ec.getNucleusContext().getMultiTenancyId(ec, cmd));
        stmt.whereAnd(tenantExpr.eq(tenantVal), true);
    }
    JavaTypeMapping softDeleteMapping = candidateTable.getSurrogateMapping(SurrogateColumnType.SOFTDELETE, false);
    if (softDeleteMapping != null && !hasOption(OPTION_INCLUDE_SOFT_DELETES)) {
        // Soft-delete restriction
        SQLTable softDeleteSqlTbl = stmt.getTable(softDeleteMapping.getTable(), discrimSqlTbl.getGroupName());
        SQLExpression softDeleteExpr = stmt.getSQLExpressionFactory().newExpression(stmt, softDeleteSqlTbl, softDeleteMapping);
        SQLExpression softDeleteVal = stmt.getSQLExpressionFactory().newLiteral(stmt, softDeleteMapping, Boolean.FALSE);
        stmt.whereAnd(softDeleteExpr.eq(softDeleteVal), true);
    }
    return stmt;
}
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) AbstractClassMetaData(org.datanucleus.metadata.AbstractClassMetaData) DiscriminatorMetaData(org.datanucleus.metadata.DiscriminatorMetaData) BooleanExpression(org.datanucleus.store.rdbms.sql.expression.BooleanExpression) NullLiteral(org.datanucleus.store.rdbms.sql.expression.NullLiteral)

Example 47 with JavaTypeMapping

use of org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping in project datanucleus-rdbms by datanucleus.

the class AbstractCollectionStore method getContainsStatementString.

private String getContainsStatementString(Object element) {
    boolean elementsAreSerialised = isElementsAreSerialised();
    boolean usingJoinTable = usingJoinTable();
    Table selectTable = null;
    JavaTypeMapping ownerMapping = null;
    JavaTypeMapping elemMapping = null;
    JavaTypeMapping relDiscrimMapping = null;
    ComponentInfo elemInfo = null;
    if (usingJoinTable) {
        selectTable = this.containerTable;
        ownerMapping = this.ownerMapping;
        elemMapping = this.elementMapping;
        relDiscrimMapping = this.relationDiscriminatorMapping;
    } else {
        elemInfo = getComponentInfoForElement(element);
        if (elemInfo != null) {
            selectTable = elemInfo.getDatastoreClass();
            elemMapping = elemInfo.getDatastoreClass().getIdMapping();
            if (ownerMemberMetaData.getMappedBy() != null) {
                ownerMapping = selectTable.getMemberMapping(elemInfo.getAbstractClassMetaData().getMetaDataForMember(ownerMemberMetaData.getMappedBy()));
            } else {
                ownerMapping = elemInfo.getDatastoreClass().getExternalMapping(ownerMemberMetaData, MappingType.EXTERNAL_FK);
            }
            relDiscrimMapping = elemInfo.getDatastoreClass().getExternalMapping(ownerMemberMetaData, MappingType.EXTERNAL_FK_DISCRIMINATOR);
        } else {
            // TODO What if no suitable elementInfo found?
            throw new NucleusException("Unable to locate owner mapping for backing store at " + ownerMemberMetaData.getFullFieldName());
        }
    }
    StringBuilder stmt = new StringBuilder("SELECT ");
    String containerAlias = "THIS";
    String joinedElementAlias = "ELEM";
    for (int i = 0; i < ownerMapping.getNumberOfDatastoreMappings(); i++) {
        if (i > 0) {
            stmt.append(",");
        }
        stmt.append(ownerMapping.getDatastoreMapping(i).getColumn().getIdentifier().toString());
    }
    stmt.append(" FROM ").append(selectTable.toString()).append(" ").append(containerAlias);
    // TODO Add join to owner if ownerMapping is for supertable
    // Add join to element table if required (only allows for 1 element table currently)
    boolean joinedDiscrim = false;
    // TODO Enable this code applying the discrim restriction to JoinTable cases
    /*if (elementInfo != null && elementInfo[0].getTable() != containerTable && elementInfo[0].getDiscriminatorMapping() != null)
        {
            // Need join to the element table to restrict the discriminator
            joinedDiscrim = true;
            JavaTypeMapping elemIdMapping = elementInfo[0].getTable().getIdMapping();
            stmt.append(" INNER JOIN ");
            stmt.append(elementInfo[0].getTable().toString()).append(" ").append(joinedElementAlias).append(" ON ");
            for (int i=0;i<elementMapping.getNumberOfDatastoreFields();i++)
            {
                if (i > 0)
                {
                    stmt.append(" AND ");
                }
                stmt.append(containerAlias).append(".").append(elementMapping.getDataStoreMapping(i).getDatastoreField().getIdentifier());
                stmt.append("=");
                stmt.append(joinedElementAlias).append(".").append(elemIdMapping.getDataStoreMapping(0).getDatastoreField().getIdentifier());
            }
        }*/
    stmt.append(" WHERE ");
    BackingStoreHelper.appendWhereClauseForMapping(stmt, ownerMapping, containerAlias, true);
    BackingStoreHelper.appendWhereClauseForElement(stmt, elemMapping, element, elementsAreSerialised, containerAlias, false);
    // Needs to pass TCK M-M relationship test. see contains(ObjectProvider, Object) method also
    if (!usingJoinTable && elemInfo.getDiscriminatorMapping() != null) {
        // TODO What if we have the discriminator in a supertable? the mapping will be null so we don't get this clause added!
        // Element table has discriminator so restrict to the element-type and subclasses
        // Add WHERE for the element and each subclass type so we restrict to valid element types TODO Is the element itself included?
        StringBuilder discrimStr = new StringBuilder();
        Collection<String> classNames = storeMgr.getSubClassesForClass(elemInfo.getClassName(), true, clr);
        classNames.add(elemInfo.getClassName());
        for (String className : classNames) {
            Class cls = clr.classForName(className);
            if (!Modifier.isAbstract(cls.getModifiers())) {
                if (discrimStr.length() > 0) {
                    discrimStr.append(" OR ");
                }
                if (joinedDiscrim) {
                    discrimStr.append(joinedElementAlias);
                } else {
                    discrimStr.append(containerAlias);
                }
                discrimStr.append(".").append(elemInfo.getDiscriminatorMapping().getDatastoreMapping(0).getColumn().getIdentifier().toString());
                discrimStr.append(" = ");
                discrimStr.append(elemInfo.getDiscriminatorMapping().getDatastoreMapping(0).getUpdateInputParameter());
            }
        }
        if (discrimStr.length() > 0) {
            stmt.append(" AND (").append(discrimStr.toString()).append(")");
        }
    }
    if (relDiscrimMapping != null) {
        // Relation uses shared resource (FK, JoinTable) so restrict to this particular relation
        BackingStoreHelper.appendWhereClauseForMapping(stmt, relDiscrimMapping, containerAlias, false);
    }
    return stmt.toString();
}
Also used : Table(org.datanucleus.store.rdbms.table.Table) JoinTable(org.datanucleus.store.rdbms.table.JoinTable) JavaTypeMapping(org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping) NucleusException(org.datanucleus.exceptions.NucleusException)

Example 48 with JavaTypeMapping

use of org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping in project datanucleus-rdbms by datanucleus.

the class AbstractMapStore method updateEmbeddedKey.

/**
 * Method to update a field of an embedded key.
 * @param op ObjectProvider of the owner
 * @param key The key to update
 * @param fieldNumber The number of the field to update
 * @param newValue The new value
 */
public boolean updateEmbeddedKey(ObjectProvider op, Object key, int fieldNumber, Object newValue) {
    boolean modified = false;
    if (keyMapping != null && keyMapping instanceof EmbeddedKeyPCMapping) {
        String fieldName = valueCmd.getMetaDataForManagedMemberAtAbsolutePosition(fieldNumber).getName();
        if (fieldName == null) {
            // We have no mapping for this field so presumably is the owner field or a PK field
            return false;
        }
        JavaTypeMapping fieldMapping = ((EmbeddedKeyPCMapping) keyMapping).getJavaTypeMapping(fieldName);
        if (fieldMapping == null) {
            // We have no mapping for this field so presumably is the owner field or a PK field
            return false;
        }
        modified = updatedEmbeddedKey(op, key, fieldNumber, newValue, fieldMapping);
    }
    return modified;
}
Also used : JavaTypeMapping(org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping) EmbeddedKeyPCMapping(org.datanucleus.store.rdbms.mapping.java.EmbeddedKeyPCMapping)

Example 49 with JavaTypeMapping

use of org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping in project datanucleus-rdbms by datanucleus.

the class AbstractMapStore method getUpdateEmbeddedValueStmt.

/**
 * Generate statement for update the field of an embedded value.
 * <PRE>
 * UPDATE MAPTABLE
 * SET EMBEDDEDVALUECOL1 = ?
 * WHERE OWNERCOL=?
 * AND EMBEDDEDVALUECOL1 = ?
 * AND EMBEDDEDVALUECOL2 = ? ...
 * </PRE>
 * @param fieldMapping The mapping for the field to be updated
 * @param ownerMapping The owner mapping
 * @param valueMapping mapping for the value
 * @param mapTable The map table
 * @return Statement for updating an embedded value in the Set
 */
protected String getUpdateEmbeddedValueStmt(JavaTypeMapping fieldMapping, JavaTypeMapping ownerMapping, JavaTypeMapping valueMapping, Table mapTable) {
    StringBuilder stmt = new StringBuilder("UPDATE ");
    stmt.append(mapTable.toString());
    stmt.append(" SET ");
    for (int i = 0; i < fieldMapping.getNumberOfDatastoreMappings(); i++) {
        if (i > 0) {
            stmt.append(",");
        }
        stmt.append(fieldMapping.getDatastoreMapping(i).getColumn().getIdentifier().toString());
        stmt.append(" = ");
        stmt.append(fieldMapping.getDatastoreMapping(i).getUpdateInputParameter());
    }
    stmt.append(" WHERE ");
    BackingStoreHelper.appendWhereClauseForMapping(stmt, ownerMapping, null, true);
    EmbeddedValuePCMapping embeddedMapping = (EmbeddedValuePCMapping) valueMapping;
    for (int i = 0; i < embeddedMapping.getNumberOfJavaTypeMappings(); i++) {
        JavaTypeMapping m = embeddedMapping.getJavaTypeMapping(i);
        if (m != null) {
            for (int j = 0; j < m.getNumberOfDatastoreMappings(); j++) {
                stmt.append(" AND ");
                stmt.append(m.getDatastoreMapping(j).getColumn().getIdentifier().toString());
                stmt.append(" = ");
                stmt.append(m.getDatastoreMapping(j).getUpdateInputParameter());
            }
        }
    }
    return stmt.toString();
}
Also used : JavaTypeMapping(org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping) EmbeddedValuePCMapping(org.datanucleus.store.rdbms.mapping.java.EmbeddedValuePCMapping)

Example 50 with JavaTypeMapping

use of org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping in project datanucleus-rdbms by datanucleus.

the class BackingStoreHelper method populateEmbeddedElementFieldsInStatement.

/**
 * Convenience method to populate the passed PreparedStatement with the field values from
 * the embedded element starting at the specified jdbc position.
 * @param op ObjectProvider of the owning container
 * @param element The embedded element
 * @param ps The PreparedStatement
 * @param jdbcPosition JDBC position in the statement to start at
 * @param ownerFieldMetaData The meta data for the owner field
 * @param elementMapping mapping for the element
 * @param emd Metadata for the element class
 * @param bcs Container store
 * @return The next JDBC position
 */
public static int populateEmbeddedElementFieldsInStatement(ObjectProvider op, Object element, PreparedStatement ps, int jdbcPosition, AbstractMemberMetaData ownerFieldMetaData, JavaTypeMapping elementMapping, AbstractClassMetaData emd, BaseContainerStore bcs) {
    EmbeddedElementPCMapping embeddedMapping = (EmbeddedElementPCMapping) elementMapping;
    StatementClassMapping mappingDefinition = new StatementClassMapping();
    int[] elementFieldNumbers = new int[embeddedMapping.getNumberOfJavaTypeMappings()];
    for (int i = 0; i < embeddedMapping.getNumberOfJavaTypeMappings(); i++) {
        JavaTypeMapping fieldMapping = embeddedMapping.getJavaTypeMapping(i);
        int absFieldNum = emd.getAbsolutePositionOfMember(fieldMapping.getMemberMetaData().getName());
        elementFieldNumbers[i] = absFieldNum;
        StatementMappingIndex stmtMapping = new StatementMappingIndex(fieldMapping);
        int[] jdbcParamPositions = new int[fieldMapping.getNumberOfDatastoreMappings()];
        for (int j = 0; j < fieldMapping.getNumberOfDatastoreMappings(); j++) {
            jdbcParamPositions[j] = jdbcPosition++;
        }
        stmtMapping.addParameterOccurrence(jdbcParamPositions);
        mappingDefinition.addMappingForMember(absFieldNum, stmtMapping);
    }
    ObjectProvider elementOP = bcs.getObjectProviderForEmbeddedPCObject(op, element, ownerFieldMetaData, ObjectProvider.EMBEDDED_COLLECTION_ELEMENT_PC);
    elementOP.provideFields(elementFieldNumbers, new ParameterSetter(elementOP, ps, mappingDefinition));
    return jdbcPosition;
}
Also used : JavaTypeMapping(org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping) ObjectProvider(org.datanucleus.state.ObjectProvider) StatementMappingIndex(org.datanucleus.store.rdbms.query.StatementMappingIndex) ParameterSetter(org.datanucleus.store.rdbms.fieldmanager.ParameterSetter) EmbeddedElementPCMapping(org.datanucleus.store.rdbms.mapping.java.EmbeddedElementPCMapping) StatementClassMapping(org.datanucleus.store.rdbms.query.StatementClassMapping)

Aggregations

JavaTypeMapping (org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping)230 SQLExpression (org.datanucleus.store.rdbms.sql.expression.SQLExpression)96 AbstractMemberMetaData (org.datanucleus.metadata.AbstractMemberMetaData)82 RDBMSStoreManager (org.datanucleus.store.rdbms.RDBMSStoreManager)82 SQLExpressionFactory (org.datanucleus.store.rdbms.sql.expression.SQLExpressionFactory)81 DatastoreClass (org.datanucleus.store.rdbms.table.DatastoreClass)76 AbstractClassMetaData (org.datanucleus.metadata.AbstractClassMetaData)69 ArrayList (java.util.ArrayList)66 NucleusException (org.datanucleus.exceptions.NucleusException)57 ClassLoaderResolver (org.datanucleus.ClassLoaderResolver)50 NucleusUserException (org.datanucleus.exceptions.NucleusUserException)47 NumericExpression (org.datanucleus.store.rdbms.sql.expression.NumericExpression)43 SQLTable (org.datanucleus.store.rdbms.sql.SQLTable)37 PersistableMapping (org.datanucleus.store.rdbms.mapping.java.PersistableMapping)30 SelectStatement (org.datanucleus.store.rdbms.sql.SelectStatement)30 StringExpression (org.datanucleus.store.rdbms.sql.expression.StringExpression)27 List (java.util.List)25 ReferenceMapping (org.datanucleus.store.rdbms.mapping.java.ReferenceMapping)22 StatementMappingIndex (org.datanucleus.store.rdbms.query.StatementMappingIndex)21 StringLiteral (org.datanucleus.store.rdbms.sql.expression.StringLiteral)21