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;
}
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();
}
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;
}
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();
}
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;
}
Aggregations