use of org.datanucleus.store.rdbms.sql.SQLTable in project datanucleus-rdbms by datanucleus.
the class QueryToSQLMapper method compileFromClassExpression.
/**
* Method to take a ClassExpression (in a FROM clause) and process the candidate and any
* linked JoinExpression(s), adding joins to the SQLStatement as required.
* @param clsExpr The ClassExpression
*/
protected void compileFromClassExpression(ClassExpression clsExpr) {
Symbol clsExprSym = clsExpr.getSymbol();
Class baseCls = (clsExprSym != null ? clsExprSym.getValueType() : null);
SQLTable candSqlTbl = stmt.getPrimaryTable();
MetaDataManager mmgr = storeMgr.getMetaDataManager();
AbstractClassMetaData cmd = mmgr.getMetaDataForClass(baseCls, clr);
if (baseCls != null && !candidateAlias.equals(clsExpr.getAlias())) {
// Not candidate class so must be cross join (JPA spec 4.4.5)
DatastoreClass candTbl = storeMgr.getDatastoreClass(baseCls.getName(), clr);
candSqlTbl = stmt.join(JoinType.CROSS_JOIN, null, null, null, candTbl, clsExpr.getAlias(), null, null, null, null, true, null);
SQLTableMapping tblMapping = new SQLTableMapping(candSqlTbl, cmd, candTbl.getIdMapping());
setSQLTableMappingForAlias(clsExpr.getAlias(), tblMapping);
}
if (clsExpr.getCandidateExpression() != null && parentMapper != null) {
// User defined the candidate of the subquery as an implied join to the outer query
// e.g SELECT c FROM Customer c WHERE EXISTS (SELECT o FROM c.orders o ...)
// so add the join(s) to the outer query
processFromClauseSubquery(clsExpr, candSqlTbl, mmgr);
}
// Process all linked JoinExpression(s) for this ClassExpression
Expression rightExpr = clsExpr.getRight();
SQLTable sqlTbl = candSqlTbl;
JavaTypeMapping previousMapping = null;
while (rightExpr != null) {
if (rightExpr instanceof JoinExpression) {
JoinExpression joinExpr = (JoinExpression) rightExpr;
JoinExpression.JoinType exprJoinType = joinExpr.getType();
JoinType joinType = org.datanucleus.store.rdbms.sql.SQLJoin.getJoinTypeForJoinExpressionType(exprJoinType);
Expression joinedExpr = joinExpr.getJoinedExpression();
Expression joinOnExpr = joinExpr.getOnExpression();
String joinAlias = joinExpr.getAlias();
PrimaryExpression joinPrimExpr = null;
Class castCls = null;
if (joinedExpr instanceof PrimaryExpression) {
joinPrimExpr = (PrimaryExpression) joinedExpr;
} else if (joinedExpr instanceof DyadicExpression && joinedExpr.getOperator() == Expression.OP_CAST) {
// TREAT this join as a particular type. Cast type is processed below where we add the joins
joinPrimExpr = (PrimaryExpression) joinedExpr.getLeft();
String castClassName = (String) ((Literal) joinedExpr.getRight()).getLiteral();
castCls = clr.classForName(castClassName);
} else {
throw new NucleusException("We do not currently support JOIN to " + joinedExpr);
}
Iterator<String> iter = joinPrimExpr.getTuples().iterator();
String rootId = iter.next();
if (joinPrimExpr.getTuples().size() == 1 && !rootId.endsWith("#KEY") && !rootId.endsWith("#VALUE")) {
// DN Extension : Join to (new) root element? We need an ON expression to be supplied in this case
if (joinOnExpr == null) {
throw new NucleusUserException("Query has join to " + joinPrimExpr.getId() + " yet this is a root component and there is no ON expression");
}
// Add the basic join first with no condition since this root will be referenced in the "on" condition
baseCls = resolveClass(joinPrimExpr.getId());
DatastoreClass baseTbl = storeMgr.getDatastoreClass(baseCls.getName(), clr);
sqlTbl = stmt.join(joinType, candSqlTbl, baseTbl, joinAlias, null, null, true);
cmd = mmgr.getMetaDataForClass(baseCls, clr);
SQLTableMapping tblMapping = new SQLTableMapping(sqlTbl, cmd, baseTbl.getIdMapping());
setSQLTableMappingForAlias(joinAlias, tblMapping);
// Convert the ON expression to a BooleanExpression and add to the join
processingOnClause = true;
joinOnExpr.evaluate(this);
BooleanExpression joinOnSqlExpr = (BooleanExpression) stack.pop();
processingOnClause = false;
stmt.addAndConditionToJoinForTable(sqlTbl, joinOnSqlExpr, true);
// Move on to next join in the chain
rightExpr = rightExpr.getRight();
continue;
}
String joinTableGroupName = null;
SQLTable tblMappingSqlTbl = null;
JavaTypeMapping tblIdMapping = null;
AbstractMemberMetaData tblMmd = null;
boolean mapKey = false;
boolean mapValue = false;
String rootComponent = rootId;
if (rootComponent.endsWith("#KEY")) {
mapKey = true;
rootComponent = rootComponent.substring(0, rootComponent.length() - 4);
} else if (rootComponent.endsWith("#VALUE")) {
mapValue = true;
rootComponent = rootComponent.substring(0, rootComponent.length() - 6);
}
if (rootComponent.equalsIgnoreCase(candidateAlias)) {
// Join relative to the candidate
// Name table group of joined-to as per the relation
// Note : this will only work for one level out from the candidate TODO Extend this
cmd = candidateCmd;
joinTableGroupName = joinPrimExpr.getId();
sqlTbl = candSqlTbl;
} else {
// Join relative to some other alias
SQLTableMapping sqlTblMapping = getSQLTableMappingForAlias(rootComponent);
if (sqlTblMapping != null) {
if (sqlTblMapping.mmd != null && (mapKey || mapValue)) {
// First component is Map-related (i.e m#KEY, m#VALUE), so add any necessary join(s)
MapMetaData mapmd = sqlTblMapping.mmd.getMap();
cmd = mapKey ? mapmd.getKeyClassMetaData(clr) : mapmd.getValueClassMetaData(clr);
// Find the table forming the Map. This may be a join table, or the key or value depending on the type
// TODO Use OPTION_CASE_INSENSITIVE
sqlTbl = stmt.getTable(rootComponent + "_MAP");
if (sqlTbl == null) {
sqlTbl = stmt.getTable((rootComponent + "_MAP").toUpperCase());
if (sqlTbl == null) {
sqlTbl = stmt.getTable((rootComponent + "_MAP").toLowerCase());
}
}
String aliasForJoin = (iter.hasNext()) ? null : joinAlias;
boolean embedded = mapKey ? (mapmd.isEmbeddedKey() || mapmd.isSerializedKey()) : (mapmd.isEmbeddedValue() || mapmd.isSerializedValue());
if (mapmd.getMapType() == MapType.MAP_TYPE_JOIN) {
// Join from join table to KEY/VALUE as required
if (!embedded) {
if (mapKey) {
DatastoreClass keyTable = storeMgr.getDatastoreClass(mapmd.getKeyType(), clr);
sqlTbl = stmt.join(joinType, sqlTbl, ((MapTable) sqlTbl.getTable()).getKeyMapping(), keyTable, aliasForJoin, keyTable.getIdMapping(), null, joinTableGroupName, true);
} else {
DatastoreClass valueTable = storeMgr.getDatastoreClass(mapmd.getValueType(), clr);
sqlTbl = stmt.join(joinType, sqlTbl, ((MapTable) sqlTbl.getTable()).getValueMapping(), valueTable, aliasForJoin, valueTable.getIdMapping(), null, joinTableGroupName, true);
}
tblMappingSqlTbl = sqlTbl;
tblIdMapping = tblMappingSqlTbl.getTable().getIdMapping();
}
} else if (mapmd.getMapType() == MapType.MAP_TYPE_KEY_IN_VALUE) {
// TODO Cater for this type
} else if (mapmd.getMapType() == MapType.MAP_TYPE_VALUE_IN_KEY) {
// TODO Cater for this type
}
} else {
cmd = sqlTblMapping.cmd;
sqlTbl = sqlTblMapping.table;
}
joinTableGroupName = sqlTbl.getGroupName() + joinPrimExpr.getId().substring(rootComponent.length());
} else {
throw new NucleusUserException("Query has " + joinPrimExpr.getId() + " yet the first component " + rootComponent + " is unknown!");
}
}
while (iter.hasNext()) {
String id = iter.next();
String[] ids = id.contains(".") ? StringUtils.split(id, ".") : new String[] { id };
for (int k = 0; k < ids.length; k++) {
if (cmd == null) {
throw new NucleusUserException("Error in JOIN clause. id=" + id + " but component prior to " + ids[k] + " has no metadata");
}
boolean lastComponent = (k == ids.length - 1);
String thisComponent = ids[k];
mapKey = false;
mapValue = false;
if (thisComponent.endsWith("#KEY")) {
thisComponent = thisComponent.substring(0, thisComponent.length() - 4);
mapKey = true;
} else if (thisComponent.endsWith("#VALUE")) {
thisComponent = thisComponent.substring(0, thisComponent.length() - 6);
mapValue = true;
}
AbstractMemberMetaData mmd = cmd.getMetaDataForMember(thisComponent);
if (mmd == null) {
if (exprJoinType == JoinExpression.JoinType.JOIN_LEFT_OUTER || exprJoinType == JoinExpression.JoinType.JOIN_LEFT_OUTER_FETCH) {
// Polymorphic join, where the field exists in a subclass (doable since we have outer join)
String[] subclasses = mmgr.getSubclassesForClass(cmd.getFullClassName(), true);
for (int l = 0; l < subclasses.length; l++) {
AbstractClassMetaData subCmd = mmgr.getMetaDataForClass(subclasses[l], clr);
if (subCmd != null) {
mmd = subCmd.getMetaDataForMember(thisComponent);
if (mmd != null) {
cmd = subCmd;
break;
}
}
}
}
if (mmd == null) {
throw new NucleusUserException("Query has " + joinPrimExpr.getId() + " yet " + thisComponent + " is not found. Fix your input");
}
}
tblMmd = null;
String aliasForJoin = null;
if (k == (ids.length - 1) && !iter.hasNext()) {
aliasForJoin = joinAlias;
}
RelationType relationType = mmd.getRelationType(clr);
DatastoreClass relTable = null;
AbstractMemberMetaData relMmd = null;
if (relationType != RelationType.NONE) {
if (JoinExpression.JoinType.isFetch(exprJoinType)) {
// Add field to FetchPlan since marked for FETCH
String fgName = "QUERY_FETCH_" + mmd.getFullFieldName();
FetchGroupManager fetchGrpMgr = storeMgr.getNucleusContext().getFetchGroupManager();
if (fetchGrpMgr.getFetchGroupsWithName(fgName) == null) {
FetchGroup grp = new FetchGroup(storeMgr.getNucleusContext(), fgName, clr.classForName(cmd.getFullClassName()));
grp.addMember(mmd.getName());
fetchGrpMgr.addFetchGroup(grp);
}
fetchPlan.addGroup(fgName);
}
}
if (relationType == RelationType.ONE_TO_ONE_UNI) {
JavaTypeMapping otherMapping = null;
Object[] castDiscrimValues = null;
if (castCls != null && lastComponent) {
cmd = mmgr.getMetaDataForClass(castCls, clr);
if (cmd.hasDiscriminatorStrategy()) {
// Restrict discriminator on cast type to be the type+subclasses
castDiscrimValues = getDiscriminatorValuesForCastClass(cmd);
}
} else {
cmd = mmgr.getMetaDataForClass(mmd.getType(), clr);
}
if (mmd.isEmbedded()) {
// Embedded into the same table as before, so no join needed
otherMapping = sqlTbl.getTable().getMemberMapping(mmd);
} else {
if (sqlTbl.getTable() instanceof CollectionTable) {
// Currently in a join table, so work from the element and this being an embedded member
CollectionTable collTbl = (CollectionTable) sqlTbl.getTable();
JavaTypeMapping elemMapping = collTbl.getElementMapping();
if (elemMapping instanceof EmbeddedMapping) {
otherMapping = ((EmbeddedMapping) elemMapping).getJavaTypeMapping(mmd.getName());
}
} else {
otherMapping = sqlTbl.getTable().getMemberMapping(mmd);
}
relTable = storeMgr.getDatastoreClass(mmd.getTypeName(), clr);
if (otherMapping == null && previousMapping != null) {
if (previousMapping instanceof EmbeddedMapping) {
// Part of an embedded 1-1 object, so find the relevant member mapping
EmbeddedMapping embMapping = (EmbeddedMapping) previousMapping;
otherMapping = embMapping.getJavaTypeMapping(mmd.getName());
}
}
if (otherMapping == null) {
// Polymorphic join? : cannot find this member in the candidate of the main statement, so need to pick which UNION
String tblGroupName = sqlTbl.getGroupName();
SQLTableGroup grp = stmt.getTableGroup(tblGroupName);
SQLTable nextSqlTbl = null;
// Try to find subtable in the same group that has a mapping for this member (and join from that)
SQLTable[] grpTbls = grp.getTables();
for (SQLTable grpTbl : grpTbls) {
if (grpTbl.getTable().getMemberMapping(mmd) != null) {
otherMapping = grpTbl.getTable().getMemberMapping(mmd);
break;
}
}
SQLTable newSqlTbl = stmt.join(joinType, sqlTbl, otherMapping, relTable, aliasForJoin, relTable.getIdMapping(), null, joinTableGroupName, false);
if (newSqlTbl != null) {
nextSqlTbl = newSqlTbl;
}
if (stmt instanceof SelectStatement) {
List<SelectStatement> unionStmts = ((SelectStatement) stmt).getUnions();
if (unionStmts != null) {
for (SQLStatement unionStmt : unionStmts) {
// Repeat the process for any unioned statements, find a subtable in the same group (and join from that)
otherMapping = null;
grp = unionStmt.getTableGroup(tblGroupName);
SQLTable[] unionGrpTbls = grp.getTables();
for (SQLTable grpTbl : unionGrpTbls) {
if (grpTbl.getTable().getMemberMapping(mmd) != null) {
otherMapping = grpTbl.getTable().getMemberMapping(mmd);
break;
}
}
newSqlTbl = unionStmt.join(joinType, sqlTbl, otherMapping, relTable, aliasForJoin, relTable.getIdMapping(), castDiscrimValues, joinTableGroupName, false);
if (newSqlTbl != null) {
nextSqlTbl = newSqlTbl;
}
}
}
}
sqlTbl = nextSqlTbl;
} else {
sqlTbl = stmt.join(joinType, sqlTbl, otherMapping, relTable, aliasForJoin, relTable.getIdMapping(), castDiscrimValues, joinTableGroupName, true);
}
}
previousMapping = otherMapping;
tblIdMapping = sqlTbl.getTable().getIdMapping();
tblMappingSqlTbl = sqlTbl;
} else if (relationType == RelationType.ONE_TO_ONE_BI) {
JavaTypeMapping otherMapping = null;
Object[] castDiscrimValues = null;
if (castCls != null && lastComponent) {
cmd = mmgr.getMetaDataForClass(castCls, clr);
if (cmd.hasDiscriminatorStrategy()) {
// Restrict discriminator on cast type to be the type+subclasses
castDiscrimValues = getDiscriminatorValuesForCastClass(cmd);
}
} else {
cmd = mmgr.getMetaDataForClass(mmd.getType(), clr);
}
if (mmd.isEmbedded()) {
// Embedded into the same table as before, so no join needed
otherMapping = sqlTbl.getTable().getMemberMapping(mmd);
} else {
relTable = storeMgr.getDatastoreClass(mmd.getTypeName(), clr);
if (mmd.getMappedBy() != null) {
relMmd = mmd.getRelatedMemberMetaData(clr)[0];
JavaTypeMapping relMapping = relTable.getMemberMapping(relMmd);
sqlTbl = stmt.join(joinType, sqlTbl, sqlTbl.getTable().getIdMapping(), relTable, aliasForJoin, relMapping, castDiscrimValues, joinTableGroupName, true);
} else {
if (sqlTbl.getTable() instanceof CollectionTable) {
// Currently in a join table, so work from the element and this being an embedded member
CollectionTable collTbl = (CollectionTable) sqlTbl.getTable();
JavaTypeMapping elemMapping = collTbl.getElementMapping();
if (elemMapping instanceof EmbeddedMapping) {
otherMapping = ((EmbeddedMapping) elemMapping).getJavaTypeMapping(mmd.getName());
}
} else {
otherMapping = sqlTbl.getTable().getMemberMapping(mmd);
}
if (otherMapping == null && previousMapping != null) {
if (previousMapping instanceof EmbeddedMapping) {
// Part of an embedded 1-1 object, so find the relevant member mapping
EmbeddedMapping embMapping = (EmbeddedMapping) previousMapping;
otherMapping = embMapping.getJavaTypeMapping(mmd.getName());
}
}
sqlTbl = stmt.join(joinType, sqlTbl, otherMapping, relTable, aliasForJoin, relTable.getIdMapping(), castDiscrimValues, joinTableGroupName, true);
}
}
previousMapping = otherMapping;
tblIdMapping = sqlTbl.getTable().getIdMapping();
tblMappingSqlTbl = sqlTbl;
} else if (relationType == RelationType.ONE_TO_MANY_BI) {
previousMapping = null;
if (mmd.hasCollection()) {
// Join across COLLECTION relation
cmd = mmd.getCollection().getElementClassMetaData(clr);
if (mmd.getCollection().isEmbeddedElement() && mmd.getJoinMetaData() != null) {
// Embedded element stored in (collection) join table
CollectionTable relEmbTable = (CollectionTable) storeMgr.getTable(mmd);
JavaTypeMapping relOwnerMapping = relEmbTable.getOwnerMapping();
sqlTbl = stmt.join(joinType, sqlTbl, sqlTbl.getTable().getIdMapping(), relEmbTable, aliasForJoin, relOwnerMapping, null, joinTableGroupName, true);
tblMappingSqlTbl = sqlTbl;
tblIdMapping = relEmbTable.getElementMapping();
} else {
relTable = storeMgr.getDatastoreClass(mmd.getCollection().getElementType(), clr);
relMmd = mmd.getRelatedMemberMetaData(clr)[0];
if (mmd.getJoinMetaData() != null || relMmd.getJoinMetaData() != null) {
// Join to join table, then to related table
ElementContainerTable joinTbl = (ElementContainerTable) storeMgr.getTable(mmd);
SQLTable joinSqlTbl = stmt.join(joinType, sqlTbl, sqlTbl.getTable().getIdMapping(), joinTbl, null, joinTbl.getOwnerMapping(), null, null, true);
sqlTbl = stmt.join(joinType, joinSqlTbl, joinTbl.getElementMapping(), relTable, aliasForJoin, relTable.getIdMapping(), null, joinTableGroupName, true);
} else {
// Join to related table FK
sqlTbl = stmt.join(joinType, sqlTbl, sqlTbl.getTable().getIdMapping(), relTable, aliasForJoin, relTable.getMemberMapping(relMmd), null, joinTableGroupName, true);
}
tblIdMapping = sqlTbl.getTable().getIdMapping();
tblMappingSqlTbl = sqlTbl;
}
} else if (mmd.hasMap()) {
// Join across MAP relation
MapMetaData mapmd = mmd.getMap();
cmd = mapmd.getValueClassMetaData(clr);
tblMmd = mmd;
boolean embedded = mapKey ? (mapmd.isEmbeddedKey() || mapmd.isSerializedKey()) : (mapmd.isEmbeddedValue() || mapmd.isSerializedValue());
if (mapmd.getMapType() == MapType.MAP_TYPE_JOIN) {
// Add join to join table, then to related table (value)
MapTable joinTbl = (MapTable) storeMgr.getTable(mmd);
String aliasForMap = embedded ? aliasForJoin : (aliasForJoin + "_MAP");
sqlTbl = stmt.join(joinType, sqlTbl, sqlTbl.getTable().getIdMapping(), joinTbl, aliasForMap, joinTbl.getOwnerMapping(), null, null, true);
if (embedded) {
tblMappingSqlTbl = sqlTbl;
tblIdMapping = mapKey ? joinTbl.getKeyMapping() : joinTbl.getValueMapping();
} else {
if (mapKey) {
// Join to key table and use that
relTable = storeMgr.getDatastoreClass(mapmd.getKeyType(), clr);
sqlTbl = stmt.join(joinType, sqlTbl, joinTbl.getKeyMapping(), relTable, aliasForJoin, relTable.getIdMapping(), null, joinTableGroupName, true);
// TODO if there is an ON clause it needs to go on the correct join See [rdbms-177]
} else {
// Join to value table and use that
relTable = storeMgr.getDatastoreClass(mapmd.getValueType(), clr);
sqlTbl = stmt.join(joinType, sqlTbl, joinTbl.getValueMapping(), relTable, aliasForJoin, relTable.getIdMapping(), null, joinTableGroupName, true);
// TODO if there is an ON clause it needs to go on the correct join See [rdbms-177]
}
tblMappingSqlTbl = sqlTbl;
tblIdMapping = tblMappingSqlTbl.getTable().getIdMapping();
}
} else if (mapmd.getMapType() == MapType.MAP_TYPE_KEY_IN_VALUE) {
// Join to value table
DatastoreClass valTable = storeMgr.getDatastoreClass(mapmd.getValueType(), clr);
JavaTypeMapping mapTblOwnerMapping;
if (mmd.getMappedBy() != null) {
mapTblOwnerMapping = valTable.getMemberMapping(mapmd.getValueClassMetaData(clr).getMetaDataForMember(mmd.getMappedBy()));
} else {
mapTblOwnerMapping = valTable.getExternalMapping(mmd, MappingType.EXTERNAL_FK);
}
String aliasForMap = (embedded || !mapKey) ? aliasForJoin : (aliasForJoin + "_MAP");
sqlTbl = stmt.join(joinType, sqlTbl, sqlTbl.getTable().getIdMapping(), valTable, aliasForMap, mapTblOwnerMapping, null, null, true);
if (!embedded) {
if (mapKey) {
// Join to key table
JavaTypeMapping keyMapping = valTable.getMemberMapping(mmd.getKeyMetaData().getMappedBy());
relTable = storeMgr.getDatastoreClass(mapmd.getKeyType(), clr);
sqlTbl = stmt.join(joinType, sqlTbl, keyMapping, relTable, aliasForJoin, relTable.getIdMapping(), null, joinTableGroupName, true);
// TODO if there is an ON clause it needs to go on the correct join See [rdbms-177]
}
}
tblMappingSqlTbl = sqlTbl;
tblIdMapping = tblMappingSqlTbl.getTable().getIdMapping();
} else if (mapmd.getMapType() == MapType.MAP_TYPE_VALUE_IN_KEY) {
// Join to key table, and then to value table
DatastoreClass keyTable = storeMgr.getDatastoreClass(mapmd.getKeyType(), clr);
JavaTypeMapping mapTblOwnerMapping;
if (mmd.getMappedBy() != null) {
mapTblOwnerMapping = keyTable.getMemberMapping(mapmd.getKeyClassMetaData(clr).getMetaDataForMember(mmd.getMappedBy()));
} else {
mapTblOwnerMapping = keyTable.getExternalMapping(mmd, MappingType.EXTERNAL_FK);
}
String aliasForMap = (embedded || mapKey) ? aliasForJoin : (aliasForJoin + "_MAP");
sqlTbl = stmt.join(joinType, sqlTbl, sqlTbl.getTable().getIdMapping(), keyTable, aliasForMap, mapTblOwnerMapping, null, null, true);
if (!embedded) {
if (!mapKey) {
// Join to value table
JavaTypeMapping valueMapping = keyTable.getMemberMapping(mmd.getValueMetaData().getMappedBy());
relTable = storeMgr.getDatastoreClass(mapmd.getValueType(), clr);
sqlTbl = stmt.join(joinType, sqlTbl, valueMapping, relTable, aliasForJoin, relTable.getIdMapping(), null, joinTableGroupName, true);
// TODO if there is an ON clause it needs to go on the correct join See [rdbms-177]
}
}
tblMappingSqlTbl = sqlTbl;
tblIdMapping = tblMappingSqlTbl.getTable().getIdMapping();
}
} else if (mmd.hasArray()) {
// Join across ARRAY relation
cmd = mmd.getArray().getElementClassMetaData(clr);
if (mmd.getArray().isEmbeddedElement() && mmd.getJoinMetaData() != null) {
// Embedded element stored in (array) join table
ArrayTable relEmbTable = (ArrayTable) storeMgr.getTable(mmd);
JavaTypeMapping relOwnerMapping = relEmbTable.getOwnerMapping();
sqlTbl = stmt.join(joinType, sqlTbl, sqlTbl.getTable().getIdMapping(), relEmbTable, aliasForJoin, relOwnerMapping, null, joinTableGroupName, true);
tblMappingSqlTbl = sqlTbl;
tblIdMapping = relEmbTable.getElementMapping();
} else {
relTable = storeMgr.getDatastoreClass(mmd.getArray().getElementType(), clr);
relMmd = mmd.getRelatedMemberMetaData(clr)[0];
if (mmd.getJoinMetaData() != null || relMmd.getJoinMetaData() != null) {
// Join to join table, then to related table
ElementContainerTable joinTbl = (ElementContainerTable) storeMgr.getTable(mmd);
SQLTable joinSqlTbl = stmt.join(joinType, sqlTbl, sqlTbl.getTable().getIdMapping(), joinTbl, null, joinTbl.getOwnerMapping(), null, null, true);
sqlTbl = stmt.join(joinType, joinSqlTbl, joinTbl.getElementMapping(), relTable, aliasForJoin, relTable.getIdMapping(), null, joinTableGroupName, true);
// TODO if there is an ON clause it needs to go on the correct join See [rdbms-177]
} else {
// Join to related table FK
sqlTbl = stmt.join(joinType, sqlTbl, sqlTbl.getTable().getIdMapping(), relTable, aliasForJoin, relTable.getMemberMapping(relMmd), null, joinTableGroupName, true);
}
tblIdMapping = sqlTbl.getTable().getIdMapping();
tblMappingSqlTbl = sqlTbl;
}
}
} else if (relationType == RelationType.ONE_TO_MANY_UNI) {
previousMapping = null;
if (mmd.hasCollection()) {
// Join across COLLECTION relation
cmd = mmd.getCollection().getElementClassMetaData(clr);
if (mmd.getCollection().isEmbeddedElement() && mmd.getJoinMetaData() != null) {
// Embedded element stored in (collection) join table
CollectionTable relEmbTable = (CollectionTable) storeMgr.getTable(mmd);
JavaTypeMapping relOwnerMapping = relEmbTable.getOwnerMapping();
sqlTbl = stmt.join(joinType, sqlTbl, sqlTbl.getTable().getIdMapping(), relEmbTable, aliasForJoin, relOwnerMapping, null, joinTableGroupName, true);
tblMappingSqlTbl = sqlTbl;
tblIdMapping = relEmbTable.getElementMapping();
} else {
relTable = storeMgr.getDatastoreClass(mmd.getCollection().getElementType(), clr);
if (mmd.getJoinMetaData() != null) {
// Join to join table, then to related table
ElementContainerTable joinTbl = (ElementContainerTable) storeMgr.getTable(mmd);
SQLTable joinSqlTbl = stmt.join(joinType, sqlTbl, sqlTbl.getTable().getIdMapping(), joinTbl, null, joinTbl.getOwnerMapping(), null, null, true);
sqlTbl = stmt.join(joinType, joinSqlTbl, joinTbl.getElementMapping(), relTable, aliasForJoin, relTable.getIdMapping(), null, joinTableGroupName, true);
// TODO if there is an ON clause it needs to go on the correct join See [rdbms-177]
} else {
// Join to related table FK
JavaTypeMapping relMapping = relTable.getExternalMapping(mmd, MappingType.EXTERNAL_FK);
sqlTbl = stmt.join(joinType, sqlTbl, sqlTbl.getTable().getIdMapping(), relTable, aliasForJoin, relMapping, null, joinTableGroupName, true);
}
tblMappingSqlTbl = sqlTbl;
tblIdMapping = tblMappingSqlTbl.getTable().getIdMapping();
}
} else if (mmd.hasMap()) {
// Join across MAP relation
MapMetaData mapmd = mmd.getMap();
cmd = mapmd.getValueClassMetaData(clr);
tblMmd = mmd;
boolean embedded = mapKey ? (mapmd.isEmbeddedKey() || mapmd.isSerializedKey()) : (mapmd.isEmbeddedValue() || mapmd.isSerializedValue());
if (mapmd.getMapType() == MapType.MAP_TYPE_JOIN) {
// Add join to join table, then to related table (value)
MapTable joinTbl = (MapTable) storeMgr.getTable(mmd);
String aliasForMap = (embedded || mapKey) ? aliasForJoin : (aliasForJoin + "_MAP");
sqlTbl = stmt.join(joinType, sqlTbl, sqlTbl.getTable().getIdMapping(), joinTbl, aliasForMap, joinTbl.getOwnerMapping(), null, null, true);
if (embedded) {
tblMappingSqlTbl = sqlTbl;
tblIdMapping = mapKey ? joinTbl.getKeyMapping() : joinTbl.getValueMapping();
} else {
if (mapKey) {
// Join to key table and use that
relTable = storeMgr.getDatastoreClass(mapmd.getKeyType(), clr);
sqlTbl = stmt.join(joinType, sqlTbl, joinTbl.getKeyMapping(), relTable, aliasForJoin, relTable.getIdMapping(), null, joinTableGroupName, true);
// TODO if there is an ON clause it needs to go on the correct join See [rdbms-177]
} else {
// Join to value table and use that
relTable = storeMgr.getDatastoreClass(mapmd.getValueType(), clr);
sqlTbl = stmt.join(joinType, sqlTbl, joinTbl.getValueMapping(), relTable, aliasForJoin, relTable.getIdMapping(), null, joinTableGroupName, true);
// TODO if there is an ON clause it needs to go on the correct join See [rdbms-177]
}
tblMappingSqlTbl = sqlTbl;
tblIdMapping = tblMappingSqlTbl.getTable().getIdMapping();
}
} else if (mapmd.getMapType() == MapType.MAP_TYPE_KEY_IN_VALUE) {
// Join to value table
DatastoreClass valTable = storeMgr.getDatastoreClass(mapmd.getValueType(), clr);
JavaTypeMapping mapTblOwnerMapping;
if (mmd.getMappedBy() != null) {
mapTblOwnerMapping = valTable.getMemberMapping(mapmd.getValueClassMetaData(clr).getMetaDataForMember(mmd.getMappedBy()));
} else {
mapTblOwnerMapping = valTable.getExternalMapping(mmd, MappingType.EXTERNAL_FK);
}
String aliasForMap = (embedded || !mapKey) ? aliasForJoin : (aliasForJoin + "_MAP");
sqlTbl = stmt.join(joinType, sqlTbl, sqlTbl.getTable().getIdMapping(), valTable, aliasForMap, mapTblOwnerMapping, null, null, true);
if (!embedded) {
if (mapKey) {
// Join to key table
JavaTypeMapping keyMapping = valTable.getMemberMapping(mmd.getKeyMetaData().getMappedBy());
relTable = storeMgr.getDatastoreClass(mapmd.getKeyType(), clr);
sqlTbl = stmt.join(joinType, sqlTbl, keyMapping, relTable, aliasForJoin, relTable.getIdMapping(), null, joinTableGroupName, true);
// TODO if there is an ON clause it needs to go on the correct join See [rdbms-177]
}
}
tblMappingSqlTbl = sqlTbl;
tblIdMapping = tblMappingSqlTbl.getTable().getIdMapping();
} else if (mapmd.getMapType() == MapType.MAP_TYPE_VALUE_IN_KEY) {
// Join to key table, and then to value table
DatastoreClass keyTable = storeMgr.getDatastoreClass(mapmd.getKeyType(), clr);
JavaTypeMapping mapTblOwnerMapping;
if (mmd.getMappedBy() != null) {
mapTblOwnerMapping = keyTable.getMemberMapping(mapmd.getKeyClassMetaData(clr).getMetaDataForMember(mmd.getMappedBy()));
} else {
mapTblOwnerMapping = keyTable.getExternalMapping(mmd, MappingType.EXTERNAL_FK);
}
String aliasForMap = (embedded || mapKey) ? aliasForJoin : (aliasForJoin + "_MAP");
sqlTbl = stmt.join(joinType, sqlTbl, sqlTbl.getTable().getIdMapping(), keyTable, aliasForMap, mapTblOwnerMapping, null, null, true);
if (!embedded) {
if (!mapKey) {
// Join to value table
JavaTypeMapping valueMapping = keyTable.getMemberMapping(mmd.getValueMetaData().getMappedBy());
relTable = storeMgr.getDatastoreClass(mapmd.getValueType(), clr);
sqlTbl = stmt.join(joinType, sqlTbl, valueMapping, relTable, aliasForJoin, relTable.getIdMapping(), null, joinTableGroupName, true);
// TODO if there is an ON clause it needs to go on the correct join See [rdbms-177]
}
}
tblMappingSqlTbl = sqlTbl;
tblIdMapping = tblMappingSqlTbl.getTable().getIdMapping();
}
} else if (mmd.hasArray()) {
// Join across ARRAY relation
cmd = mmd.getArray().getElementClassMetaData(clr);
if (mmd.getArray().isEmbeddedElement() && mmd.getJoinMetaData() != null) {
// Embedded element stored in (array) join table
ArrayTable relEmbTable = (ArrayTable) storeMgr.getTable(mmd);
JavaTypeMapping relOwnerMapping = relEmbTable.getOwnerMapping();
sqlTbl = stmt.join(joinType, sqlTbl, sqlTbl.getTable().getIdMapping(), relEmbTable, aliasForJoin, relOwnerMapping, null, joinTableGroupName, true);
tblMappingSqlTbl = sqlTbl;
tblIdMapping = relEmbTable.getElementMapping();
} else {
relTable = storeMgr.getDatastoreClass(mmd.getArray().getElementType(), clr);
if (mmd.getJoinMetaData() != null) {
// Join to join table, then to related table
ElementContainerTable joinTbl = (ElementContainerTable) storeMgr.getTable(mmd);
SQLTable joinSqlTbl = stmt.join(joinType, sqlTbl, sqlTbl.getTable().getIdMapping(), joinTbl, null, joinTbl.getOwnerMapping(), null, null, true);
sqlTbl = stmt.join(joinType, joinSqlTbl, joinTbl.getElementMapping(), relTable, aliasForJoin, relTable.getIdMapping(), null, joinTableGroupName, true);
} else {
// Join to related table FK
JavaTypeMapping relMapping = relTable.getExternalMapping(mmd, MappingType.EXTERNAL_FK);
sqlTbl = stmt.join(joinType, sqlTbl, sqlTbl.getTable().getIdMapping(), relTable, aliasForJoin, relMapping, null, joinTableGroupName, true);
}
tblMappingSqlTbl = sqlTbl;
tblIdMapping = tblMappingSqlTbl.getTable().getIdMapping();
}
}
} else if (relationType == RelationType.MANY_TO_MANY_BI) {
previousMapping = null;
relTable = storeMgr.getDatastoreClass(mmd.getCollection().getElementType(), clr);
cmd = mmd.getCollection().getElementClassMetaData(clr);
relMmd = mmd.getRelatedMemberMetaData(clr)[0];
// Join to join table, then to related table
if (mmd.hasCollection()) {
CollectionTable joinTbl = (CollectionTable) storeMgr.getTable(mmd);
SQLTable joinSqlTbl = stmt.join(joinType, sqlTbl, sqlTbl.getTable().getIdMapping(), joinTbl, null, joinTbl.getOwnerMapping(), null, null, true);
sqlTbl = stmt.join(joinType, joinSqlTbl, joinTbl.getElementMapping(), relTable, aliasForJoin, relTable.getIdMapping(), null, joinTableGroupName, true);
} else if (mmd.hasMap()) {
NucleusLogger.QUERY.warn("We do not support joining across a M-N MAP field : " + mmd.getFullFieldName());
} else if (mmd.hasArray()) {
NucleusLogger.QUERY.warn("We do not support joining across a M-N ARRAY field : " + mmd.getFullFieldName());
}
tblMappingSqlTbl = sqlTbl;
tblIdMapping = tblMappingSqlTbl.getTable().getIdMapping();
} else if (relationType == RelationType.MANY_TO_ONE_BI) {
previousMapping = null;
relTable = storeMgr.getDatastoreClass(mmd.getTypeName(), clr);
Object[] castDiscrimValues = null;
if (castCls != null && lastComponent) {
cmd = mmgr.getMetaDataForClass(castCls, clr);
if (cmd.hasDiscriminatorStrategy()) {
// Restrict discriminator on cast type to be the type+subclasses
castDiscrimValues = getDiscriminatorValuesForCastClass(cmd);
}
} else {
cmd = mmgr.getMetaDataForClass(mmd.getType(), clr);
}
relMmd = mmd.getRelatedMemberMetaData(clr)[0];
if (mmd.getJoinMetaData() != null || relMmd.getJoinMetaData() != null) {
// Join to join table, then to related table
if (mmd.hasCollection()) {
CollectionTable joinTbl = (CollectionTable) storeMgr.getTable(relMmd);
SQLTable joinSqlTbl = stmt.join(joinType, sqlTbl, sqlTbl.getTable().getIdMapping(), joinTbl, null, joinTbl.getElementMapping(), null, null, true);
sqlTbl = stmt.join(joinType, joinSqlTbl, joinTbl.getOwnerMapping(), relTable, aliasForJoin, relTable.getIdMapping(), castDiscrimValues, joinTableGroupName, true);
} else if (mmd.hasMap()) {
NucleusLogger.QUERY.warn("We do not support joining across a N-1 MAP field : " + mmd.getFullFieldName());
} else if (mmd.hasArray()) {
NucleusLogger.QUERY.warn("We do not support joining across a N-1 ARRAY field : " + mmd.getFullFieldName());
}
} else {
// Join to owner table
JavaTypeMapping fkMapping = sqlTbl.getTable().getMemberMapping(mmd);
sqlTbl = stmt.join(joinType, sqlTbl, fkMapping, relTable, aliasForJoin, relTable.getIdMapping(), castDiscrimValues, joinTableGroupName, true);
}
tblMappingSqlTbl = sqlTbl;
tblIdMapping = tblMappingSqlTbl.getTable().getIdMapping();
} else {
// NO RELATION, but cater for join table cases
previousMapping = null;
if (mmd.hasCollection()) {
cmd = null;
if (mmd.getJoinMetaData() != null) {
// Join to join table
CollectionTable joinTbl = (CollectionTable) storeMgr.getTable(mmd);
sqlTbl = stmt.join(joinType, sqlTbl, sqlTbl.getTable().getIdMapping(), joinTbl, aliasForJoin, joinTbl.getOwnerMapping(), null, null, true);
tblMappingSqlTbl = sqlTbl;
tblIdMapping = joinTbl.getElementMapping();
} else {
throw new NucleusUserException("FROM clause contains join to Collection field at " + mmd.getFullFieldName() + " yet this has no join table");
}
} else if (mmd.hasMap()) {
MapMetaData mapmd = mmd.getMap();
cmd = mapmd.getValueClassMetaData(clr);
tblMmd = mmd;
if (// Should be the only type when relationType is NONE
mapmd.getMapType() == MapType.MAP_TYPE_JOIN) {
// Add join to join table
MapTable joinTbl = (MapTable) storeMgr.getTable(mmd);
String aliasForMap = aliasForJoin;
sqlTbl = stmt.join(joinType, sqlTbl, sqlTbl.getTable().getIdMapping(), joinTbl, aliasForMap, joinTbl.getOwnerMapping(), null, null, true);
tblMappingSqlTbl = sqlTbl;
tblIdMapping = joinTbl.getValueMapping();
} else {
throw new NucleusUserException("FROM clause contains join to Map field at " + mmd.getFullFieldName() + " yet this has no join table");
}
} else if (mmd.hasArray()) {
cmd = null;
if (mmd.getJoinMetaData() != null) {
// Join to join table
ArrayTable joinTbl = (ArrayTable) storeMgr.getTable(mmd);
sqlTbl = stmt.join(joinType, sqlTbl, sqlTbl.getTable().getIdMapping(), joinTbl, aliasForJoin, joinTbl.getOwnerMapping(), null, null, true);
tblMappingSqlTbl = sqlTbl;
tblIdMapping = joinTbl.getElementMapping();
} else {
throw new NucleusUserException("FROM clause contains join to array field at " + mmd.getFullFieldName() + " yet this has no join table");
}
}
}
}
}
if (joinAlias != null) {
if (explicitJoinPrimaryByAlias == null) {
explicitJoinPrimaryByAlias = new HashMap<>();
}
explicitJoinPrimaryByAlias.put(joinAlias, joinPrimExpr.getId());
SQLTableMapping tblMapping = null;
if (tblMmd != null) {
// Maps store the member so we can more easily navigate to the key/value
tblMapping = new SQLTableMapping(tblMappingSqlTbl, cmd, tblMmd, tblIdMapping);
} else {
tblMapping = new SQLTableMapping(tblMappingSqlTbl, cmd, tblIdMapping);
}
setSQLTableMappingForAlias(joinAlias, tblMapping);
}
if (joinOnExpr != null) {
// Convert the ON expression to a BooleanExpression
processingOnClause = true;
joinOnExpr.evaluate(this);
BooleanExpression joinOnSqlExpr = (BooleanExpression) stack.pop();
processingOnClause = false;
// Add the ON expression to the most recent SQLTable at the end of this chain
// TODO Allow for SQL JOIN "grouping" [rdbms-177]. This applies to all cases where we join to a join table then to an element/value table and
// need to apply the ON clause across both
SQLJoin join = stmt.getJoinForTable(sqlTbl);
join.addAndCondition(joinOnSqlExpr);
}
} else {
previousMapping = null;
}
// Move on to next join in the chain
rightExpr = rightExpr.getRight();
}
}
use of org.datanucleus.store.rdbms.sql.SQLTable in project datanucleus-rdbms by datanucleus.
the class JDOQLQuery method compileQueryDelete.
/**
* Method to compile the query for RDBMS for a bulk delete.
* @param parameterValues The parameter values (if any)
* @param candidateCmd Meta-data for the candidate class
*/
protected void compileQueryDelete(Map parameterValues, AbstractClassMetaData candidateCmd) {
RDBMSStoreManager storeMgr = (RDBMSStoreManager) getStoreManager();
DatastoreClass candidateTbl = storeMgr.getDatastoreClass(candidateCmd.getFullClassName(), clr);
if (candidateTbl == null) {
// TODO Using subclass-table, so find the table(s) it can be persisted into
throw new NucleusDataStoreException("Bulk delete of " + candidateCmd.getFullClassName() + " not supported since candidate has no table of its own");
}
InheritanceStrategy inhStr = candidateCmd.getBaseAbstractClassMetaData().getInheritanceMetaData().getStrategy();
List<BulkTable> tables = new ArrayList<>();
tables.add(new BulkTable(candidateTbl, true));
if (inhStr != InheritanceStrategy.COMPLETE_TABLE) {
// Add deletion from superclass tables since we will have an entry there
while (candidateTbl.getSuperDatastoreClass() != null) {
candidateTbl = candidateTbl.getSuperDatastoreClass();
tables.add(new BulkTable(candidateTbl, false));
}
}
Collection<String> subclassNames = storeMgr.getSubClassesForClass(candidateCmd.getFullClassName(), true, clr);
if (subclassNames != null && !subclassNames.isEmpty()) {
// Check for subclasses having their own tables and hence needing multiple DELETEs
Iterator<String> iter = subclassNames.iterator();
while (iter.hasNext()) {
String subclassName = iter.next();
DatastoreClass subclassTbl = storeMgr.getDatastoreClass(subclassName, clr);
if (candidateTbl != subclassTbl) {
// Only include BulkTable in count if using COMPLETE_TABLE strategy
tables.add(0, new BulkTable(subclassTbl, inhStr == InheritanceStrategy.COMPLETE_TABLE));
}
}
}
List<SQLStatement> stmts = new ArrayList<>();
List<Boolean> stmtCountFlags = new ArrayList<>();
for (BulkTable bulkTable : tables) {
// Generate statement for candidate
DatastoreClass table = bulkTable.table;
JavaTypeMapping softDeleteMapping = table.getSurrogateMapping(SurrogateColumnType.SOFTDELETE, false);
if (softDeleteMapping != null) {
throw new NucleusUserException("Cannot use BulkDelete queries when using SoftDelete on an affected table (" + table + ")");
}
Map<String, Object> extensions = null;
if (!storeMgr.getDatastoreAdapter().supportsOption(DatastoreAdapter.UPDATE_DELETE_STATEMENT_ALLOW_TABLE_ALIAS_IN_WHERE_CLAUSE)) {
extensions = new HashMap<>();
extensions.put(SQLStatement.EXTENSION_SQL_TABLE_NAMING_STRATEGY, "table-name");
}
SQLStatement stmt = new DeleteStatement(storeMgr, table, null, null, extensions);
stmt.setClassLoaderResolver(clr);
stmt.setCandidateClassName(candidateCmd.getFullClassName());
JavaTypeMapping multitenancyMapping = table.getSurrogateMapping(SurrogateColumnType.MULTITENANCY, false);
if (multitenancyMapping != null) {
// Multi-tenancy restriction
SQLTable tenantSqlTbl = stmt.getPrimaryTable();
SQLExpression tenantExpr = stmt.getSQLExpressionFactory().newExpression(stmt, tenantSqlTbl, multitenancyMapping);
SQLExpression tenantVal = stmt.getSQLExpressionFactory().newLiteral(stmt, multitenancyMapping, ec.getNucleusContext().getMultiTenancyId(ec, candidateCmd));
stmt.whereAnd(tenantExpr.eq(tenantVal), true);
}
// TODO Discriminator restriction?
Set<String> options = new HashSet<>();
if (getBooleanExtensionProperty(EXTENSION_USE_IS_NULL_WHEN_EQUALS_NULL_PARAM, true)) {
options.add(QueryToSQLMapper.OPTION_NULL_PARAM_USE_IS_NULL);
}
QueryToSQLMapper sqlMapper = new QueryToSQLMapper(stmt, compilation, parameterValues, null, null, candidateCmd, subclasses, getFetchPlan(), ec, null, options, extensions);
setMapperJoinTypes(sqlMapper);
sqlMapper.compile();
stmts.add(stmt);
stmtCountFlags.add(bulkTable.useInCount);
datastoreCompilation.setStatementParameters(stmt.getSQLText().getParametersForStatement());
datastoreCompilation.setPrecompilable(sqlMapper.isPrecompilable());
}
datastoreCompilation.clearStatements();
Iterator<SQLStatement> stmtIter = stmts.iterator();
Iterator<Boolean> stmtCountFlagsIter = stmtCountFlags.iterator();
while (stmtIter.hasNext()) {
SQLStatement stmt = stmtIter.next();
Boolean useInCount = stmtCountFlagsIter.next();
if (stmts.size() == 1) {
useInCount = true;
}
datastoreCompilation.addStatement(stmt, stmt.getSQLText().toSQL(), useInCount);
}
}
use of org.datanucleus.store.rdbms.sql.SQLTable in project datanucleus-rdbms by datanucleus.
the class OracleBlobRDBMSMapping method updateBlobColumn.
/**
* Convenience method to update the contents of a BLOB column.
* Oracle requires that a BLOB is initialised with EMPTY_BLOB() and then you retrieve
* the column and update its BLOB value. Performs a statement
* <pre>
* SELECT {blobColumn} FROM TABLE WHERE ID=? FOR UPDATE
* </pre>
* and then updates the Blob value returned.
* @param op ObjectProvider of the object
* @param table Table storing the BLOB column
* @param mapping Datastore mapping for the BLOB column
* @param bytes The bytes to store in the BLOB
* @throws NucleusObjectNotFoundException thrown if an object isnt found
* @throws NucleusDataStoreException thrown if an error occurs in datastore communication
*/
@SuppressWarnings("deprecation")
public static void updateBlobColumn(ObjectProvider op, Table table, DatastoreMapping mapping, byte[] bytes) {
ExecutionContext ec = op.getExecutionContext();
RDBMSStoreManager storeMgr = table.getStoreManager();
// Don't support join tables yet
DatastoreClass classTable = (DatastoreClass) table;
SQLExpressionFactory exprFactory = storeMgr.getSQLExpressionFactory();
// Generate "SELECT {blobColumn} FROM TABLE WHERE ID=? FOR UPDATE" statement
SelectStatement sqlStmt = new SelectStatement(storeMgr, table, null, null);
sqlStmt.setClassLoaderResolver(ec.getClassLoaderResolver());
sqlStmt.addExtension(SQLStatement.EXTENSION_LOCK_FOR_UPDATE, true);
SQLTable blobSqlTbl = SQLStatementHelper.getSQLTableForMappingOfTable(sqlStmt, sqlStmt.getPrimaryTable(), mapping.getJavaTypeMapping());
sqlStmt.select(blobSqlTbl, mapping.getColumn(), null);
StatementClassMapping mappingDefinition = new StatementClassMapping();
AbstractClassMetaData cmd = op.getClassMetaData();
int inputParamNum = 1;
if (cmd.getIdentityType() == IdentityType.DATASTORE) {
// Datastore identity value for input
JavaTypeMapping datastoreIdMapping = classTable.getSurrogateMapping(SurrogateColumnType.DATASTORE_ID, false);
SQLExpression expr = exprFactory.newExpression(sqlStmt, sqlStmt.getPrimaryTable(), datastoreIdMapping);
SQLExpression val = exprFactory.newLiteralParameter(sqlStmt, datastoreIdMapping, null, "ID");
sqlStmt.whereAnd(expr.eq(val), true);
StatementMappingIndex datastoreIdx = mappingDefinition.getMappingForMemberPosition(SurrogateColumnType.DATASTORE_ID.getFieldNumber());
if (datastoreIdx == null) {
datastoreIdx = new StatementMappingIndex(datastoreIdMapping);
mappingDefinition.addMappingForMember(SurrogateColumnType.DATASTORE_ID.getFieldNumber(), datastoreIdx);
}
datastoreIdx.addParameterOccurrence(new int[] { inputParamNum });
} else if (cmd.getIdentityType() == IdentityType.APPLICATION) {
// Application identity value(s) for input
int[] pkNums = cmd.getPKMemberPositions();
for (int i = 0; i < pkNums.length; i++) {
AbstractMemberMetaData mmd = cmd.getMetaDataForManagedMemberAtAbsolutePosition(pkNums[i]);
JavaTypeMapping pkMapping = classTable.getMemberMapping(mmd);
SQLExpression expr = exprFactory.newExpression(sqlStmt, sqlStmt.getPrimaryTable(), pkMapping);
SQLExpression val = exprFactory.newLiteralParameter(sqlStmt, pkMapping, null, "PK" + i);
sqlStmt.whereAnd(expr.eq(val), true);
StatementMappingIndex pkIdx = mappingDefinition.getMappingForMemberPosition(pkNums[i]);
if (pkIdx == null) {
pkIdx = new StatementMappingIndex(pkMapping);
mappingDefinition.addMappingForMember(pkNums[i], pkIdx);
}
int[] inputParams = new int[pkMapping.getNumberOfDatastoreMappings()];
for (int j = 0; j < pkMapping.getNumberOfDatastoreMappings(); j++) {
inputParams[j] = inputParamNum++;
}
pkIdx.addParameterOccurrence(inputParams);
}
}
String textStmt = sqlStmt.getSQLText().toSQL();
if (op.isEmbedded()) {
// This mapping is embedded, so navigate back to the real owner since that is the "id" in the table
ObjectProvider[] embeddedOwners = ec.getOwnersForEmbeddedObjectProvider(op);
if (embeddedOwners != null) {
// Just use the first owner
// TODO Should check if the owner is stored in this table
op = embeddedOwners[0];
}
}
try {
ManagedConnection mconn = storeMgr.getConnectionManager().getConnection(ec);
SQLController sqlControl = storeMgr.getSQLController();
try {
PreparedStatement ps = sqlControl.getStatementForQuery(mconn, textStmt);
try {
// Provide the primary key field(s) to the JDBC statement
if (cmd.getIdentityType() == IdentityType.DATASTORE) {
StatementMappingIndex datastoreIdx = mappingDefinition.getMappingForMemberPosition(SurrogateColumnType.DATASTORE_ID.getFieldNumber());
for (int i = 0; i < datastoreIdx.getNumberOfParameterOccurrences(); i++) {
classTable.getSurrogateMapping(SurrogateColumnType.DATASTORE_ID, false).setObject(ec, ps, datastoreIdx.getParameterPositionsForOccurrence(i), op.getInternalObjectId());
}
} else if (cmd.getIdentityType() == IdentityType.APPLICATION) {
op.provideFields(cmd.getPKMemberPositions(), new ParameterSetter(op, ps, mappingDefinition));
}
ResultSet rs = sqlControl.executeStatementQuery(ec, mconn, textStmt, ps);
try {
if (!rs.next()) {
throw new NucleusObjectNotFoundException("No such database row", op.getInternalObjectId());
}
DatastoreAdapter dba = storeMgr.getDatastoreAdapter();
int jdbcMajorVersion = dba.getDriverMajorVersion();
if (dba.getDatastoreDriverName().equalsIgnoreCase(OracleAdapter.OJDBC_DRIVER_NAME) && jdbcMajorVersion < 10) {
// Oracle JDBC drivers version 9 and below use some sh*tty Oracle-specific BLOB type
// we have to cast to that, face west, pray whilst saying ommmmmmmmmmm
oracle.sql.BLOB blob = null;
if (jdbcMajorVersion <= 8) {
OracleResultSet ors = (OracleResultSet) rs;
blob = ors.getBLOB(1);
} else {
blob = (oracle.sql.BLOB) rs.getBlob(1);
}
if (blob != null) {
// Deprecated but what can you do
blob.putBytes(1, bytes);
}
} else {
// Oracle JDBC drivers 10 and above supposedly use the JDBC standard class for Blobs
java.sql.Blob blob = rs.getBlob(1);
if (blob != null) {
blob.setBytes(1, bytes);
}
}
} finally {
rs.close();
}
} finally {
sqlControl.closeStatement(mconn, ps);
}
} finally {
mconn.release();
}
} catch (SQLException e) {
throw new NucleusDataStoreException("Update of BLOB value failed: " + textStmt, e);
}
}
use of org.datanucleus.store.rdbms.sql.SQLTable in project datanucleus-rdbms by datanucleus.
the class MapContainsEntryMethod method containsAsInnerJoin.
/**
* Method to return an expression for Map.containsEntry using INNER JOIN to the element.
* This is only for use when there are no "!containsEntry" and no "OR" operations.
* Creates SQL by adding INNER JOIN to the join table (where it exists), and also to the value table
* adding an AND condition on the value (with value of the valueExpr).
* Returns a BooleanExpression "TRUE" (since the INNER JOIN will guarantee if the entry is
* contained of not).
* @param stmt SQLStatement
* @param mapExpr Map expression
* @param keyExpr Expression for the key
* @param valExpr Expression for the value
* @return Contains expression
*/
protected SQLExpression containsAsInnerJoin(SQLStatement stmt, MapExpression mapExpr, SQLExpression keyExpr, SQLExpression valExpr) {
boolean keyIsUnbound = (keyExpr instanceof UnboundExpression);
String keyVarName = null;
if (keyIsUnbound) {
keyVarName = ((UnboundExpression) keyExpr).getVariableName();
NucleusLogger.QUERY.debug(">> Map.containsEntry binding unbound variable " + keyVarName + " using INNER JOIN");
// TODO What if the variable is declared as a subtype, handle this see CollectionContainsMethod
}
boolean valIsUnbound = (valExpr instanceof UnboundExpression);
String valVarName = null;
if (valIsUnbound) {
valVarName = ((UnboundExpression) valExpr).getVariableName();
NucleusLogger.QUERY.debug(">> Map.containsEntry binding unbound variable " + valVarName + " using INNER JOIN");
// TODO What if the variable is declared as a subtype, handle this see CollectionContainsMethod
}
RDBMSStoreManager storeMgr = stmt.getRDBMSManager();
SQLExpressionFactory exprFactory = stmt.getSQLExpressionFactory();
ClassLoaderResolver clr = stmt.getQueryGenerator().getClassLoaderResolver();
AbstractMemberMetaData mmd = mapExpr.getJavaTypeMapping().getMemberMetaData();
AbstractClassMetaData keyCmd = mmd.getMap().getKeyClassMetaData(clr);
AbstractClassMetaData valCmd = mmd.getMap().getValueClassMetaData(clr);
if (mmd.getMap().getMapType() == MapType.MAP_TYPE_JOIN) {
// Map formed in join table - add join to join table, then to key/value tables (if present)
MapTable mapTbl = (MapTable) storeMgr.getTable(mmd);
SQLTable joinSqlTbl = stmt.join(JoinType.INNER_JOIN, mapExpr.getSQLTable(), mapExpr.getSQLTable().getTable().getIdMapping(), mapTbl, null, mapTbl.getOwnerMapping(), null, null);
if (valCmd != null) {
DatastoreClass valTbl = storeMgr.getDatastoreClass(valCmd.getFullClassName(), clr);
SQLTable valSqlTbl = stmt.join(JoinType.INNER_JOIN, joinSqlTbl, mapTbl.getValueMapping(), valTbl, null, valTbl.getIdMapping(), null, null);
SQLExpression valIdExpr = exprFactory.newExpression(stmt, valSqlTbl, valTbl.getIdMapping());
if (valIsUnbound) {
// Bind the variable in the QueryGenerator
stmt.getQueryGenerator().bindVariable(valVarName, valCmd, valIdExpr.getSQLTable(), valIdExpr.getJavaTypeMapping());
} else {
// Add restrict to value
stmt.whereAnd(valIdExpr.eq(valExpr), true);
}
} else {
SQLExpression valIdExpr = exprFactory.newExpression(stmt, joinSqlTbl, mapTbl.getValueMapping());
if (valIsUnbound) {
// Bind the variable in the QueryGenerator
stmt.getQueryGenerator().bindVariable(valVarName, null, valIdExpr.getSQLTable(), valIdExpr.getJavaTypeMapping());
} else {
// Add restrict to value
stmt.whereAnd(valIdExpr.eq(valExpr), true);
}
}
if (keyCmd != null) {
DatastoreClass keyTbl = storeMgr.getDatastoreClass(keyCmd.getFullClassName(), clr);
SQLTable keySqlTbl = stmt.join(JoinType.INNER_JOIN, joinSqlTbl, mapTbl.getKeyMapping(), keyTbl, null, keyTbl.getIdMapping(), null, null);
SQLExpression keyIdExpr = exprFactory.newExpression(stmt, keySqlTbl, keyTbl.getIdMapping());
if (keyIsUnbound) {
// Bind the variable in the QueryGenerator
stmt.getQueryGenerator().bindVariable(keyVarName, keyCmd, keyIdExpr.getSQLTable(), keyIdExpr.getJavaTypeMapping());
} else {
// Add restrict to key
stmt.whereAnd(keyIdExpr.eq(keyExpr), true);
}
} else {
SQLExpression keyIdExpr = exprFactory.newExpression(stmt, joinSqlTbl, mapTbl.getKeyMapping());
if (keyIsUnbound) {
// Bind the variable in the QueryGenerator
stmt.getQueryGenerator().bindVariable(keyVarName, null, keyIdExpr.getSQLTable(), keyIdExpr.getJavaTypeMapping());
} else {
// Add restrict to key
stmt.whereAnd(keyIdExpr.eq(keyExpr), true);
}
}
} else if (mmd.getMap().getMapType() == MapType.MAP_TYPE_KEY_IN_VALUE) {
// Map formed in value table - add join to value table, then to key table (if present)
DatastoreClass valTbl = storeMgr.getDatastoreClass(valCmd.getFullClassName(), clr);
JavaTypeMapping ownerMapping = null;
if (mmd.getMappedBy() != null) {
ownerMapping = valTbl.getMemberMapping(valCmd.getMetaDataForMember(mmd.getMappedBy()));
} else {
ownerMapping = valTbl.getExternalMapping(mmd, MappingType.EXTERNAL_FK);
}
SQLTable valSqlTbl = stmt.join(JoinType.INNER_JOIN, mapExpr.getSQLTable(), mapExpr.getSQLTable().getTable().getIdMapping(), valTbl, null, ownerMapping, null, null);
SQLExpression valIdExpr = exprFactory.newExpression(stmt, valSqlTbl, valTbl.getIdMapping());
if (valIsUnbound) {
// Bind the variable in the QueryGenerator
stmt.getQueryGenerator().bindVariable(valVarName, valCmd, valIdExpr.getSQLTable(), valIdExpr.getJavaTypeMapping());
} else {
// Add restrict to value
stmt.whereAnd(valIdExpr.eq(valExpr), true);
}
if (keyCmd != null) {
// Add inner join to key table
AbstractMemberMetaData valKeyMmd = valCmd.getMetaDataForMember(mmd.getKeyMetaData().getMappedBy());
DatastoreClass keyTbl = storeMgr.getDatastoreClass(keyCmd.getFullClassName(), clr);
SQLTable keySqlTbl = stmt.join(JoinType.INNER_JOIN, valSqlTbl, valTbl.getMemberMapping(valKeyMmd), keyTbl, null, keyTbl.getIdMapping(), null, null);
SQLExpression keyIdExpr = exprFactory.newExpression(stmt, keySqlTbl, keyTbl.getIdMapping());
if (keyIsUnbound) {
// Bind the variable in the QueryGenerator
stmt.getQueryGenerator().bindVariable(keyVarName, keyCmd, keyIdExpr.getSQLTable(), keyIdExpr.getJavaTypeMapping());
} else {
// Add restriction to key
stmt.whereAnd(keyIdExpr.eq(keyExpr), true);
}
} else {
AbstractMemberMetaData valKeyMmd = valCmd.getMetaDataForMember(mmd.getKeyMetaData().getMappedBy());
SQLExpression keyIdExpr = exprFactory.newExpression(stmt, valSqlTbl, valTbl.getMemberMapping(valKeyMmd));
if (keyIsUnbound) {
// Bind the variable in the QueryGenerator
stmt.getQueryGenerator().bindVariable(keyVarName, keyCmd, keyIdExpr.getSQLTable(), keyIdExpr.getJavaTypeMapping());
} else {
// Add restriction to key
stmt.whereAnd(keyIdExpr.eq(keyExpr), true);
}
}
} else if (mmd.getMap().getMapType() == MapType.MAP_TYPE_VALUE_IN_KEY) {
// Map formed in key table - add join to key table then to value table (if present)
DatastoreClass keyTbl = storeMgr.getDatastoreClass(keyCmd.getFullClassName(), clr);
AbstractMemberMetaData keyValMmd = keyCmd.getMetaDataForMember(mmd.getValueMetaData().getMappedBy());
JavaTypeMapping ownerMapping = null;
if (mmd.getMappedBy() != null) {
ownerMapping = keyTbl.getMemberMapping(keyCmd.getMetaDataForMember(mmd.getMappedBy()));
} else {
ownerMapping = keyTbl.getExternalMapping(mmd, MappingType.EXTERNAL_FK);
}
SQLTable keySqlTbl = stmt.join(JoinType.INNER_JOIN, mapExpr.getSQLTable(), mapExpr.getSQLTable().getTable().getIdMapping(), keyTbl, null, ownerMapping, null, null);
SQLExpression keyIdExpr = exprFactory.newExpression(stmt, keySqlTbl, keyTbl.getIdMapping());
if (keyIsUnbound) {
// Bind the variable in the QueryGenerator
stmt.getQueryGenerator().bindVariable(keyVarName, keyCmd, keyIdExpr.getSQLTable(), keyIdExpr.getJavaTypeMapping());
} else {
// Add restrict to key
stmt.whereAnd(keyIdExpr.eq(keyExpr), true);
}
if (valCmd != null) {
// Add inner join to value table
DatastoreClass valTbl = storeMgr.getDatastoreClass(valCmd.getFullClassName(), clr);
SQLTable valSqlTbl = stmt.join(JoinType.INNER_JOIN, keySqlTbl, keyTbl.getMemberMapping(keyValMmd), valTbl, null, valTbl.getIdMapping(), null, null);
SQLExpression valIdExpr = exprFactory.newExpression(stmt, valSqlTbl, valTbl.getIdMapping());
if (valIsUnbound) {
// Bind the variable in the QueryGenerator
stmt.getQueryGenerator().bindVariable(valVarName, valCmd, valIdExpr.getSQLTable(), valIdExpr.getJavaTypeMapping());
} else {
// Add restrict to value
stmt.whereAnd(valIdExpr.eq(valExpr), true);
}
} else {
SQLExpression valIdExpr = exprFactory.newExpression(stmt, keySqlTbl, keyTbl.getMemberMapping(keyValMmd));
if (valIsUnbound) {
// Bind the variable in the QueryGenerator
stmt.getQueryGenerator().bindVariable(valVarName, null, valIdExpr.getSQLTable(), valIdExpr.getJavaTypeMapping());
} else {
// Add restrict to value
stmt.whereAnd(valIdExpr.eq(valExpr), true);
}
}
}
JavaTypeMapping m = exprFactory.getMappingForType(boolean.class, true);
return exprFactory.newLiteral(stmt, m, true).eq(exprFactory.newLiteral(stmt, m, true));
}
use of org.datanucleus.store.rdbms.sql.SQLTable in project datanucleus-rdbms by datanucleus.
the class MapContainsKeyMethod method containsAsJoin.
/**
* Method to return an expression for Map.containsKey using INNER JOIN to the element.
* This is only for use when there are no "!containsKey" and no "OR" operations.
* Creates SQL by adding INNER JOIN to the join table (where it exists), and also to the key table
* adding an AND condition on the element (with value of the keyExpr).
* Returns a BooleanExpression "TRUE" (since the INNER JOIN will guarantee if the key is contained of not).
* @param stmt SQLStatement
* @param mapExpr Map expression
* @param keyExpr Expression for the key
* @param joinType Type of join
* @return Contains expression
*/
protected SQLExpression containsAsJoin(SQLStatement stmt, MapExpression mapExpr, SQLExpression keyExpr, JoinType joinType) {
boolean keyIsUnbound = (keyExpr instanceof UnboundExpression);
String varName = null;
String keyAlias = null;
if (keyIsUnbound) {
varName = ((UnboundExpression) keyExpr).getVariableName();
NucleusLogger.QUERY.debug("map.containsKey(" + keyExpr + ") binding unbound variable " + varName + " using INNER JOIN");
// TODO What if the variable is declared as a subtype, handle this see CollectionContainsMethod
} else if (!stmt.getQueryGenerator().hasExplicitJoins()) {
if (stmt.getJoinTypeForTable(keyExpr.getSQLTable()) == JoinType.CROSS_JOIN) {
keyAlias = stmt.removeCrossJoin(keyExpr.getSQLTable());
keyIsUnbound = true;
NucleusLogger.QUERY.debug("map.containsKey(" + keyExpr + ") was previously bound as CROSS JOIN but changing to INNER JOIN");
}
}
RDBMSStoreManager storeMgr = stmt.getRDBMSManager();
SQLExpressionFactory exprFactory = stmt.getSQLExpressionFactory();
ClassLoaderResolver clr = stmt.getQueryGenerator().getClassLoaderResolver();
AbstractMemberMetaData mmd = mapExpr.getJavaTypeMapping().getMemberMetaData();
AbstractClassMetaData keyCmd = mmd.getMap().getKeyClassMetaData(clr);
if (mmd.getMap().getMapType() == MapType.MAP_TYPE_JOIN) {
// Map formed in join table - add join to join table, then to key table (if present)
MapTable mapTbl = (MapTable) storeMgr.getTable(mmd);
SQLTable joinSqlTbl = stmt.join(joinType, mapExpr.getSQLTable(), mapExpr.getSQLTable().getTable().getIdMapping(), mapTbl, null, mapTbl.getOwnerMapping(), null, null);
if (keyCmd != null) {
if (keyIsUnbound) {
DatastoreClass keyTbl = storeMgr.getDatastoreClass(keyCmd.getFullClassName(), clr);
SQLTable keySqlTbl = stmt.join(joinType, joinSqlTbl, mapTbl.getKeyMapping(), keyTbl, keyAlias, keyTbl.getIdMapping(), null, null);
// Bind the variable in the QueryGenerator
keyExpr = exprFactory.newExpression(stmt, keySqlTbl, keyTbl.getIdMapping());
stmt.getQueryGenerator().bindVariable(varName, keyCmd, keyExpr.getSQLTable(), keyExpr.getJavaTypeMapping());
} else {
// Add restrict to key
SQLExpression keyIdExpr = exprFactory.newExpression(stmt, joinSqlTbl, mapTbl.getKeyMapping());
stmt.whereAnd(keyIdExpr.eq(keyExpr), true);
}
} else {
if (keyIsUnbound) {
// Bind the variable in the QueryGenerator
keyExpr = exprFactory.newExpression(stmt, joinSqlTbl, mapTbl.getKeyMapping());
stmt.getQueryGenerator().bindVariable(varName, null, keyExpr.getSQLTable(), keyExpr.getJavaTypeMapping());
} else {
// Add restrict to key
SQLExpression keyIdExpr = exprFactory.newExpression(stmt, joinSqlTbl, mapTbl.getKeyMapping());
stmt.whereAnd(keyIdExpr.eq(keyExpr), true);
}
}
} else if (mmd.getMap().getMapType() == MapType.MAP_TYPE_KEY_IN_VALUE) {
// Map formed in value table - add join to value table, then to key table
AbstractClassMetaData valCmd = mmd.getMap().getValueClassMetaData(clr);
DatastoreClass valTbl = storeMgr.getDatastoreClass(valCmd.getFullClassName(), clr);
AbstractMemberMetaData valKeyMmd = valCmd.getMetaDataForMember(mmd.getKeyMetaData().getMappedBy());
JavaTypeMapping ownerMapping = null;
if (mmd.getMappedBy() != null) {
ownerMapping = valTbl.getMemberMapping(valCmd.getMetaDataForMember(mmd.getMappedBy()));
} else {
ownerMapping = valTbl.getExternalMapping(mmd, MappingType.EXTERNAL_FK);
}
SQLTable valSqlTbl = stmt.join(joinType, mapExpr.getSQLTable(), mapExpr.getSQLTable().getTable().getIdMapping(), valTbl, null, ownerMapping, null, null);
if (keyCmd != null) {
DatastoreClass keyTbl = storeMgr.getDatastoreClass(keyCmd.getFullClassName(), clr);
SQLTable keySqlTbl = stmt.join(joinType, valSqlTbl, valTbl.getMemberMapping(valKeyMmd), keyTbl, keyAlias, keyTbl.getIdMapping(), null, null);
if (keyIsUnbound) {
// Bind the variable in the QueryGenerator
keyExpr = exprFactory.newExpression(stmt, keySqlTbl, keyTbl.getIdMapping());
stmt.getQueryGenerator().bindVariable(varName, keyCmd, keyExpr.getSQLTable(), keyExpr.getJavaTypeMapping());
} else {
// Add restrict to key
SQLExpression keyIdExpr = exprFactory.newExpression(stmt, keySqlTbl, keyTbl.getIdMapping());
stmt.whereAnd(keyIdExpr.eq(keyExpr), true);
}
} else {
if (keyIsUnbound) {
// Bind the variable in the QueryGenerator
keyExpr = exprFactory.newExpression(stmt, valSqlTbl, valTbl.getMemberMapping(valKeyMmd));
stmt.getQueryGenerator().bindVariable(varName, null, keyExpr.getSQLTable(), keyExpr.getJavaTypeMapping());
} else {
// Add restrict to key
SQLExpression keyIdExpr = exprFactory.newExpression(stmt, valSqlTbl, valTbl.getMemberMapping(valKeyMmd));
stmt.whereAnd(keyIdExpr.eq(keyExpr), true);
}
}
} else if (mmd.getMap().getMapType() == MapType.MAP_TYPE_VALUE_IN_KEY) {
// Map formed in key table - add join to key table
DatastoreClass keyTbl = storeMgr.getDatastoreClass(keyCmd.getFullClassName(), clr);
JavaTypeMapping ownerMapping = null;
if (mmd.getMappedBy() != null) {
ownerMapping = keyTbl.getMemberMapping(keyCmd.getMetaDataForMember(mmd.getMappedBy()));
} else {
ownerMapping = keyTbl.getExternalMapping(mmd, MappingType.EXTERNAL_FK);
}
SQLTable keySqlTbl = stmt.join(joinType, mapExpr.getSQLTable(), mapExpr.getSQLTable().getTable().getIdMapping(), keyTbl, keyAlias, ownerMapping, null, null);
if (keyIsUnbound) {
// Bind the variable in the QueryGenerator
keyExpr = exprFactory.newExpression(stmt, keySqlTbl, keyTbl.getIdMapping());
stmt.getQueryGenerator().bindVariable(varName, keyCmd, keyExpr.getSQLTable(), keyExpr.getJavaTypeMapping());
} else {
// Add restrict to key
SQLExpression keyIdExpr = exprFactory.newExpression(stmt, keySqlTbl, keyTbl.getIdMapping());
stmt.whereAnd(keyIdExpr.eq(keyExpr), true);
}
}
JavaTypeMapping m = exprFactory.getMappingForType(boolean.class, true);
return exprFactory.newLiteral(stmt, m, true).eq(exprFactory.newLiteral(stmt, m, true));
}
Aggregations