use of org.datanucleus.store.rdbms.sql.expression.SQLExpressionFactory in project datanucleus-rdbms by datanucleus.
the class RDBMSStoreHelper method getClassNameForIdUsingUnion.
/**
* Utility that does a union candidate query for the specified candidate(s) and subclasses
* and returns the class name of the instance that has the specified identity (if any).
* @param storeMgr RDBMS StoreManager
* @param ec execution context
* @param id The id
* @param rootCmds Metadata for the classes at the root
* @return Name of the class with this identity (or null if none found)
*/
public static String getClassNameForIdUsingUnion(RDBMSStoreManager storeMgr, ExecutionContext ec, Object id, List<AbstractClassMetaData> rootCmds) {
// Check for input error
if (rootCmds == null || rootCmds.isEmpty() || id == null) {
return null;
}
SQLExpressionFactory exprFactory = storeMgr.getSQLExpressionFactory();
ClassLoaderResolver clr = ec.getClassLoaderResolver();
// Form a query UNIONing all possible root candidates (and their subclasses)
Iterator<AbstractClassMetaData> rootCmdIter = rootCmds.iterator();
// Metadata for sample class in the tree so we can check if needs locking
AbstractClassMetaData sampleCmd = null;
SelectStatement sqlStmtMain = null;
while (rootCmdIter.hasNext()) {
AbstractClassMetaData rootCmd = rootCmdIter.next();
DatastoreClass rootTbl = storeMgr.getDatastoreClass(rootCmd.getFullClassName(), clr);
InheritanceMetaData rootInhmd = rootCmd.getBaseAbstractClassMetaData().getInheritanceMetaData();
if (rootInhmd.getStrategy() == InheritanceStrategy.COMPLETE_TABLE) {
// COMPLETE TABLE so use one branch of UNION for each possible class
if (rootTbl != null) {
UnionStatementGenerator stmtGen = new UnionStatementGenerator(storeMgr, clr, clr.classForName(rootCmd.getFullClassName()), false, null, null);
stmtGen.setOption(SelectStatementGenerator.OPTION_SELECT_DN_TYPE);
if (sqlStmtMain == null) {
sampleCmd = rootCmd;
sqlStmtMain = stmtGen.getStatement(ec);
// WHERE (object id) = ?
JavaTypeMapping idMapping = sqlStmtMain.getPrimaryTable().getTable().getIdMapping();
JavaTypeMapping idParamMapping = new PersistableIdMapping((PersistableMapping) idMapping);
SQLExpression fieldExpr = exprFactory.newExpression(sqlStmtMain, sqlStmtMain.getPrimaryTable(), idMapping);
SQLExpression fieldVal = exprFactory.newLiteralParameter(sqlStmtMain, idParamMapping, id, "ID");
sqlStmtMain.whereAnd(fieldExpr.eq(fieldVal), true);
} else {
SelectStatement sqlStmt = stmtGen.getStatement(ec);
// WHERE (object id) = ?
JavaTypeMapping idMapping = sqlStmt.getPrimaryTable().getTable().getIdMapping();
JavaTypeMapping idParamMapping = new PersistableIdMapping((PersistableMapping) idMapping);
SQLExpression fieldExpr = exprFactory.newExpression(sqlStmt, sqlStmt.getPrimaryTable(), idMapping);
SQLExpression fieldVal = exprFactory.newLiteralParameter(sqlStmt, idParamMapping, id, "ID");
sqlStmt.whereAnd(fieldExpr.eq(fieldVal), true);
sqlStmtMain.union(sqlStmt);
}
}
Collection<String> rootSubclassNames = storeMgr.getSubClassesForClass(rootCmd.getFullClassName(), true, clr);
for (String rootSubclassName : rootSubclassNames) {
AbstractClassMetaData rootSubclassCmd = storeMgr.getMetaDataManager().getMetaDataForClass(rootSubclassName, clr);
DatastoreClass rootSubclassTbl = storeMgr.getDatastoreClass(rootSubclassCmd.getFullClassName(), clr);
if (rootSubclassTbl != null) {
UnionStatementGenerator stmtGen = new UnionStatementGenerator(storeMgr, clr, clr.classForName(rootSubclassCmd.getFullClassName()), false, null, null);
stmtGen.setOption(SelectStatementGenerator.OPTION_SELECT_DN_TYPE);
if (sqlStmtMain == null) {
sampleCmd = rootSubclassCmd;
sqlStmtMain = stmtGen.getStatement(ec);
// WHERE (object id) = ?
JavaTypeMapping idMapping = sqlStmtMain.getPrimaryTable().getTable().getIdMapping();
JavaTypeMapping idParamMapping = new PersistableIdMapping((PersistableMapping) idMapping);
SQLExpression fieldExpr = exprFactory.newExpression(sqlStmtMain, sqlStmtMain.getPrimaryTable(), idMapping);
SQLExpression fieldVal = exprFactory.newLiteralParameter(sqlStmtMain, idParamMapping, id, "ID");
sqlStmtMain.whereAnd(fieldExpr.eq(fieldVal), true);
} else {
SelectStatement sqlStmt = stmtGen.getStatement(ec);
// WHERE (object id) = ?
JavaTypeMapping idMapping = sqlStmt.getPrimaryTable().getTable().getIdMapping();
JavaTypeMapping idParamMapping = new PersistableIdMapping((PersistableMapping) idMapping);
SQLExpression fieldExpr = exprFactory.newExpression(sqlStmt, sqlStmt.getPrimaryTable(), idMapping);
SQLExpression fieldVal = exprFactory.newLiteralParameter(sqlStmt, idParamMapping, id, "ID");
sqlStmt.whereAnd(fieldExpr.eq(fieldVal), true);
sqlStmtMain.union(sqlStmt);
}
}
}
continue;
}
if (rootTbl == null) {
// Class must be using "subclass-table" (no table of its own) so find where it is
AbstractClassMetaData[] subcmds = storeMgr.getClassesManagingTableForClass(rootCmd, clr);
if (subcmds == null || subcmds.length == 0) {
// No table for this class so ignore
} else {
for (int i = 0; i < subcmds.length; i++) {
UnionStatementGenerator stmtGen = new UnionStatementGenerator(storeMgr, clr, clr.classForName(subcmds[i].getFullClassName()), true, null, null);
stmtGen.setOption(SelectStatementGenerator.OPTION_SELECT_DN_TYPE);
if (sqlStmtMain == null) {
sampleCmd = subcmds[i];
sqlStmtMain = stmtGen.getStatement(ec);
// WHERE (object id) = ?
JavaTypeMapping idMapping = sqlStmtMain.getPrimaryTable().getTable().getIdMapping();
JavaTypeMapping idParamMapping = new PersistableIdMapping((PersistableMapping) idMapping);
SQLExpression fieldExpr = exprFactory.newExpression(sqlStmtMain, sqlStmtMain.getPrimaryTable(), idMapping);
SQLExpression fieldVal = exprFactory.newLiteralParameter(sqlStmtMain, idParamMapping, id, "ID");
sqlStmtMain.whereAnd(fieldExpr.eq(fieldVal), true);
} else {
SelectStatement sqlStmt = stmtGen.getStatement(ec);
// WHERE (object id) = ?
JavaTypeMapping idMapping = sqlStmt.getPrimaryTable().getTable().getIdMapping();
JavaTypeMapping idParamMapping = new PersistableIdMapping((PersistableMapping) idMapping);
SQLExpression fieldExpr = exprFactory.newExpression(sqlStmt, sqlStmt.getPrimaryTable(), idMapping);
SQLExpression fieldVal = exprFactory.newLiteralParameter(sqlStmt, idParamMapping, id, "ID");
sqlStmt.whereAnd(fieldExpr.eq(fieldVal), true);
sqlStmtMain.union(sqlStmt);
}
}
}
} else {
UnionStatementGenerator stmtGen = new UnionStatementGenerator(storeMgr, clr, clr.classForName(rootCmd.getFullClassName()), true, null, null);
stmtGen.setOption(SelectStatementGenerator.OPTION_SELECT_DN_TYPE);
if (sqlStmtMain == null) {
sampleCmd = rootCmd;
sqlStmtMain = stmtGen.getStatement(ec);
// WHERE (object id) = ?
JavaTypeMapping idMapping = sqlStmtMain.getPrimaryTable().getTable().getIdMapping();
JavaTypeMapping idParamMapping = new PersistableIdMapping((PersistableMapping) idMapping);
SQLExpression fieldExpr = exprFactory.newExpression(sqlStmtMain, sqlStmtMain.getPrimaryTable(), idMapping);
SQLExpression fieldVal = exprFactory.newLiteralParameter(sqlStmtMain, idParamMapping, id, "ID");
sqlStmtMain.whereAnd(fieldExpr.eq(fieldVal), true);
} else {
SelectStatement sqlStmt = stmtGen.getStatement(ec);
// WHERE (object id) = ?
JavaTypeMapping idMapping = sqlStmt.getPrimaryTable().getTable().getIdMapping();
JavaTypeMapping idParamMapping = new PersistableIdMapping((PersistableMapping) idMapping);
SQLExpression fieldExpr = exprFactory.newExpression(sqlStmt, sqlStmt.getPrimaryTable(), idMapping);
SQLExpression fieldVal = exprFactory.newLiteralParameter(sqlStmt, idParamMapping, id, "ID");
sqlStmt.whereAnd(fieldExpr.eq(fieldVal), true);
sqlStmtMain.union(sqlStmt);
}
}
}
// Perform the query
if (sqlStmtMain != null) {
try {
ManagedConnection mconn = storeMgr.getConnectionManager().getConnection(ec);
SQLController sqlControl = storeMgr.getSQLController();
if (sampleCmd != null && ec.getSerializeReadForClass(sampleCmd.getFullClassName())) {
sqlStmtMain.addExtension(SQLStatement.EXTENSION_LOCK_FOR_UPDATE, true);
}
try {
PreparedStatement ps = SQLStatementHelper.getPreparedStatementForSQLStatement(sqlStmtMain, ec, mconn, null, null);
String statement = sqlStmtMain.getSQLText().toSQL();
try {
ResultSet rs = sqlControl.executeStatementQuery(ec, mconn, statement, ps);
try {
while (rs.next()) {
try {
return rs.getString(UnionStatementGenerator.DN_TYPE_COLUMN).trim();
} catch (SQLException sqle) {
}
}
} finally {
rs.close();
}
} finally {
sqlControl.closeStatement(mconn, ps);
}
} finally {
mconn.release();
}
} catch (SQLException sqe) {
NucleusLogger.DATASTORE.error("Exception with UNION statement", sqe);
throw new NucleusDataStoreException(sqe.toString());
}
}
return null;
}
use of org.datanucleus.store.rdbms.sql.expression.SQLExpressionFactory in project datanucleus-rdbms by datanucleus.
the class FKSetStore method getIteratorStatement.
/**
* Method to return the SQLStatement and mapping for an iterator for this backing store.
* Create a statement of the form
* <pre>
* SELECT ELEM_COLS
* FROM ELEM_TBL
* [WHERE]
* [ELEM_TBL.OWNER_ID = {value}] [AND]
* [ELEM_TBL.DISCRIM = {discrimValue}]
* [ORDER BY {orderClause}]
* </pre>
* @param ec ExecutionContext
* @param fp FetchPlan to use in determining which fields of element to select
* @param addRestrictionOnOwner Whether to restrict to a particular owner (otherwise functions as bulk fetch for many owners).
* @return The SQLStatement and its associated StatementClassMapping
*/
public IteratorStatement getIteratorStatement(ExecutionContext ec, FetchPlan fp, boolean addRestrictionOnOwner) {
SelectStatement sqlStmt = null;
SQLExpressionFactory exprFactory = storeMgr.getSQLExpressionFactory();
StatementClassMapping iteratorMappingClass = new StatementClassMapping();
if (elementInfo[0].getDatastoreClass().getDiscriminatorMetaData() != null && elementInfo[0].getDatastoreClass().getDiscriminatorMetaData().getStrategy() != DiscriminatorStrategy.NONE) {
// TODO Only caters for one elementInfo, but with subclass-table we can have multiple
String elementType = ownerMemberMetaData.getCollection().getElementType();
if (ClassUtils.isReferenceType(clr.classForName(elementType))) {
String[] clsNames = storeMgr.getNucleusContext().getMetaDataManager().getClassesImplementingInterface(elementType, clr);
Class[] cls = new Class[clsNames.length];
for (int i = 0; i < clsNames.length; i++) {
cls[i] = clr.classForName(clsNames[i]);
}
sqlStmt = new DiscriminatorStatementGenerator(storeMgr, clr, cls, true, null, null).getStatement(ec);
} else {
sqlStmt = new DiscriminatorStatementGenerator(storeMgr, clr, clr.classForName(elementInfo[0].getClassName()), true, null, null).getStatement(ec);
}
iterateUsingDiscriminator = true;
// TODO Cater for having all possible subclasses stored in the same table (so we can select their fields too)
// String[] elemSubclasses = op.getExecutionContext().getMetaDataManager().getSubclassesForClass(emd.getFullClassName(), false);
// NucleusLogger.GENERAL.info(">> FKSetStore.iter iterMapDef=" + iteratorMappingDef + " table=" + sqlStmt.getPrimaryTable() +
// " emd=" + emd.getFullClassName() + " elem.subclasses=" + StringUtils.objectArrayToString(elemSubclasses));
// Select the required fields (of the element class)
SQLStatementHelper.selectFetchPlanOfSourceClassInStatement(sqlStmt, iteratorMappingClass, fp, sqlStmt.getPrimaryTable(), elementCmd, fp.getMaxFetchDepth());
} else {
boolean selectFetchPlan = true;
Class elementTypeCls = clr.classForName(elementType);
if (elementTypeCls.isInterface() && elementInfo.length > 1) {
// Multiple implementations of an interface, so assume the FetchPlan differs between implementation
selectFetchPlan = false;
}
// TODO This only works if the different elementInfos have the same number of PK fields (otherwise get SQL error in UNION)
for (int i = 0; i < elementInfo.length; i++) {
final Class elementCls = clr.classForName(this.elementInfo[i].getClassName());
UnionStatementGenerator stmtGen = new UnionStatementGenerator(storeMgr, clr, elementCls, true, null, null);
stmtGen.setOption(SelectStatementGenerator.OPTION_SELECT_DN_TYPE);
iteratorMappingClass.setNucleusTypeColumnName(UnionStatementGenerator.DN_TYPE_COLUMN);
SelectStatement subStmt = stmtGen.getStatement(ec);
if (selectFetchPlan) {
// Select the FetchPlan fields (of the element class)
if (sqlStmt == null) {
SQLStatementHelper.selectFetchPlanOfSourceClassInStatement(subStmt, iteratorMappingClass, fp, subStmt.getPrimaryTable(), elementInfo[i].getAbstractClassMetaData(), fp.getMaxFetchDepth());
} else {
SQLStatementHelper.selectFetchPlanOfSourceClassInStatement(subStmt, null, fp, subStmt.getPrimaryTable(), elementInfo[i].getAbstractClassMetaData(), fp.getMaxFetchDepth());
}
} else {
// Select the candidate id of the element class only
if (sqlStmt == null) {
SQLStatementHelper.selectIdentityOfCandidateInStatement(subStmt, iteratorMappingClass, elementInfo[i].getAbstractClassMetaData());
} else {
SQLStatementHelper.selectIdentityOfCandidateInStatement(subStmt, null, elementInfo[i].getAbstractClassMetaData());
}
}
if (sqlStmt == null) {
sqlStmt = subStmt;
} else {
sqlStmt.union(subStmt);
}
}
if (sqlStmt == null) {
throw new NucleusException("Unable to generate iterator statement for field " + getOwnerMemberMetaData().getFullFieldName());
}
}
if (addRestrictionOnOwner) {
// Apply condition to filter by owner
// TODO If ownerMapping is not for containerTable then do JOIN to ownerTable in the FROM clause (or find if already done)
SQLTable ownerSqlTbl = SQLStatementHelper.getSQLTableForMappingOfTable(sqlStmt, sqlStmt.getPrimaryTable(), ownerMapping);
SQLExpression ownerExpr = exprFactory.newExpression(sqlStmt, ownerSqlTbl, ownerMapping);
SQLExpression ownerVal = exprFactory.newLiteralParameter(sqlStmt, ownerMapping, null, "OWNER");
sqlStmt.whereAnd(ownerExpr.eq(ownerVal), true);
}
if (relationDiscriminatorMapping != null) {
// Apply condition on distinguisher field to filter by distinguisher (when present)
SQLTable distSqlTbl = SQLStatementHelper.getSQLTableForMappingOfTable(sqlStmt, sqlStmt.getPrimaryTable(), relationDiscriminatorMapping);
SQLExpression distExpr = exprFactory.newExpression(sqlStmt, distSqlTbl, relationDiscriminatorMapping);
SQLExpression distVal = exprFactory.newLiteral(sqlStmt, relationDiscriminatorMapping, relationDiscriminatorValue);
sqlStmt.whereAnd(distExpr.eq(distVal), true);
}
if (orderMapping != null) {
// Order by the ordering column, when present
SQLTable orderSqlTbl = SQLStatementHelper.getSQLTableForMappingOfTable(sqlStmt, sqlStmt.getPrimaryTable(), orderMapping);
SQLExpression[] orderExprs = new SQLExpression[orderMapping.getNumberOfDatastoreMappings()];
boolean[] descendingOrder = new boolean[orderMapping.getNumberOfDatastoreMappings()];
orderExprs[0] = exprFactory.newExpression(sqlStmt, orderSqlTbl, orderMapping);
sqlStmt.setOrdering(orderExprs, descendingOrder);
}
return new IteratorStatement(this, sqlStmt, iteratorMappingClass);
}
use of org.datanucleus.store.rdbms.sql.expression.SQLExpressionFactory in project datanucleus-rdbms by datanucleus.
the class JoinArrayStore method getIteratorStatement.
/**
* Method to return the SQLStatement and mapping for an iterator for this backing store.
* Create a statement of the form
* <pre>
* SELECT ELEM_COLS
* FROM JOIN_TBL
* [JOIN ELEM_TBL ON ELEM_TBL.ID = JOIN_TBL.ELEM_ID]
* [WHERE]
* [JOIN_TBL.OWNER_ID = {value}] [AND]
* [JOIN_TBL.DISCRIM = {discrimValue}]
* [ORDER BY {orderClause}]
* </pre>
* @param ec ExecutionContext
* @param fp FetchPlan to use in determing which fields of element to select
* @param addRestrictionOnOwner Whether to restrict to a particular owner (otherwise functions as bulk fetch for many owners).
* @return The SQLStatement and its associated StatementClassMapping
*/
public IteratorStatement getIteratorStatement(ExecutionContext ec, FetchPlan fp, boolean addRestrictionOnOwner) {
SelectStatement sqlStmt = null;
SQLExpressionFactory exprFactory = storeMgr.getSQLExpressionFactory();
StatementClassMapping iteratorMappingClass = null;
if (elementsAreEmbedded || elementsAreSerialised) {
// Element = embedded, serialised (maybe Non-PC)
// Just select the join table since we're going to return the embedded/serialised columns from it
sqlStmt = new SelectStatement(storeMgr, containerTable, null, null);
sqlStmt.setClassLoaderResolver(clr);
// Select the element column - first select is assumed by SetStoreIterator
sqlStmt.select(sqlStmt.getPrimaryTable(), elementMapping, null);
// TODO If embedded element and it includes 1-1/N-1 in FetchPlan then select its fields also
} else if (elementMapping instanceof ReferenceMapping) {
// Element = Reference type (interface/Object)
// Just select the join table since we're going to return the implementation id columns only
sqlStmt = new SelectStatement(storeMgr, containerTable, null, null);
sqlStmt.setClassLoaderResolver(clr);
// Select the reference column(s) - first select is assumed by SetStoreIterator
sqlStmt.select(sqlStmt.getPrimaryTable(), elementMapping, null);
} else {
// Element = PC
// Join to the element table(s)
iteratorMappingClass = new StatementClassMapping();
for (int i = 0; i < elementInfo.length; i++) {
// TODO This will only work if all element types have a discriminator
final int elementNo = i;
final Class elementCls = clr.classForName(elementInfo[elementNo].getClassName());
SelectStatement elementStmt = null;
if (elementInfo[elementNo].getDiscriminatorStrategy() != null && elementInfo[elementNo].getDiscriminatorStrategy() != DiscriminatorStrategy.NONE) {
// The element uses a discriminator so just use that in the SELECT
String elementType = ownerMemberMetaData.getCollection().getElementType();
if (ClassUtils.isReferenceType(clr.classForName(elementType))) {
String[] clsNames = storeMgr.getNucleusContext().getMetaDataManager().getClassesImplementingInterface(elementType, clr);
Class[] cls = new Class[clsNames.length];
for (int j = 0; j < clsNames.length; j++) {
cls[j] = clr.classForName(clsNames[j]);
}
SelectStatementGenerator stmtGen = new DiscriminatorStatementGenerator(storeMgr, clr, cls, true, null, null, containerTable, null, elementMapping);
if (allowNulls) {
stmtGen.setOption(SelectStatementGenerator.OPTION_ALLOW_NULLS);
}
elementStmt = stmtGen.getStatement(ec);
} else {
SelectStatementGenerator stmtGen = new DiscriminatorStatementGenerator(storeMgr, clr, elementCls, true, null, null, containerTable, null, elementMapping);
if (allowNulls) {
stmtGen.setOption(SelectStatementGenerator.OPTION_ALLOW_NULLS);
}
elementStmt = stmtGen.getStatement(ec);
}
iterateUsingDiscriminator = true;
} else {
// No discriminator, but subclasses so use UNIONs
SelectStatementGenerator stmtGen = new UnionStatementGenerator(storeMgr, clr, elementCls, true, null, null, containerTable, null, elementMapping);
stmtGen.setOption(SelectStatementGenerator.OPTION_SELECT_DN_TYPE);
if (allowNulls) {
stmtGen.setOption(SelectStatementGenerator.OPTION_ALLOW_NULLS);
}
iteratorMappingClass.setNucleusTypeColumnName(UnionStatementGenerator.DN_TYPE_COLUMN);
elementStmt = stmtGen.getStatement(ec);
}
if (sqlStmt == null) {
sqlStmt = elementStmt;
} else {
sqlStmt.union(elementStmt);
}
}
if (sqlStmt == null) {
throw new NucleusException("Error in generation of SQL statement for iterator over (Join) array. Statement is null");
}
// Select the required fields
SQLTable elementSqlTbl = sqlStmt.getTable(elementInfo[0].getDatastoreClass(), sqlStmt.getPrimaryTable().getGroupName());
SQLStatementHelper.selectFetchPlanOfSourceClassInStatement(sqlStmt, iteratorMappingClass, fp, elementSqlTbl, elementCmd, fp.getMaxFetchDepth());
}
if (addRestrictionOnOwner) {
// Apply condition on join-table owner field to filter by owner
SQLTable ownerSqlTbl = SQLStatementHelper.getSQLTableForMappingOfTable(sqlStmt, sqlStmt.getPrimaryTable(), ownerMapping);
SQLExpression ownerExpr = exprFactory.newExpression(sqlStmt, ownerSqlTbl, ownerMapping);
SQLExpression ownerVal = exprFactory.newLiteralParameter(sqlStmt, ownerMapping, null, "OWNER");
sqlStmt.whereAnd(ownerExpr.eq(ownerVal), true);
}
if (relationDiscriminatorMapping != null) {
// Apply condition on distinguisher field to filter by distinguisher (when present)
SQLTable distSqlTbl = SQLStatementHelper.getSQLTableForMappingOfTable(sqlStmt, sqlStmt.getPrimaryTable(), relationDiscriminatorMapping);
SQLExpression distExpr = exprFactory.newExpression(sqlStmt, distSqlTbl, relationDiscriminatorMapping);
SQLExpression distVal = exprFactory.newLiteral(sqlStmt, relationDiscriminatorMapping, relationDiscriminatorValue);
sqlStmt.whereAnd(distExpr.eq(distVal), true);
}
if (orderMapping != null) {
// Order by the ordering column, when present
SQLTable orderSqlTbl = SQLStatementHelper.getSQLTableForMappingOfTable(sqlStmt, sqlStmt.getPrimaryTable(), orderMapping);
SQLExpression[] orderExprs = new SQLExpression[orderMapping.getNumberOfDatastoreMappings()];
boolean[] descendingOrder = new boolean[orderMapping.getNumberOfDatastoreMappings()];
orderExprs[0] = exprFactory.newExpression(sqlStmt, orderSqlTbl, orderMapping);
sqlStmt.setOrdering(orderExprs, descendingOrder);
}
return new IteratorStatement(this, sqlStmt, iteratorMappingClass);
}
use of org.datanucleus.store.rdbms.sql.expression.SQLExpressionFactory in project datanucleus-rdbms by datanucleus.
the class JoinSetStore method getIteratorStatement.
/**
* Method to return the SQLStatement and mapping for an iterator for this backing store.
* Create a statement of the form
* <pre>
* SELECT ELEM_COLS
* FROM JOIN_TBL
* [JOIN ELEM_TBL ON ELEM_TBL.ID = JOIN_TBL.ELEM_ID]
* [WHERE]
* [JOIN_TBL.OWNER_ID = {value}] [AND]
* [JOIN_TBL.DISCRIM = {discrimValue}]
* [ORDER BY {orderClause}]
* </pre>
* @param ec ExecutionContext
* @param fp FetchPlan to use in determining which fields of element to select
* @param addRestrictionOnOwner Whether to restrict to a particular owner (otherwise functions as bulk fetch for many owners).
* @return The SQLStatement and its associated StatementClassMapping
*/
public IteratorStatement getIteratorStatement(ExecutionContext ec, FetchPlan fp, boolean addRestrictionOnOwner) {
SelectStatement sqlStmt = null;
SQLExpressionFactory exprFactory = storeMgr.getSQLExpressionFactory();
StatementClassMapping iteratorMappingClass = null;
if (elementsAreEmbedded || elementsAreSerialised) {
// Element = embedded, serialised (maybe Non-PC)
// Just select the join table since we're going to return the embedded/serialised columns from it
sqlStmt = new SelectStatement(storeMgr, containerTable, null, null);
sqlStmt.setClassLoaderResolver(clr);
// Select the element column - first select is assumed by SetStoreIterator
sqlStmt.select(sqlStmt.getPrimaryTable(), elementMapping, null);
// TODO If embedded element and it includes 1-1/N-1 in FetchPlan then select its fields also
} else if (elementMapping instanceof ReferenceMapping) {
// Element = Reference type (interface/Object)
// Just select the join table since we're going to return the implementation id columns only
sqlStmt = new SelectStatement(storeMgr, containerTable, null, null);
sqlStmt.setClassLoaderResolver(clr);
// Select the reference column(s) - first select is assumed by SetStoreIterator
sqlStmt.select(sqlStmt.getPrimaryTable(), elementMapping, null);
} else {
// Element = PC
// Join to the element table(s)
iteratorMappingClass = new StatementClassMapping();
for (int i = 0; i < elementInfo.length; i++) {
final int elementNo = i;
final Class elementCls = clr.classForName(elementInfo[elementNo].getClassName());
SelectStatement elementStmt = null;
if (elementInfo[elementNo].getDiscriminatorStrategy() != null && elementInfo[elementNo].getDiscriminatorStrategy() != DiscriminatorStrategy.NONE) {
// The element uses a discriminator so just use that in the SELECT
String elementType = ownerMemberMetaData.getCollection().getElementType();
if (ClassUtils.isReferenceType(clr.classForName(elementType))) {
String[] clsNames = storeMgr.getNucleusContext().getMetaDataManager().getClassesImplementingInterface(elementType, clr);
Class[] cls = new Class[clsNames.length];
for (int j = 0; j < clsNames.length; j++) {
cls[j] = clr.classForName(clsNames[j]);
}
SelectStatementGenerator stmtGen = new DiscriminatorStatementGenerator(storeMgr, clr, cls, true, null, null, containerTable, null, elementMapping);
if (allowNulls) {
stmtGen.setOption(SelectStatementGenerator.OPTION_ALLOW_NULLS);
}
elementStmt = stmtGen.getStatement(ec);
} else {
SelectStatementGenerator stmtGen = new DiscriminatorStatementGenerator(storeMgr, clr, elementCls, true, null, null, containerTable, null, elementMapping);
if (allowNulls) {
stmtGen.setOption(SelectStatementGenerator.OPTION_ALLOW_NULLS);
}
elementStmt = stmtGen.getStatement(ec);
}
iterateUsingDiscriminator = true;
} else {
// No discriminator, but subclasses so use UNIONs
SelectStatementGenerator stmtGen = new UnionStatementGenerator(storeMgr, clr, elementCls, true, null, null, containerTable, null, elementMapping);
stmtGen.setOption(SelectStatementGenerator.OPTION_SELECT_DN_TYPE);
iteratorMappingClass.setNucleusTypeColumnName(UnionStatementGenerator.DN_TYPE_COLUMN);
elementStmt = stmtGen.getStatement(ec);
}
// TODO What if the first elementInfo has fields selected in one order and then the second in a different order?
if (sqlStmt == null) {
sqlStmt = elementStmt;
// Select the required fields
SQLTable elementSqlTbl = sqlStmt.getTable(elementInfo[i].getDatastoreClass(), sqlStmt.getPrimaryTable().getGroupName());
SQLStatementHelper.selectFetchPlanOfSourceClassInStatement(sqlStmt, iteratorMappingClass, fp, elementSqlTbl, elementCmd, fp.getMaxFetchDepth());
} else {
// Select the required fields
SQLTable elementSqlTbl = elementStmt.getTable(elementInfo[i].getDatastoreClass(), elementStmt.getPrimaryTable().getGroupName());
SQLStatementHelper.selectFetchPlanOfSourceClassInStatement(elementStmt, iteratorMappingClass, fp, elementSqlTbl, elementCmd, fp.getMaxFetchDepth());
sqlStmt.union(elementStmt);
}
}
}
if (sqlStmt == null) {
throw new NucleusException("Error in generation of SQL statement for iterator over (Join) set. Statement is null");
}
if (addRestrictionOnOwner) {
// Apply condition on join-table owner field to filter by owner
SQLTable ownerSqlTbl = SQLStatementHelper.getSQLTableForMappingOfTable(sqlStmt, sqlStmt.getPrimaryTable(), ownerMapping);
SQLExpression ownerExpr = exprFactory.newExpression(sqlStmt, ownerSqlTbl, ownerMapping);
SQLExpression ownerVal = exprFactory.newLiteralParameter(sqlStmt, ownerMapping, null, "OWNER");
sqlStmt.whereAnd(ownerExpr.eq(ownerVal), true);
}
if (relationDiscriminatorMapping != null) {
// Apply condition on distinguisher field to filter by distinguisher (when present)
SQLTable distSqlTbl = SQLStatementHelper.getSQLTableForMappingOfTable(sqlStmt, sqlStmt.getPrimaryTable(), relationDiscriminatorMapping);
SQLExpression distExpr = exprFactory.newExpression(sqlStmt, distSqlTbl, relationDiscriminatorMapping);
SQLExpression distVal = exprFactory.newLiteral(sqlStmt, relationDiscriminatorMapping, relationDiscriminatorValue);
sqlStmt.whereAnd(distExpr.eq(distVal), true);
}
if (orderMapping != null) {
// TODO If we have multiple roots then cannot allow this
// Order by the ordering column, when present
SQLTable orderSqlTbl = SQLStatementHelper.getSQLTableForMappingOfTable(sqlStmt, sqlStmt.getPrimaryTable(), orderMapping);
SQLExpression[] orderExprs = new SQLExpression[orderMapping.getNumberOfDatastoreMappings()];
boolean[] descendingOrder = new boolean[orderMapping.getNumberOfDatastoreMappings()];
orderExprs[0] = exprFactory.newExpression(sqlStmt, orderSqlTbl, orderMapping);
sqlStmt.setOrdering(orderExprs, descendingOrder);
}
return new IteratorStatement(this, sqlStmt, iteratorMappingClass);
}
use of org.datanucleus.store.rdbms.sql.expression.SQLExpressionFactory in project datanucleus-rdbms by datanucleus.
the class MapEntrySetStore method getSQLStatementForIterator.
/**
* Method to generate an SQLStatement for iterating through entries of the map.
* Creates a statement that selects the table holding the map definition (key/value mappings).
* Adds a restriction on the ownerMapping of the containerTable so we can restrict to the owner object.
* Adds a restriction on the keyMapping not being null.
* <pre>
* SELECT KEY, VALUE FROM MAP_TABLE WHERE OWNER_ID=? AND KEY IS NOT NULL
* </pre>
* @param ownerOP ObjectProvider for the owner object
* @return The SQLStatement
*/
protected SQLStatement getSQLStatementForIterator(ObjectProvider ownerOP) {
SelectStatement sqlStmt = new SelectStatement(storeMgr, mapTable, null, null);
sqlStmt.setClassLoaderResolver(clr);
// Select the key mapping
// TODO If key is persistable and has inheritance also select a discriminator to get the type
SQLTable entrySqlTblForKey = sqlStmt.getPrimaryTable();
if (keyMapping.getTable() != mapTable) {
entrySqlTblForKey = sqlStmt.getTableForDatastoreContainer(keyMapping.getTable());
if (entrySqlTblForKey == null) {
// Add join to key table
entrySqlTblForKey = sqlStmt.join(JoinType.INNER_JOIN, sqlStmt.getPrimaryTable(), sqlStmt.getPrimaryTable().getTable().getIdMapping(), keyMapping.getTable(), null, keyMapping.getTable().getIdMapping(), null, null, true);
}
}
iteratorKeyResultCols = sqlStmt.select(entrySqlTblForKey, keyMapping, null);
// Select the value mapping
// TODO If value is persistable and has inheritance also select a discriminator to get the type
SQLTable entrySqlTblForVal = sqlStmt.getPrimaryTable();
if (valueMapping.getTable() != mapTable) {
entrySqlTblForVal = sqlStmt.getTableForDatastoreContainer(valueMapping.getTable());
if (entrySqlTblForVal == null) {
// Add join to key table
entrySqlTblForVal = sqlStmt.join(JoinType.INNER_JOIN, sqlStmt.getPrimaryTable(), sqlStmt.getPrimaryTable().getTable().getIdMapping(), valueMapping.getTable(), null, valueMapping.getTable().getIdMapping(), null, null, true);
}
}
iteratorValueResultCols = sqlStmt.select(entrySqlTblForVal, valueMapping, null);
// Apply condition on owner field to filter by owner
SQLExpressionFactory exprFactory = storeMgr.getSQLExpressionFactory();
SQLTable ownerSqlTbl = SQLStatementHelper.getSQLTableForMappingOfTable(sqlStmt, sqlStmt.getPrimaryTable(), ownerMapping);
SQLExpression ownerExpr = exprFactory.newExpression(sqlStmt, ownerSqlTbl, ownerMapping);
SQLExpression ownerVal = exprFactory.newLiteralParameter(sqlStmt, ownerMapping, null, "OWNER");
sqlStmt.whereAnd(ownerExpr.eq(ownerVal), true);
// Apply condition that key is not null
SQLExpression keyExpr = exprFactory.newExpression(sqlStmt, sqlStmt.getPrimaryTable(), keyMapping);
SQLExpression nullExpr = exprFactory.newLiteral(sqlStmt, null, null);
sqlStmt.whereAnd(keyExpr.ne(nullExpr), true);
// Input parameter(s) - the owner
int inputParamNum = 1;
StatementMappingIndex ownerIdx = new StatementMappingIndex(ownerMapping);
if (sqlStmt.getNumberOfUnions() > 0) {
// Add parameter occurrence for each union of statement
for (int j = 0; j < sqlStmt.getNumberOfUnions() + 1; j++) {
int[] paramPositions = new int[ownerMapping.getNumberOfDatastoreMappings()];
for (int k = 0; k < ownerMapping.getNumberOfDatastoreMappings(); k++) {
paramPositions[k] = inputParamNum++;
}
ownerIdx.addParameterOccurrence(paramPositions);
}
} else {
int[] paramPositions = new int[ownerMapping.getNumberOfDatastoreMappings()];
for (int k = 0; k < ownerMapping.getNumberOfDatastoreMappings(); k++) {
paramPositions[k] = inputParamNum++;
}
ownerIdx.addParameterOccurrence(paramPositions);
}
iteratorMappingParams = new StatementParameterMapping();
iteratorMappingParams.addMappingForParameter("owner", ownerIdx);
return sqlStmt;
}
Aggregations