use of org.datanucleus.store.rdbms.query.StatementMappingIndex in project datanucleus-rdbms by datanucleus.
the class MapEntrySetStore method iterator.
/**
* Method returning an iterator across the entries in the map for this owner object.
* @param ownerSM StateManager of the owning object
* @return The iterator for the entries (<pre>map.entrySet().iterator()</pre>).
*/
public Iterator<Map.Entry<K, V>> iterator(DNStateManager ownerSM) {
ExecutionContext ec = ownerSM.getExecutionContext();
Boolean serializeRead = ec.getTransaction().getSerializeRead();
String stmtSql = serializeRead ? iteratorSelectStmtLockedSql : iteratorSelectStmtSql;
if (stmtSql == null) {
synchronized (// Make sure this completes in case another thread needs the same info
this) {
// Generate the statement
SelectStatement selectStmt = getSQLStatementForIterator(ownerSM, ec.getFetchPlan(), true);
// Input parameter(s) - the owner
int inputParamNum = 1;
StatementMappingIndex ownerIdx = new StatementMappingIndex(ownerMapping);
if (selectStmt.getNumberOfUnions() > 0) {
// Add parameter occurrence for each union of statement
for (int j = 0; j < selectStmt.getNumberOfUnions() + 1; j++) {
int[] paramPositions = new int[ownerMapping.getNumberOfColumnMappings()];
for (int k = 0; k < ownerMapping.getNumberOfColumnMappings(); k++) {
paramPositions[k] = inputParamNum++;
}
ownerIdx.addParameterOccurrence(paramPositions);
}
} else {
int[] paramPositions = new int[ownerMapping.getNumberOfColumnMappings()];
for (int k = 0; k < ownerMapping.getNumberOfColumnMappings(); k++) {
paramPositions[k] = inputParamNum++;
}
ownerIdx.addParameterOccurrence(paramPositions);
}
iteratorMappingParams = new StatementParameterMapping();
iteratorMappingParams.addMappingForParameter("owner", ownerIdx);
// Save the two possible select statements (normal, locked)
iteratorSelectStmtSql = selectStmt.getSQLText().toSQL();
selectStmt.addExtension(SQLStatement.EXTENSION_LOCK_FOR_UPDATE, true);
iteratorSelectStmtLockedSql = selectStmt.getSQLText().toSQL();
}
stmtSql = serializeRead ? iteratorSelectStmtLockedSql : iteratorSelectStmtSql;
}
try {
ManagedConnection mconn = storeMgr.getConnectionManager().getConnection(ec);
SQLController sqlControl = storeMgr.getSQLController();
try {
// Create the statement and set the owner
PreparedStatement ps = sqlControl.getStatementForQuery(mconn, stmtSql);
StatementMappingIndex ownerIdx = iteratorMappingParams.getMappingForParameter("owner");
int numParams = ownerIdx.getNumberOfParameterOccurrences();
for (int paramInstance = 0; paramInstance < numParams; paramInstance++) {
ownerIdx.getMapping().setObject(ec, ps, ownerIdx.getParameterPositionsForOccurrence(paramInstance), ownerSM.getObject());
}
try {
ResultSet rs = sqlControl.executeStatementQuery(ec, mconn, stmtSql, ps);
try {
return new SetIterator(ownerSM, this, ownerMemberMetaData, rs, iteratorKeyResultCols, iteratorValueResultCols) {
protected boolean next(Object rs) {
try {
return ((ResultSet) rs).next();
} catch (SQLException e) {
throw new NucleusDataStoreException("SQLException", e);
}
}
};
} finally {
rs.close();
}
} finally {
sqlControl.closeStatement(mconn, ps);
}
} finally {
mconn.release();
}
} catch (SQLException e) {
throw new NucleusDataStoreException(Localiser.msg("056012", stmtSql), e);
}
}
use of org.datanucleus.store.rdbms.query.StatementMappingIndex in project datanucleus-rdbms by datanucleus.
the class MapValueCollectionStore method getSQLStatementForIterator.
/**
* Method to generate an SQLStatement for iterating through values of the map.
* Populates the iteratorMappingDef and iteratorMappingParams.
* Creates a statement that selects the value table(s), and adds any necessary join to the containerTable
* if that is not the value table. If the value is embedded then selects the table it is embedded in.
* Adds a restriction on the ownerMapping of the containerTable so we can restrict to the owner object.
* @param ownerSM StateManager for the owner object
* @return The SQLStatement
*/
protected SelectStatement getSQLStatementForIterator(DNStateManager ownerSM) {
SelectStatement sqlStmt = null;
ExecutionContext ec = ownerSM.getExecutionContext();
final ClassLoaderResolver clr = ec.getClassLoaderResolver();
final Class valueCls = clr.classForName(elementType);
SQLTable containerSqlTbl = null;
MapType mapType = getOwnerMemberMetaData().getMap().getMapType();
FetchPlan fp = ec.getFetchPlan();
if (elementCmd != null && elementCmd.getDiscriminatorStrategyForTable() != null && elementCmd.getDiscriminatorStrategyForTable() != DiscriminatorStrategy.NONE) {
// Map<?, PC> where value has discriminator
if (ClassUtils.isReferenceType(valueCls)) {
// Take the metadata for the first implementation of the reference type
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);
sqlStmt = stmtGen.getStatement(ec);
} else {
SelectStatementGenerator stmtGen = new DiscriminatorStatementGenerator(storeMgr, clr, valueCls, true, null, null);
sqlStmt = stmtGen.getStatement(ec);
}
iterateUsingDiscriminator = true;
if (mapType == MapType.MAP_TYPE_VALUE_IN_KEY) {
// Join to key table and select value fields
JavaTypeMapping valueIdMapping = sqlStmt.getPrimaryTable().getTable().getIdMapping();
containerSqlTbl = sqlStmt.join(JoinType.INNER_JOIN, sqlStmt.getPrimaryTable(), valueIdMapping, containerTable, null, elementMapping, null, null, true);
iteratorMappingDef = new StatementClassMapping();
SQLStatementHelper.selectFetchPlanOfSourceClassInStatement(sqlStmt, iteratorMappingDef, fp, sqlStmt.getPrimaryTable(), elementCmd, fp.getMaxFetchDepth());
} else if (mapType == MapType.MAP_TYPE_KEY_IN_VALUE) {
// Select value fields
containerSqlTbl = sqlStmt.getPrimaryTable();
iteratorMappingDef = new StatementClassMapping();
SQLStatementHelper.selectFetchPlanOfSourceClassInStatement(sqlStmt, iteratorMappingDef, fp, sqlStmt.getPrimaryTable(), elementCmd, fp.getMaxFetchDepth());
} else {
// Join to join table and select value fields
JavaTypeMapping valueIdMapping = sqlStmt.getPrimaryTable().getTable().getIdMapping();
containerSqlTbl = sqlStmt.join(JoinType.INNER_JOIN, sqlStmt.getPrimaryTable(), valueIdMapping, containerTable, null, elementMapping, null, null, true);
iteratorMappingDef = new StatementClassMapping();
SQLStatementHelper.selectFetchPlanOfSourceClassInStatement(sqlStmt, iteratorMappingDef, fp, sqlStmt.getPrimaryTable(), elementCmd, fp.getMaxFetchDepth());
}
} else {
if (mapType == MapType.MAP_TYPE_VALUE_IN_KEY) {
if (elementCmd != null) {
// TODO Allow for null value [change to select the key table and left outer join to the key]
// Select of value table, joining to key table
iteratorMappingDef = new StatementClassMapping();
UnionStatementGenerator stmtGen = new UnionStatementGenerator(storeMgr, clr, valueCls, true, null, null);
stmtGen.setOption(SelectStatementGenerator.OPTION_SELECT_DN_TYPE);
iteratorMappingDef.setNucleusTypeColumnName(UnionStatementGenerator.DN_TYPE_COLUMN);
sqlStmt = stmtGen.getStatement(ec);
JavaTypeMapping valueIdMapping = sqlStmt.getPrimaryTable().getTable().getIdMapping();
containerSqlTbl = sqlStmt.join(JoinType.INNER_JOIN, sqlStmt.getPrimaryTable(), valueIdMapping, containerTable, null, elementMapping, null, null, true);
SQLStatementHelper.selectFetchPlanOfSourceClassInStatement(sqlStmt, iteratorMappingDef, fp, sqlStmt.getPrimaryTable(), elementCmd, fp.getMaxFetchDepth());
} else {
// Select of value in key table
sqlStmt = new SelectStatement(storeMgr, containerTable, null, null);
sqlStmt.setClassLoaderResolver(clr);
containerSqlTbl = sqlStmt.getPrimaryTable();
SQLTable elemSqlTblForValue = containerSqlTbl;
if (elementMapping.getTable() != containerSqlTbl.getTable()) {
elemSqlTblForValue = sqlStmt.getTableForDatastoreContainer(elementMapping.getTable());
if (elemSqlTblForValue == null) {
// Add join to key table holding value
elemSqlTblForValue = sqlStmt.join(JoinType.INNER_JOIN, sqlStmt.getPrimaryTable(), sqlStmt.getPrimaryTable().getTable().getIdMapping(), elementMapping.getTable(), null, elementMapping.getTable().getIdMapping(), null, null, true);
}
}
sqlStmt.select(elemSqlTblForValue, elementMapping, null);
}
} else if (mapType == MapType.MAP_TYPE_KEY_IN_VALUE) {
// Select of value in value table (allow union of possible value types)
iteratorMappingDef = new StatementClassMapping();
UnionStatementGenerator stmtGen = new UnionStatementGenerator(storeMgr, clr, valueCls, true, null, null);
stmtGen.setOption(SelectStatementGenerator.OPTION_SELECT_DN_TYPE);
iteratorMappingDef.setNucleusTypeColumnName(UnionStatementGenerator.DN_TYPE_COLUMN);
sqlStmt = stmtGen.getStatement(ec);
containerSqlTbl = sqlStmt.getPrimaryTable();
SQLStatementHelper.selectFetchPlanOfSourceClassInStatement(sqlStmt, iteratorMappingDef, fp, sqlStmt.getPrimaryTable(), elementCmd, fp.getMaxFetchDepth());
} else {
if (elementCmd != null) {
// TODO Allow for null value [change to select the join table and left outer join to the key]
// Select of value table, joining to key table
iteratorMappingDef = new StatementClassMapping();
UnionStatementGenerator stmtGen = new UnionStatementGenerator(storeMgr, clr, valueCls, true, null, null);
stmtGen.setOption(SelectStatementGenerator.OPTION_SELECT_DN_TYPE);
iteratorMappingDef.setNucleusTypeColumnName(UnionStatementGenerator.DN_TYPE_COLUMN);
sqlStmt = stmtGen.getStatement(ec);
JavaTypeMapping valueIdMapping = sqlStmt.getPrimaryTable().getTable().getIdMapping();
containerSqlTbl = sqlStmt.join(JoinType.INNER_JOIN, sqlStmt.getPrimaryTable(), valueIdMapping, containerTable, null, elementMapping, null, null, true);
SQLStatementHelper.selectFetchPlanOfSourceClassInStatement(sqlStmt, iteratorMappingDef, fp, sqlStmt.getPrimaryTable(), elementCmd, fp.getMaxFetchDepth());
} else {
// Select of value in join table
sqlStmt = new SelectStatement(storeMgr, containerTable, null, null);
containerSqlTbl = sqlStmt.getPrimaryTable();
sqlStmt.select(sqlStmt.getPrimaryTable(), elementMapping, null);
}
}
}
// Apply condition on owner field to filter by owner
SQLExpressionFactory exprFactory = storeMgr.getSQLExpressionFactory();
SQLTable ownerSqlTbl = SQLStatementHelper.getSQLTableForMappingOfTable(sqlStmt, containerSqlTbl, ownerMapping);
SQLExpression ownerExpr = exprFactory.newExpression(sqlStmt, ownerSqlTbl, ownerMapping);
SQLExpression ownerVal = exprFactory.newLiteralParameter(sqlStmt, ownerMapping, null, "OWNER");
sqlStmt.whereAnd(ownerExpr.eq(ownerVal), 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.getNumberOfColumnMappings()];
for (int k = 0; k < ownerMapping.getNumberOfColumnMappings(); k++) {
paramPositions[k] = inputParamNum++;
}
ownerIdx.addParameterOccurrence(paramPositions);
}
} else {
int[] paramPositions = new int[ownerMapping.getNumberOfColumnMappings()];
for (int k = 0; k < ownerMapping.getNumberOfColumnMappings(); k++) {
paramPositions[k] = inputParamNum++;
}
ownerIdx.addParameterOccurrence(paramPositions);
}
iteratorMappingParams = new StatementParameterMapping();
iteratorMappingParams.addMappingForParameter("owner", ownerIdx);
return sqlStmt;
}
use of org.datanucleus.store.rdbms.query.StatementMappingIndex in project datanucleus-rdbms by datanucleus.
the class SQLStatementHelper method selectIdentityOfCandidateInStatement.
/**
* Method to select the identity for the candidate class.
* The supplied statement and mapping definition are updated during this method.
* Selects the datastore id (if using datastore id) as "DN_DATASTOREID",
* the version (if present) as "DN_VERSION", the discriminator (if present) as "DN_DISCRIM",
* and the application id (if using application id) as "DN_APPID_{i}"
* @param stmt The statement
* @param mappingDefinition Mapping definition for result columns
* @param candidateCmd The candidate class meta-data
*/
public static void selectIdentityOfCandidateInStatement(SelectStatement stmt, StatementClassMapping mappingDefinition, AbstractClassMetaData candidateCmd) {
DatastoreClass candidateTbl = (DatastoreClass) stmt.getPrimaryTable().getTable();
if (candidateCmd.getIdentityType() == IdentityType.DATASTORE) {
// Datastore-identity surrogate column
JavaTypeMapping idMapping = candidateTbl.getSurrogateMapping(SurrogateColumnType.DATASTORE_ID, false);
int[] colNumbers = stmt.select(stmt.getPrimaryTable(), idMapping, "DN_DATASTOREID", false);
if (mappingDefinition != null) {
StatementMappingIndex datastoreIdIdx = new StatementMappingIndex(idMapping);
datastoreIdIdx.setColumnPositions(colNumbers);
mappingDefinition.addMappingForMember(SurrogateColumnType.DATASTORE_ID.getFieldNumber(), datastoreIdIdx);
}
} else if (candidateCmd.getIdentityType() == IdentityType.APPLICATION) {
// Application-identity column(s)
int[] pkPositions = candidateCmd.getPKMemberPositions();
String alias = "DN_APPID";
for (int i = 0; i < pkPositions.length; i++) {
AbstractMemberMetaData pkMmd = candidateCmd.getMetaDataForManagedMemberAtAbsolutePosition(pkPositions[i]);
JavaTypeMapping pkMapping = candidateTbl.getMemberMapping(pkMmd);
SQLTable sqlTbl = SQLStatementHelper.getSQLTableForMappingOfTable(stmt, stmt.getPrimaryTable(), pkMapping);
if (pkPositions.length > 1) {
alias = "DN_APPID" + i;
}
int[] colNumbers = stmt.select(sqlTbl, pkMapping, alias, false);
if (mappingDefinition != null) {
StatementMappingIndex appIdIdx = new StatementMappingIndex(pkMapping);
appIdIdx.setColumnPositions(colNumbers);
mappingDefinition.addMappingForMember(pkPositions[i], appIdIdx);
}
}
}
JavaTypeMapping verMapping = candidateTbl.getSurrogateMapping(SurrogateColumnType.VERSION, true);
if (verMapping != null) {
// Version surrogate column (adds inner join to any required superclass table)
SQLTable versionSqlTbl = SQLStatementHelper.getSQLTableForMappingOfTable(stmt, stmt.getPrimaryTable(), verMapping);
int[] colNumbers = stmt.select(versionSqlTbl, verMapping, "DN_VERSION", false);
if (mappingDefinition != null) {
StatementMappingIndex versionIdx = new StatementMappingIndex(verMapping);
versionIdx.setColumnPositions(colNumbers);
mappingDefinition.addMappingForMember(SurrogateColumnType.VERSION.getFieldNumber(), versionIdx);
}
}
JavaTypeMapping discrimMapping = candidateTbl.getSurrogateMapping(SurrogateColumnType.DISCRIMINATOR, true);
if (discrimMapping != null) {
// Discriminator surrogate column (adds inner join to any required superclass table)
SQLTable discrimSqlTbl = SQLStatementHelper.getSQLTableForMappingOfTable(stmt, stmt.getPrimaryTable(), discrimMapping);
int[] colNumbers = stmt.select(discrimSqlTbl, discrimMapping, "DN_DISCRIM", false);
if (mappingDefinition != null) {
StatementMappingIndex discrimIdx = new StatementMappingIndex(discrimMapping);
discrimIdx.setColumnPositions(colNumbers);
mappingDefinition.addMappingForMember(SurrogateColumnType.DISCRIMINATOR.getFieldNumber(), discrimIdx);
}
}
List<SelectStatement> unionStmts = stmt.getUnions();
if (unionStmts != null) {
Iterator<SelectStatement> iter = unionStmts.iterator();
while (iter.hasNext()) {
SelectStatement unionStmt = iter.next();
selectIdentityOfCandidateInStatement(unionStmt, null, candidateCmd);
}
}
}
use of org.datanucleus.store.rdbms.query.StatementMappingIndex in project datanucleus-rdbms by datanucleus.
the class SQLStatementHelper method selectFetchPlanOfSourceClassInStatement.
/**
* Method to select all fetch plan members for the "source" class.
* If the passed FetchPlan is null then the default fetch group fields will be selected.
* The source class is defined by the supplied meta-data, and the SQLTable that we are selecting from.
* The supplied statement and mapping definition are updated during this method.
* @param stmt The statement
* @param mappingDefinition Mapping definition for result columns (populated with column positions
* of any selected mappings if provided as input)
* @param fetchPlan FetchPlan in use
* @param sourceSqlTbl SQLTable for the source class that we select from
* @param sourceCmd Meta-data for the source class
* @param maxFetchDepth Max fetch depth from this point to select (0 implies no other objects)
* @param inputJoinType Optional join type to use for subobjects (otherwise decide join type internally)
*/
public static void selectFetchPlanOfSourceClassInStatement(SelectStatement stmt, StatementClassMapping mappingDefinition, FetchPlan fetchPlan, SQLTable sourceSqlTbl, AbstractClassMetaData sourceCmd, int maxFetchDepth, JoinType inputJoinType) {
DatastoreClass sourceTbl = (DatastoreClass) sourceSqlTbl.getTable();
int[] fieldNumbers;
if (fetchPlan != null) {
// Use FetchPlan fields
fieldNumbers = fetchPlan.getFetchPlanForClass(sourceCmd).getMemberNumbers();
} else {
// Use DFG fields
fieldNumbers = sourceCmd.getDFGMemberPositions();
}
ClassLoaderResolver clr = stmt.getRDBMSManager().getNucleusContext().getClassLoaderResolver(null);
for (int fieldNumber : fieldNumbers) {
AbstractMemberMetaData mmd = sourceCmd.getMetaDataForManagedMemberAtAbsolutePosition(fieldNumber);
selectMemberOfSourceInStatement(stmt, mappingDefinition, fetchPlan, sourceSqlTbl, mmd, clr, maxFetchDepth, inputJoinType);
}
if (sourceCmd.getIdentityType() == IdentityType.DATASTORE) {
// Datastore-identity surrogate column
JavaTypeMapping idMapping = sourceTbl.getSurrogateMapping(SurrogateColumnType.DATASTORE_ID, false);
int[] colNumbers = stmt.select(sourceSqlTbl, idMapping, null);
if (mappingDefinition != null) {
StatementMappingIndex datastoreIdIdx = new StatementMappingIndex(idMapping);
datastoreIdIdx.setColumnPositions(colNumbers);
mappingDefinition.addMappingForMember(SurrogateColumnType.DATASTORE_ID.getFieldNumber(), datastoreIdIdx);
}
}
JavaTypeMapping verMapping = sourceTbl.getSurrogateMapping(SurrogateColumnType.VERSION, true);
if (verMapping != null) {
// Version surrogate column (adds inner join to any required superclass table)
SQLTable versionSqlTbl = SQLStatementHelper.getSQLTableForMappingOfTable(stmt, sourceSqlTbl, verMapping);
int[] colNumbers = stmt.select(versionSqlTbl, verMapping, null);
if (mappingDefinition != null) {
StatementMappingIndex versionIdx = new StatementMappingIndex(verMapping);
versionIdx.setColumnPositions(colNumbers);
mappingDefinition.addMappingForMember(SurrogateColumnType.VERSION.getFieldNumber(), versionIdx);
}
}
JavaTypeMapping discrimMapping = sourceTbl.getSurrogateMapping(SurrogateColumnType.DISCRIMINATOR, true);
if (discrimMapping != null) {
// Discriminator surrogate column (adds inner join to any required superclass table)
SQLTable discrimSqlTbl = SQLStatementHelper.getSQLTableForMappingOfTable(stmt, sourceSqlTbl, discrimMapping);
int[] colNumbers = stmt.select(discrimSqlTbl, discrimMapping, null);
if (mappingDefinition != null) {
StatementMappingIndex discrimIdx = new StatementMappingIndex(discrimMapping);
discrimIdx.setColumnPositions(colNumbers);
mappingDefinition.addMappingForMember(SurrogateColumnType.DISCRIMINATOR.getFieldNumber(), discrimIdx);
}
}
}
use of org.datanucleus.store.rdbms.query.StatementMappingIndex in project datanucleus-rdbms by datanucleus.
the class SQLStatementHelper method selectMemberOfSourceInStatement.
/**
* Method to select the specified member (field/property) of the source table in the passed SQL
* statement. This populates the mappingDefinition with the column details for this member.
* @param stmt The SQL statement
* @param mappingDefinition Mapping definition for the results (will be populated by any
* selected mappings if provided as input)
* @param fetchPlan FetchPlan
* @param sourceSqlTbl Table that has the member (or a super-table/secondary-table of this table)
* @param mmd Meta-data for the field/property in the source that we are selecting
* @param clr ClassLoader resolver
* @param maxFetchPlanLimit Max fetch depth from this point to select (0 implies no other objects)
* @param inputJoinType Optional join type to use for subobjects (otherwise decide join type internally)
*/
public static void selectMemberOfSourceInStatement(SelectStatement stmt, StatementClassMapping mappingDefinition, FetchPlan fetchPlan, SQLTable sourceSqlTbl, AbstractMemberMetaData mmd, ClassLoaderResolver clr, int maxFetchPlanLimit, JoinType inputJoinType) {
boolean selectSubobjects = false;
if (maxFetchPlanLimit > 0) {
selectSubobjects = true;
}
if (mmd.fetchFKOnly()) {
// Equivalent to recursion-depth=0
selectSubobjects = false;
}
if (fetchPlan != null) {
FetchPlanForClass fpClass = fetchPlan.getFetchPlanForClass(mmd.getAbstractClassMetaData());
if (RelationType.isRelationSingleValued(mmd.getRelationType(clr)) && fpClass.getRecursionDepthForMember(mmd.getAbsoluteFieldNumber()) == 0) {
// User has marked this member as recursion-depth=0 meaning pull in just the FK and dont join to the sub-object
selectSubobjects = false;
}
}
// Set table-group name for any related object we join to (naming based on member name)
String tableGroupName = sourceSqlTbl.getGroupName() + "." + mmd.getName();
JavaTypeMapping m = sourceSqlTbl.getTable().getMemberMapping(mmd);
if (m != null && m.includeInFetchStatement()) {
RelationType relationType = mmd.getRelationType(clr);
RDBMSStoreManager storeMgr = stmt.getRDBMSManager();
DatastoreAdapter dba = storeMgr.getDatastoreAdapter();
if (!dba.validToSelectMappingInStatement(stmt, m)) {
// Not valid to select this mapping for this statement so return
return;
}
MetaDataManager mmgr = storeMgr.getMetaDataManager();
StatementMappingIndex stmtMapping = new StatementMappingIndex(m);
if (m.getNumberOfColumnMappings() > 0) {
// Select of fields with columns in source table(s)
// Adds inner/outer join to any required superclass/secondary tables
SQLTable sqlTbl = SQLStatementHelper.getSQLTableForMappingOfTable(stmt, sourceSqlTbl, m);
boolean selectFK = true;
if (selectSubobjects && (relationType == RelationType.ONE_TO_ONE_UNI || (relationType == RelationType.ONE_TO_ONE_BI && mmd.getMappedBy() == null)) && !mmd.isSerialized() && !mmd.isEmbedded()) {
// Related object with FK at this side
selectFK = selectFetchPlanFieldsOfFKRelatedObject(stmt, mappingDefinition, fetchPlan, sourceSqlTbl, mmd, clr, maxFetchPlanLimit, m, tableGroupName, stmtMapping, sqlTbl, inputJoinType);
} else if (selectSubobjects && (!mmd.isEmbedded() && !mmd.isSerialized()) && relationType == RelationType.MANY_TO_ONE_BI) {
AbstractMemberMetaData[] relatedMmds = mmd.getRelatedMemberMetaData(clr);
if (mmd.getJoinMetaData() != null || relatedMmds[0].getJoinMetaData() != null) {
// N-1 bidirectional join table relation
// TODO Add left outer join from {sourceTable}.ID to {joinTable}.ELEM_FK
Table joinTable = storeMgr.getTable(relatedMmds[0]);
ElementContainerTable collTable = (ElementContainerTable) joinTable;
JavaTypeMapping selectMapping = collTable.getOwnerMapping();
SQLTable joinSqlTbl = null;
if (stmt.getPrimaryTable().getTable() != joinTable) {
// Join to the join table
JavaTypeMapping referenceMapping = collTable.getElementMapping();
joinSqlTbl = stmt.join(JoinType.LEFT_OUTER_JOIN, sourceSqlTbl, sourceSqlTbl.getTable().getIdMapping(), collTable, null, referenceMapping, null, tableGroupName, true);
} else {
// Main table of the statement is the join table so no need to join
joinSqlTbl = stmt.getPrimaryTable();
}
// Select the owner mapping of the join table
int[] colNumbers = stmt.select(joinSqlTbl, selectMapping, null);
stmtMapping.setColumnPositions(colNumbers);
// TODO Join to 1 side from join table?
} else {
// N-1 bidirectional FK relation
// Related object with FK at this side, so join/select related object as required
selectFK = selectFetchPlanFieldsOfFKRelatedObject(stmt, mappingDefinition, fetchPlan, sourceSqlTbl, mmd, clr, maxFetchPlanLimit, m, tableGroupName, stmtMapping, sqlTbl, inputJoinType);
}
}
if (selectFK) {
int[] colNumbers = stmt.select(sqlTbl, m, null);
stmtMapping.setColumnPositions(colNumbers);
}
} else {
// Select of related objects with FK in other table
if (relationType == RelationType.ONE_TO_ONE_BI && mmd.getMappedBy() != null) {
// 1-1 bidirectional relation with FK in related table
AbstractMemberMetaData[] relatedMmds = mmd.getRelatedMemberMetaData(clr);
AbstractMemberMetaData relatedMmd = relatedMmds[0];
String[] clsNames = null;
if (mmd.getType().isInterface()) {
if (mmd.getFieldTypes() != null && mmd.getFieldTypes().length == 1) {
// Use field-type since only one class specified
Class fldTypeCls = clr.classForName(mmd.getFieldTypes()[0]);
if (fldTypeCls.isInterface()) {
// User has specified an interface, so find its implementations
clsNames = mmgr.getClassesImplementingInterface(mmd.getFieldTypes()[0], clr);
} else {
// Use user-provided field-type
clsNames = new String[] { mmd.getFieldTypes()[0] };
}
}
if (clsNames == null) {
clsNames = mmgr.getClassesImplementingInterface(mmd.getTypeName(), clr);
}
} else {
String typeName = mmd.isSingleCollection() ? mmd.getCollection().getElementType() : mmd.getTypeName();
clsNames = new String[] { typeName };
}
DatastoreClass relatedTbl = storeMgr.getDatastoreClass(clsNames[0], clr);
JavaTypeMapping relatedMapping = relatedTbl.getMemberMapping(relatedMmd);
JavaTypeMapping relatedDiscrimMapping = relatedTbl.getSurrogateMapping(SurrogateColumnType.DISCRIMINATOR, true);
Object[] discrimValues = null;
JavaTypeMapping relatedTypeMapping = null;
AbstractClassMetaData relatedCmd = relatedMmd.getAbstractClassMetaData();
if (relatedDiscrimMapping != null && (relatedCmd.getSuperAbstractClassMetaData() != null || !relatedCmd.getFullClassName().equals(mmd.getTypeName()))) {
// Related table has a discriminator and the field can store other types
List discValueList = null;
for (String clsName : clsNames) {
List values = getDiscriminatorValuesForMember(clsName, relatedDiscrimMapping, storeMgr, clr);
if (discValueList == null) {
discValueList = values;
} else {
discValueList.addAll(values);
}
}
if (discValueList != null) {
discrimValues = discValueList.toArray(new Object[discValueList.size()]);
}
} else if (relatedTbl != relatedMapping.getTable()) {
// The relation is to a base class table, and the type stored is a sub-class
relatedTypeMapping = relatedTbl.getIdMapping();
}
SQLTable relatedSqlTbl = null;
if (relatedTypeMapping == null) {
// Join the 1-1 relation, if not already joined
relatedSqlTbl = stmt.getTable(relatedTbl, tableGroupName);
if (relatedSqlTbl == null) {
JoinType joinType = getJoinTypeForOneToOneRelationJoin(sourceSqlTbl.getTable().getIdMapping(), sourceSqlTbl, inputJoinType);
if (joinType == JoinType.LEFT_OUTER_JOIN || joinType == JoinType.RIGHT_OUTER_JOIN) {
inputJoinType = joinType;
}
relatedSqlTbl = addJoinForOneToOneRelation(stmt, sourceSqlTbl.getTable().getIdMapping(), sourceSqlTbl, relatedMapping, relatedTbl, null, discrimValues, tableGroupName, joinType);
}
// Select the id mapping in the related table
int[] colNumbers = stmt.select(relatedSqlTbl, relatedTbl.getIdMapping(), null);
stmtMapping.setColumnPositions(colNumbers);
} else {
DatastoreClass relationTbl = (DatastoreClass) relatedMapping.getTable();
if (relatedTbl != relatedMapping.getTable()) {
if (relatedMapping.isNullable()) {
// Nullable - left outer join from {sourceTable}.ID to {relatedBaseTable}.FK
// and inner join from {relatedBaseTable}.ID to {relatedTable}.ID
// (joins the relation and restricts to the right type)
relatedSqlTbl = stmt.join(JoinType.LEFT_OUTER_JOIN, sourceSqlTbl, sourceSqlTbl.getTable().getIdMapping(), relatedMapping.getTable(), null, relatedMapping, null, tableGroupName, true);
relatedSqlTbl = stmt.join(JoinType.INNER_JOIN, relatedSqlTbl, relatedMapping.getTable().getIdMapping(), relatedTbl, null, relatedTbl.getIdMapping(), null, tableGroupName, true);
} else {
// Not nullable - inner join from {sourceTable}.ID to {relatedBaseTable}.FK
// and inner join from {relatedBaseTable}.ID to {relatedTable}.ID
// (joins the relation and restricts to the right type)
relatedSqlTbl = stmt.join(JoinType.INNER_JOIN, sourceSqlTbl, sourceSqlTbl.getTable().getIdMapping(), relatedMapping.getTable(), null, relatedMapping, null, tableGroupName, true);
relatedSqlTbl = stmt.join(JoinType.INNER_JOIN, relatedSqlTbl, relatedMapping.getTable().getIdMapping(), relatedTbl, null, relatedTbl.getIdMapping(), null, tableGroupName, true);
}
} else {
// Join the 1-1 relation, if not already joined
relatedSqlTbl = stmt.getTable(relatedTbl, tableGroupName);
if (relatedSqlTbl == null) {
JoinType joinType = getJoinTypeForOneToOneRelationJoin(sourceSqlTbl.getTable().getIdMapping(), sourceSqlTbl, inputJoinType);
if (joinType == JoinType.LEFT_OUTER_JOIN || joinType == JoinType.RIGHT_OUTER_JOIN) {
inputJoinType = joinType;
}
relatedSqlTbl = addJoinForOneToOneRelation(stmt, sourceSqlTbl.getTable().getIdMapping(), sourceSqlTbl, relatedMapping, relationTbl, null, null, tableGroupName, joinType);
}
}
// Select the id mapping in the subclass of the related table
// Note this adds an inner join from relatedTable to its subclass
relatedSqlTbl = SQLStatementHelper.getSQLTableForMappingOfTable(stmt, relatedSqlTbl, relatedTbl.getIdMapping());
int[] colNumbers = stmt.select(relatedSqlTbl, relatedTbl.getIdMapping(), null);
stmtMapping.setColumnPositions(colNumbers);
}
if (selectSubobjects && !mmd.isSerialized() && !mmd.isEmbedded()) {
// Select the fetch-plan fields of the related object
StatementClassMapping subMappingDefinition = new StatementClassMapping(null, mmd.getName());
selectFetchPlanOfSourceClassInStatement(stmt, subMappingDefinition, fetchPlan, relatedSqlTbl, relatedMmd.getAbstractClassMetaData(), maxFetchPlanLimit - 1, inputJoinType);
if (mappingDefinition != null) {
mappingDefinition.addMappingDefinitionForMember(mmd.getAbsoluteFieldNumber(), subMappingDefinition);
}
}
} else if (relationType == RelationType.MANY_TO_ONE_BI) {
AbstractMemberMetaData[] relatedMmds = mmd.getRelatedMemberMetaData(clr);
if (mmd.getJoinMetaData() != null || relatedMmds[0].getJoinMetaData() != null) {
// N-1 bidirectional join table relation
// Add left outer join from {sourceTable}.ID to {joinTable}.ELEM_FK
Table joinTable = storeMgr.getTable(relatedMmds[0]);
ElementContainerTable collTable = (ElementContainerTable) joinTable;
JavaTypeMapping selectMapping = collTable.getOwnerMapping();
SQLTable joinSqlTbl = null;
if (stmt.getPrimaryTable().getTable() != joinTable) {
// Join to the join table
JavaTypeMapping referenceMapping = collTable.getElementMapping();
if (referenceMapping instanceof ReferenceMapping) {
// Join table has a reference mapping pointing to our table, so get the submapping for the implementation
ReferenceMapping refMap = (ReferenceMapping) referenceMapping;
Class implType = clr.classForName(mmd.getClassName(true));
referenceMapping = refMap.getJavaTypeMappingForType(implType);
}
joinSqlTbl = stmt.join(JoinType.LEFT_OUTER_JOIN, sourceSqlTbl, sourceSqlTbl.getTable().getIdMapping(), collTable, null, referenceMapping, null, tableGroupName + "_JOIN", true);
} else {
// Main table of the statement is the join table so no need to join
joinSqlTbl = stmt.getPrimaryTable();
}
// Select the owner mapping of the join table
int[] colNumbers = stmt.select(joinSqlTbl, selectMapping, null);
stmtMapping.setColumnPositions(colNumbers);
}
// TODO Select fetch plan fields of this related object
} else if (relationType == RelationType.MANY_TO_ONE_UNI) {
// Add left outer join from {sourceTable}.ID to {joinTable}.OWNER_FK
PersistableJoinTable joinTable = (PersistableJoinTable) storeMgr.getTable(mmd);
SQLTable joinSqlTbl = stmt.join(JoinType.LEFT_OUTER_JOIN, sourceSqlTbl, sourceSqlTbl.getTable().getIdMapping(), joinTable, null, joinTable.getOwnerMapping(), null, tableGroupName + "_JOIN", true);
int[] colNumbers = stmt.select(joinSqlTbl, joinTable.getRelatedMapping(), null);
stmtMapping.setColumnPositions(colNumbers);
// TODO Select fetch plan fields of this related object
}
}
if (mappingDefinition != null) {
mappingDefinition.addMappingForMember(mmd.getAbsoluteFieldNumber(), stmtMapping);
}
}
}
Aggregations