use of org.datanucleus.store.rdbms.RDBMSStoreManager in project datanucleus-rdbms by datanucleus.
the class LocateRequest method execute.
/**
* Method performing the retrieval of the record from the datastore.
* Takes the constructed retrieval query and populates with the specific record information.
* @param op ObjectProvider for the record to be retrieved
*/
public void execute(ObjectProvider op) {
if (statementLocked != null) {
ExecutionContext ec = op.getExecutionContext();
RDBMSStoreManager storeMgr = table.getStoreManager();
boolean locked = ec.getSerializeReadForClass(op.getClassMetaData().getFullClassName());
LockMode lockType = ec.getLockManager().getLockMode(op.getInternalObjectId());
if (lockType != LockMode.LOCK_NONE) {
if (lockType == LockMode.LOCK_PESSIMISTIC_READ || lockType == LockMode.LOCK_PESSIMISTIC_WRITE) {
// Override with pessimistic lock
locked = true;
}
}
String statement = (locked ? statementLocked : statementUnlocked);
try {
ManagedConnection mconn = storeMgr.getConnectionManager().getConnection(ec);
SQLController sqlControl = storeMgr.getSQLController();
try {
PreparedStatement ps = sqlControl.getStatementForQuery(mconn, statement);
AbstractClassMetaData cmd = op.getClassMetaData();
try {
// Provide the primary key field(s)
if (cmd.getIdentityType() == IdentityType.DATASTORE) {
StatementMappingIndex datastoreIdx = mappingDefinition.getMappingForMemberPosition(SurrogateColumnType.DATASTORE_ID.getFieldNumber());
for (int i = 0; i < datastoreIdx.getNumberOfParameterOccurrences(); i++) {
table.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));
}
JavaTypeMapping multitenancyMapping = table.getSurrogateMapping(SurrogateColumnType.MULTITENANCY, false);
if (multitenancyMapping != null) {
// Set MultiTenancy parameter in statement
StatementMappingIndex multitenancyIdx = mappingDefinition.getMappingForMemberPosition(SurrogateColumnType.MULTITENANCY.getFieldNumber());
String tenantId = ec.getNucleusContext().getMultiTenancyId(ec, cmd);
for (int i = 0; i < multitenancyIdx.getNumberOfParameterOccurrences(); i++) {
multitenancyMapping.setObject(ec, ps, multitenancyIdx.getParameterPositionsForOccurrence(i), tenantId);
}
}
JavaTypeMapping softDeleteMapping = table.getSurrogateMapping(SurrogateColumnType.SOFTDELETE, false);
if (softDeleteMapping != null) {
// Set SoftDelete parameter in statement
StatementMappingIndex softDeleteIdx = mappingDefinition.getMappingForMemberPosition(SurrogateColumnType.SOFTDELETE.getFieldNumber());
for (int i = 0; i < softDeleteIdx.getNumberOfParameterOccurrences(); i++) {
softDeleteMapping.setObject(ec, ps, softDeleteIdx.getParameterPositionsForOccurrence(i), Boolean.FALSE);
}
}
// Execute the statement
ResultSet rs = sqlControl.executeStatementQuery(ec, mconn, statement, ps);
try {
if (!rs.next()) {
NucleusLogger.DATASTORE_RETRIEVE.info(Localiser.msg("050018", op.getInternalObjectId()));
throw new NucleusObjectNotFoundException("No such database row", op.getInternalObjectId());
}
} finally {
rs.close();
}
} finally {
sqlControl.closeStatement(mconn, ps);
}
} finally {
mconn.release();
}
} catch (SQLException sqle) {
String msg = Localiser.msg("052220", op.getObjectAsPrintable(), statement, sqle.getMessage());
NucleusLogger.DATASTORE_RETRIEVE.warn(msg);
List exceptions = new ArrayList();
exceptions.add(sqle);
while ((sqle = sqle.getNextException()) != null) {
exceptions.add(sqle);
}
throw new NucleusDataStoreException(msg, (Throwable[]) exceptions.toArray(new Throwable[exceptions.size()]));
}
}
}
use of org.datanucleus.store.rdbms.RDBMSStoreManager in project datanucleus-rdbms by datanucleus.
the class UpdateRequest method execute.
/**
* Method performing the update of the record in the datastore.
* Takes the constructed update query and populates with the specific record information.
* @param op The ObjectProvider for the record to be updated
*/
public void execute(ObjectProvider op) {
// Choose the statement based on whether optimistic or not
String stmt = null;
ExecutionContext ec = op.getExecutionContext();
boolean optimisticChecks = (versionMetaData != null && ec.getTransaction().getOptimistic() && versionChecks);
stmt = optimisticChecks ? updateStmtOptimistic : updateStmt;
if (stmt != null) {
// TODO Support surrogate update user/timestamp
AbstractMemberMetaData[] mmds = cmd.getManagedMembers();
for (int i = 0; i < mmds.length; i++) {
if (// TODO Make this accessible from cmd
mmds[i].isUpdateTimestamp()) {
op.replaceField(mmds[i].getAbsoluteFieldNumber(), new Timestamp(ec.getTransaction().getIsActive() ? ec.getTransaction().getBeginTime() : System.currentTimeMillis()));
} else if (// TODO Make this accessible from cmd
mmds[i].isUpdateUser()) {
op.replaceField(mmds[i].getAbsoluteFieldNumber(), ec.getNucleusContext().getCurrentUser(ec));
}
}
if (NucleusLogger.PERSISTENCE.isDebugEnabled()) {
// Debug info about fields being updated
StringBuilder fieldStr = new StringBuilder();
if (updateFieldNumbers != null) {
for (int i = 0; i < updateFieldNumbers.length; i++) {
if (fieldStr.length() > 0) {
fieldStr.append(",");
}
fieldStr.append(cmd.getMetaDataForManagedMemberAtAbsolutePosition(updateFieldNumbers[i]).getName());
}
}
if (versionMetaData != null && versionMetaData.getFieldName() == null) {
if (fieldStr.length() > 0) {
fieldStr.append(",");
}
fieldStr.append("[VERSION]");
}
// Debug information about what we are updating
NucleusLogger.PERSISTENCE.debug(Localiser.msg("052214", op.getObjectAsPrintable(), fieldStr.toString(), table));
}
RDBMSStoreManager storeMgr = table.getStoreManager();
boolean batch = false;
// TODO Set the batch flag based on whether we have no other SQL being invoked in here just our UPDATE
try {
ManagedConnection mconn = storeMgr.getConnectionManager().getConnection(ec);
SQLController sqlControl = storeMgr.getSQLController();
try {
// Perform the update
PreparedStatement ps = sqlControl.getStatementForUpdate(mconn, stmt, batch);
try {
Object currentVersion = op.getTransactionalVersion();
Object nextVersion = null;
if (// TODO What if strategy is NONE?
versionMetaData != null) {
// Set the next version in the object
if (versionMetaData.getFieldName() != null) {
// Version field
AbstractMemberMetaData verfmd = cmd.getMetaDataForMember(table.getVersionMetaData().getFieldName());
if (currentVersion instanceof Number) {
// Cater for Integer-based versions
currentVersion = Long.valueOf(((Number) currentVersion).longValue());
}
nextVersion = ec.getLockManager().getNextVersion(versionMetaData, currentVersion);
if (verfmd.getType() == Integer.class || verfmd.getType() == int.class) {
// Cater for Integer-based versions
nextVersion = Integer.valueOf(((Number) nextVersion).intValue());
}
op.replaceField(verfmd.getAbsoluteFieldNumber(), nextVersion);
} else {
// Surrogate version column
nextVersion = ec.getLockManager().getNextVersion(versionMetaData, currentVersion);
}
op.setTransactionalVersion(nextVersion);
}
// SELECT clause - set the required fields to be updated
if (updateFieldNumbers != null) {
StatementClassMapping mappingDefinition = new StatementClassMapping();
StatementMappingIndex[] idxs = stmtMappingDefinition.getUpdateFields();
for (int i = 0; i < idxs.length; i++) {
if (idxs[i] != null) {
mappingDefinition.addMappingForMember(i, idxs[i]);
}
}
op.provideFields(updateFieldNumbers, new ParameterSetter(op, ps, mappingDefinition));
}
if (versionMetaData != null && versionMetaData.getFieldName() == null) {
// SELECT clause - set the surrogate version column to the new version
StatementMappingIndex mapIdx = stmtMappingDefinition.getUpdateVersion();
for (int i = 0; i < mapIdx.getNumberOfParameterOccurrences(); i++) {
table.getSurrogateMapping(SurrogateColumnType.VERSION, false).setObject(ec, ps, mapIdx.getParameterPositionsForOccurrence(i), nextVersion);
}
}
// WHERE clause - primary key fields
if (table.getIdentityType() == IdentityType.DATASTORE) {
// a). datastore identity
StatementMappingIndex mapIdx = stmtMappingDefinition.getWhereDatastoreId();
for (int i = 0; i < mapIdx.getNumberOfParameterOccurrences(); i++) {
table.getSurrogateMapping(SurrogateColumnType.DATASTORE_ID, false).setObject(ec, ps, mapIdx.getParameterPositionsForOccurrence(i), op.getInternalObjectId());
}
} else {
// b). application/nondurable identity
StatementClassMapping mappingDefinition = new StatementClassMapping();
StatementMappingIndex[] idxs = stmtMappingDefinition.getWhereFields();
for (int i = 0; i < idxs.length; i++) {
if (idxs[i] != null) {
mappingDefinition.addMappingForMember(i, idxs[i]);
}
}
FieldManager fm = null;
if (cmd.getIdentityType() == IdentityType.NONDURABLE) {
fm = new OldValueParameterSetter(op, ps, mappingDefinition);
} else {
fm = new ParameterSetter(op, ps, mappingDefinition);
}
op.provideFields(whereFieldNumbers, fm);
}
if (optimisticChecks) {
if (currentVersion == null) {
// Somehow the version is not set on this object (not read in ?) so report the bug
String msg = Localiser.msg("052201", op.getInternalObjectId(), table);
NucleusLogger.PERSISTENCE.error(msg);
throw new NucleusException(msg);
}
// WHERE clause - current version discriminator
StatementMappingIndex mapIdx = stmtMappingDefinition.getWhereVersion();
for (int i = 0; i < mapIdx.getNumberOfParameterOccurrences(); i++) {
mapIdx.getMapping().setObject(ec, ps, mapIdx.getParameterPositionsForOccurrence(i), currentVersion);
}
}
int[] rcs = sqlControl.executeStatementUpdate(ec, mconn, stmt, ps, !batch);
if (rcs[0] == 0 && optimisticChecks) {
// TODO Batching : when we use batching here we need to process these somehow
throw new NucleusOptimisticException(Localiser.msg("052203", op.getObjectAsPrintable(), op.getInternalObjectId(), "" + currentVersion), op.getObject());
}
} finally {
sqlControl.closeStatement(mconn, ps);
}
} finally {
mconn.release();
}
} catch (SQLException e) {
String msg = Localiser.msg("052215", op.getObjectAsPrintable(), stmt, StringUtils.getStringFromStackTrace(e));
NucleusLogger.DATASTORE_PERSIST.error(msg);
List exceptions = new ArrayList();
exceptions.add(e);
while ((e = e.getNextException()) != null) {
exceptions.add(e);
}
throw new NucleusDataStoreException(msg, (Throwable[]) exceptions.toArray(new Throwable[exceptions.size()]));
}
}
// Execute any mapping actions now that we have done the update
for (int i = 0; i < callbacks.length; ++i) {
try {
if (NucleusLogger.PERSISTENCE.isDebugEnabled()) {
NucleusLogger.PERSISTENCE.debug(Localiser.msg("052216", op.getObjectAsPrintable(), ((JavaTypeMapping) callbacks[i]).getMemberMetaData().getFullFieldName()));
}
callbacks[i].postUpdate(op);
} catch (NotYetFlushedException e) {
op.updateFieldAfterInsert(e.getPersistable(), ((JavaTypeMapping) callbacks[i]).getMemberMetaData().getAbsoluteFieldNumber());
}
}
}
use of org.datanucleus.store.rdbms.RDBMSStoreManager in project datanucleus-rdbms by datanucleus.
the class CollectionLiteral method setStatement.
protected void setStatement() {
if (value != null && value.size() > 0) {
RDBMSStoreManager storeMgr = stmt.getRDBMSManager();
elementExpressions = new ArrayList();
st.append("(");
boolean hadPrev = false;
for (Iterator it = value.iterator(); it.hasNext(); ) {
Object element = it.next();
if (element != null) {
JavaTypeMapping elemMapping = storeMgr.getSQLExpressionFactory().getMappingForType(element.getClass(), false);
SQLExpression elemExpr = storeMgr.getSQLExpressionFactory().newLiteral(stmt, elemMapping, element);
// Append the SQLExpression (should be a literal) for the current element
st.append(hadPrev ? "," : "");
st.append(elemExpr);
elementExpressions.add(elemExpr);
hadPrev = true;
}
}
st.append(")");
}
}
use of org.datanucleus.store.rdbms.RDBMSStoreManager in project datanucleus-rdbms by datanucleus.
the class MapContainsKeyMethod method containsAsSubquery.
/**
* Method to return an expression for Map.containsKey using a subquery "EXISTS".
* This is for use when there are "!contains" or "OR" operations in the filter.
* Creates the following SQL,
* <ul>
* <li><b>Map using join table</b>
* <pre>
* SELECT 1 FROM JOIN_TBL A0_SUB
* WHERE A0_SUB.JOIN_OWN_ID = A0.ID AND A0_SUB.JOIN_KEY_ID = {keyExpr}
* </pre>
* </li>
* <li><b>Map with key stored in value</b>
* <pre>
* SELECT 1 FROM KEY_TABLE A0_SUB INNER JOIN VALUE_TBL B0 ON ...
* WHERE B0.JOIN_OWN_ID = A0.ID AND A0_SUB.ID = {keyExpr}
* </pre>
* </li>
* <li><b>Map of value stored in key</b>
* <pre>
* SELECT 1 FROM KEY_TABLE A0_SUB
* WHERE A0_SUB.OWN_ID = A0.ID AND A0_SUB.ID = {keyExpr}
* </pre>
* </li>
* </ul>
* and returns a BooleanSubqueryExpression ("EXISTS (subquery)")
* @param stmt SQLStatement
* @param mapExpr Map expression
* @param keyExpr Expression for the key
* @return Contains expression
*/
protected SQLExpression containsAsSubquery(SQLStatement stmt, MapExpression mapExpr, SQLExpression keyExpr) {
boolean keyIsUnbound = (keyExpr instanceof UnboundExpression);
String varName = null;
if (keyIsUnbound) {
varName = ((UnboundExpression) keyExpr).getVariableName();
NucleusLogger.QUERY.debug("map.containsKey binding unbound variable " + varName + " using SUBQUERY");
// 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);
MapTable joinTbl = (MapTable) storeMgr.getTable(mmd);
SelectStatement subStmt = null;
if (mmd.getMap().getMapType() == MapType.MAP_TYPE_JOIN) {
// JoinTable Map
if (keyCmd == null) {
// Map<Non-PC, ?>
subStmt = new SelectStatement(stmt, storeMgr, joinTbl, null, null);
subStmt.setClassLoaderResolver(clr);
JavaTypeMapping oneMapping = storeMgr.getMappingManager().getMapping(Integer.class);
subStmt.select(exprFactory.newLiteral(subStmt, oneMapping, 1), null);
// Restrict to map owner
JavaTypeMapping ownerMapping = ((JoinTable) joinTbl).getOwnerMapping();
SQLExpression ownerExpr = exprFactory.newExpression(subStmt, subStmt.getPrimaryTable(), ownerMapping);
SQLExpression ownerIdExpr = exprFactory.newExpression(stmt, mapExpr.getSQLTable(), mapExpr.getSQLTable().getTable().getIdMapping());
subStmt.whereAnd(ownerExpr.eq(ownerIdExpr), true);
if (keyIsUnbound) {
// Bind the variable in the QueryGenerator
keyExpr = exprFactory.newExpression(subStmt, subStmt.getPrimaryTable(), joinTbl.getKeyMapping());
stmt.getQueryGenerator().bindVariable(varName, null, keyExpr.getSQLTable(), keyExpr.getJavaTypeMapping());
} else {
// Add restrict to key
SQLExpression elemIdExpr = exprFactory.newExpression(subStmt, subStmt.getPrimaryTable(), joinTbl.getKeyMapping());
subStmt.whereAnd(elemIdExpr.eq(keyExpr), true);
}
} else {
// Map<PC, ?>
DatastoreClass keyTbl = storeMgr.getDatastoreClass(mmd.getMap().getKeyType(), clr);
subStmt = new SelectStatement(stmt, storeMgr, keyTbl, null, null);
subStmt.setClassLoaderResolver(clr);
JavaTypeMapping oneMapping = storeMgr.getMappingManager().getMapping(Integer.class);
subStmt.select(exprFactory.newLiteral(subStmt, oneMapping, 1), null);
// Join to join table
SQLTable joinSqlTbl = subStmt.join(JoinType.INNER_JOIN, subStmt.getPrimaryTable(), keyTbl.getIdMapping(), joinTbl, null, joinTbl.getKeyMapping(), null, null, true);
// Restrict to map owner
JavaTypeMapping ownerMapping = joinTbl.getOwnerMapping();
SQLExpression ownerExpr = exprFactory.newExpression(subStmt, joinSqlTbl, ownerMapping);
SQLExpression ownerIdExpr = exprFactory.newExpression(stmt, mapExpr.getSQLTable(), mapExpr.getSQLTable().getTable().getIdMapping());
subStmt.whereAnd(ownerExpr.eq(ownerIdExpr), true);
if (keyIsUnbound) {
// Bind the variable in the QueryGenerator
keyExpr = exprFactory.newExpression(subStmt, subStmt.getPrimaryTable(), keyTbl.getIdMapping());
stmt.getQueryGenerator().bindVariable(varName, keyCmd, keyExpr.getSQLTable(), keyExpr.getJavaTypeMapping());
} else {
// Add restrict to key
SQLExpression keyIdExpr = exprFactory.newExpression(subStmt, subStmt.getPrimaryTable(), keyTbl.getIdMapping());
subStmt.whereAnd(keyIdExpr.eq(keyExpr), true);
}
}
} else if (mmd.getMap().getMapType() == MapType.MAP_TYPE_KEY_IN_VALUE) {
// Key stored in value table
AbstractClassMetaData valCmd = mmd.getMap().getValueClassMetaData(clr);
DatastoreClass valTbl = storeMgr.getDatastoreClass(mmd.getMap().getValueType(), clr);
JavaTypeMapping ownerMapping = null;
if (mmd.getMappedBy() != null) {
ownerMapping = valTbl.getMemberMapping(valCmd.getMetaDataForMember(mmd.getMappedBy()));
} else {
ownerMapping = valTbl.getExternalMapping(mmd, MappingType.EXTERNAL_FK);
}
AbstractMemberMetaData valKeyMmd = valCmd.getMetaDataForMember(mmd.getKeyMetaData().getMappedBy());
if (keyCmd == null) {
subStmt = new SelectStatement(stmt, storeMgr, valTbl, null, null);
subStmt.setClassLoaderResolver(clr);
JavaTypeMapping oneMapping = storeMgr.getMappingManager().getMapping(Integer.class);
subStmt.select(exprFactory.newLiteral(subStmt, oneMapping, 1), null);
// Restrict to map owner (on value table)
SQLExpression ownerExpr = exprFactory.newExpression(subStmt, subStmt.getPrimaryTable(), ownerMapping);
SQLExpression ownerIdExpr = exprFactory.newExpression(stmt, mapExpr.getSQLTable(), mapExpr.getSQLTable().getTable().getIdMapping());
subStmt.whereAnd(ownerExpr.eq(ownerIdExpr), true);
if (keyIsUnbound) {
// Bind the variable in the QueryGenerator
keyExpr = exprFactory.newExpression(subStmt, subStmt.getPrimaryTable(), valTbl.getMemberMapping(valKeyMmd));
stmt.getQueryGenerator().bindVariable(varName, null, keyExpr.getSQLTable(), keyExpr.getJavaTypeMapping());
} else {
// Add restrict to key
JavaTypeMapping keyMapping = valTbl.getMemberMapping(valKeyMmd);
SQLExpression elemIdExpr = exprFactory.newExpression(subStmt, subStmt.getPrimaryTable(), keyMapping);
subStmt.whereAnd(elemIdExpr.eq(keyExpr), true);
}
} else {
DatastoreClass keyTbl = storeMgr.getDatastoreClass(mmd.getMap().getKeyType(), clr);
subStmt = new SelectStatement(stmt, storeMgr, keyTbl, null, null);
subStmt.setClassLoaderResolver(clr);
JavaTypeMapping oneMapping = storeMgr.getMappingManager().getMapping(Integer.class);
subStmt.select(exprFactory.newLiteral(subStmt, oneMapping, 1), null);
// Join to value table
SQLTable valSqlTbl = subStmt.join(JoinType.INNER_JOIN, subStmt.getPrimaryTable(), keyTbl.getIdMapping(), valTbl, null, valTbl.getMemberMapping(valKeyMmd), null, null, true);
// Restrict to map owner (on value table)
SQLExpression ownerExpr = exprFactory.newExpression(subStmt, valSqlTbl, ownerMapping);
SQLExpression ownerIdExpr = exprFactory.newExpression(stmt, mapExpr.getSQLTable(), mapExpr.getSQLTable().getTable().getIdMapping());
subStmt.whereAnd(ownerExpr.eq(ownerIdExpr), true);
if (keyIsUnbound) {
// Bind the variable in the QueryGenerator
keyExpr = exprFactory.newExpression(subStmt, subStmt.getPrimaryTable(), keyTbl.getIdMapping());
stmt.getQueryGenerator().bindVariable(varName, keyCmd, keyExpr.getSQLTable(), keyExpr.getJavaTypeMapping());
} else {
// Add restrict to key
SQLExpression keyIdExpr = exprFactory.newExpression(subStmt, subStmt.getPrimaryTable(), keyTbl.getIdMapping());
subStmt.whereAnd(keyIdExpr.eq(keyExpr), true);
}
}
} else if (mmd.getMap().getMapType() == MapType.MAP_TYPE_VALUE_IN_KEY) {
DatastoreClass keyTbl = storeMgr.getDatastoreClass(mmd.getMap().getKeyType(), clr);
JavaTypeMapping ownerMapping = null;
if (mmd.getMappedBy() != null) {
ownerMapping = keyTbl.getMemberMapping(keyCmd.getMetaDataForMember(mmd.getMappedBy()));
} else {
ownerMapping = keyTbl.getExternalMapping(mmd, MappingType.EXTERNAL_FK);
}
subStmt = new SelectStatement(stmt, storeMgr, keyTbl, null, null);
subStmt.setClassLoaderResolver(clr);
JavaTypeMapping oneMapping = storeMgr.getMappingManager().getMapping(Integer.class);
subStmt.select(exprFactory.newLiteral(subStmt, oneMapping, 1), null);
// Restrict to map owner (on key table)
SQLExpression ownerExpr = exprFactory.newExpression(subStmt, subStmt.getPrimaryTable(), ownerMapping);
SQLExpression ownerIdExpr = exprFactory.newExpression(stmt, mapExpr.getSQLTable(), mapExpr.getSQLTable().getTable().getIdMapping());
subStmt.whereAnd(ownerExpr.eq(ownerIdExpr), true);
if (keyIsUnbound) {
// Bind the variable in the QueryGenerator
keyExpr = exprFactory.newExpression(subStmt, subStmt.getPrimaryTable(), keyTbl.getIdMapping());
stmt.getQueryGenerator().bindVariable(varName, keyCmd, keyExpr.getSQLTable(), keyExpr.getJavaTypeMapping());
} else {
// Add restrict to key
JavaTypeMapping keyMapping = keyTbl.getIdMapping();
SQLExpression keyIdExpr = exprFactory.newExpression(subStmt, subStmt.getPrimaryTable(), keyMapping);
subStmt.whereAnd(keyIdExpr.eq(keyExpr), true);
}
}
return new BooleanSubqueryExpression(stmt, "EXISTS", subStmt);
}
use of org.datanucleus.store.rdbms.RDBMSStoreManager in project datanucleus-rdbms by datanucleus.
the class MapContainsValueMethod method containsAsSubquery.
/**
* Method to return an expression for Map.containsValue using a subquery "EXISTS".
* This is for use when there are "!contains" or "OR" operations in the filter.
* Creates the following SQL,
* <ul>
* <li><b>Map using join table</b>
* <pre>
* SELECT 1 FROM JOIN_TBL A0_SUB
* WHERE A0_SUB.JOIN_OWN_ID = A0.ID AND A0_SUB.JOIN_VAL_ID = {valExpr}
* </pre>
* </li>
* <li><b>Map with key stored in value</b>
* <pre>
* SELECT 1 FROM VAL_TABLE A0_SUB INNER JOIN KEY_TBL B0 ON ...
* WHERE B0.JOIN_OWN_ID = A0.ID AND A0_SUB.ID = {valExpr}
* </pre>
* </li>
* <li><b>Map of value stored in key</b>
* <pre>
* SELECT 1 FROM VAL_TABLE A0_SUB
* WHERE A0_SUB.OWN_ID = A0.ID AND A0_SUB.ID = {valExpr}
* </pre>
* </li>
* </ul>
* and returns a BooleanSubqueryExpression ("EXISTS (subquery)")
* @param stmt SQLStatement
* @param mapExpr Map expression
* @param valExpr Expression for the value
* @return Contains expression
*/
protected SQLExpression containsAsSubquery(SQLStatement stmt, MapExpression mapExpr, SQLExpression valExpr) {
boolean valIsUnbound = (valExpr instanceof UnboundExpression);
String varName = null;
if (valIsUnbound) {
varName = ((UnboundExpression) valExpr).getVariableName();
NucleusLogger.QUERY.debug("map.containsValue binding unbound variable " + varName + " using SUBQUERY");
// 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 valCmd = mmd.getMap().getValueClassMetaData(clr);
MapTable joinTbl = (MapTable) storeMgr.getTable(mmd);
SelectStatement subStmt = null;
if (mmd.getMap().getMapType() == MapType.MAP_TYPE_JOIN) {
// JoinTable Map
if (valCmd == null) {
// Map<?, Non-PC>
subStmt = new SelectStatement(stmt, storeMgr, joinTbl, null, null);
subStmt.setClassLoaderResolver(clr);
JavaTypeMapping oneMapping = storeMgr.getMappingManager().getMapping(Integer.class);
subStmt.select(exprFactory.newLiteral(subStmt, oneMapping, 1), null);
// Restrict to map owner
JavaTypeMapping ownerMapping = ((JoinTable) joinTbl).getOwnerMapping();
SQLExpression ownerExpr = exprFactory.newExpression(subStmt, subStmt.getPrimaryTable(), ownerMapping);
SQLExpression ownerIdExpr = exprFactory.newExpression(stmt, mapExpr.getSQLTable(), mapExpr.getSQLTable().getTable().getIdMapping());
subStmt.whereAnd(ownerExpr.eq(ownerIdExpr), true);
if (valIsUnbound) {
// Bind the variable in the QueryGenerator
valExpr = exprFactory.newExpression(subStmt, subStmt.getPrimaryTable(), joinTbl.getValueMapping());
stmt.getQueryGenerator().bindVariable(varName, null, valExpr.getSQLTable(), valExpr.getJavaTypeMapping());
} else {
// Add restrict to value
SQLExpression valIdExpr = exprFactory.newExpression(subStmt, subStmt.getPrimaryTable(), joinTbl.getValueMapping());
subStmt.whereAnd(valIdExpr.eq(valExpr), true);
}
} else {
// Map<?, PC>
DatastoreClass valTbl = storeMgr.getDatastoreClass(mmd.getMap().getValueType(), clr);
subStmt = new SelectStatement(stmt, storeMgr, valTbl, null, null);
subStmt.setClassLoaderResolver(clr);
JavaTypeMapping oneMapping = storeMgr.getMappingManager().getMapping(Integer.class);
subStmt.select(exprFactory.newLiteral(subStmt, oneMapping, 1), null);
// Join to join table
SQLTable joinSqlTbl = subStmt.join(JoinType.INNER_JOIN, subStmt.getPrimaryTable(), valTbl.getIdMapping(), joinTbl, null, joinTbl.getValueMapping(), null, null, true);
// Restrict to map owner
JavaTypeMapping ownerMapping = joinTbl.getOwnerMapping();
SQLExpression ownerExpr = exprFactory.newExpression(subStmt, joinSqlTbl, ownerMapping);
SQLExpression ownerIdExpr = exprFactory.newExpression(stmt, mapExpr.getSQLTable(), mapExpr.getSQLTable().getTable().getIdMapping());
subStmt.whereAnd(ownerExpr.eq(ownerIdExpr), true);
if (valIsUnbound) {
// Bind the variable in the QueryGenerator
valExpr = exprFactory.newExpression(subStmt, subStmt.getPrimaryTable(), valTbl.getIdMapping());
stmt.getQueryGenerator().bindVariable(varName, valCmd, valExpr.getSQLTable(), valExpr.getJavaTypeMapping());
} else {
// Add restrict to value
SQLExpression valIdExpr = exprFactory.newExpression(subStmt, subStmt.getPrimaryTable(), valTbl.getIdMapping());
subStmt.whereAnd(valIdExpr.eq(valExpr), true);
}
}
} else if (mmd.getMap().getMapType() == MapType.MAP_TYPE_KEY_IN_VALUE) {
// Key stored in value table
DatastoreClass valTbl = storeMgr.getDatastoreClass(mmd.getMap().getValueType(), clr);
JavaTypeMapping ownerMapping = null;
if (mmd.getMappedBy() != null) {
ownerMapping = valTbl.getMemberMapping(valCmd.getMetaDataForMember(mmd.getMappedBy()));
} else {
ownerMapping = valTbl.getExternalMapping(mmd, MappingType.EXTERNAL_FK);
}
subStmt = new SelectStatement(stmt, storeMgr, valTbl, null, null);
subStmt.setClassLoaderResolver(clr);
JavaTypeMapping oneMapping = storeMgr.getMappingManager().getMapping(Integer.class);
subStmt.select(exprFactory.newLiteral(subStmt, oneMapping, 1), null);
// Restrict to map owner (on value table)
SQLExpression ownerExpr = exprFactory.newExpression(subStmt, subStmt.getPrimaryTable(), ownerMapping);
SQLExpression ownerIdExpr = exprFactory.newExpression(stmt, mapExpr.getSQLTable(), mapExpr.getSQLTable().getTable().getIdMapping());
subStmt.whereAnd(ownerExpr.eq(ownerIdExpr), true);
if (valIsUnbound) {
// Bind the variable in the QueryGenerator
valExpr = exprFactory.newExpression(subStmt, subStmt.getPrimaryTable(), valTbl.getIdMapping());
stmt.getQueryGenerator().bindVariable(varName, valCmd, valExpr.getSQLTable(), valExpr.getJavaTypeMapping());
} else {
// Add restrict to value
JavaTypeMapping valMapping = valTbl.getIdMapping();
SQLExpression valIdExpr = exprFactory.newExpression(subStmt, subStmt.getPrimaryTable(), valMapping);
subStmt.whereAnd(valIdExpr.eq(valExpr), true);
}
} else if (mmd.getMap().getMapType() == MapType.MAP_TYPE_VALUE_IN_KEY) {
AbstractClassMetaData keyCmd = mmd.getMap().getKeyClassMetaData(clr);
DatastoreClass keyTbl = storeMgr.getDatastoreClass(mmd.getMap().getKeyType(), clr);
JavaTypeMapping ownerMapping = null;
if (mmd.getMappedBy() != null) {
ownerMapping = keyTbl.getMemberMapping(keyCmd.getMetaDataForMember(mmd.getMappedBy()));
} else {
ownerMapping = keyTbl.getExternalMapping(mmd, MappingType.EXTERNAL_FK);
}
AbstractMemberMetaData keyValMmd = keyCmd.getMetaDataForMember(mmd.getValueMetaData().getMappedBy());
if (valCmd == null) {
subStmt = new SelectStatement(stmt, storeMgr, keyTbl, null, null);
subStmt.setClassLoaderResolver(clr);
JavaTypeMapping oneMapping = storeMgr.getMappingManager().getMapping(Integer.class);
subStmt.select(exprFactory.newLiteral(subStmt, oneMapping, 1), null);
// Restrict to map owner (on key table)
SQLExpression ownerExpr = exprFactory.newExpression(subStmt, subStmt.getPrimaryTable(), ownerMapping);
SQLExpression ownerIdExpr = exprFactory.newExpression(stmt, mapExpr.getSQLTable(), mapExpr.getSQLTable().getTable().getIdMapping());
subStmt.whereAnd(ownerExpr.eq(ownerIdExpr), true);
if (valIsUnbound) {
// Bind the variable in the QueryGenerator
valExpr = exprFactory.newExpression(subStmt, subStmt.getPrimaryTable(), keyTbl.getMemberMapping(keyValMmd));
stmt.getQueryGenerator().bindVariable(varName, null, valExpr.getSQLTable(), valExpr.getJavaTypeMapping());
} else {
// Add restrict to value
JavaTypeMapping valMapping = keyTbl.getMemberMapping(keyValMmd);
SQLExpression valIdExpr = exprFactory.newExpression(subStmt, subStmt.getPrimaryTable(), valMapping);
subStmt.whereAnd(valIdExpr.eq(valExpr), true);
}
} else {
DatastoreClass valTbl = storeMgr.getDatastoreClass(mmd.getMap().getValueType(), clr);
subStmt = new SelectStatement(stmt, storeMgr, valTbl, null, null);
subStmt.setClassLoaderResolver(clr);
JavaTypeMapping oneMapping = storeMgr.getMappingManager().getMapping(Integer.class);
subStmt.select(exprFactory.newLiteral(subStmt, oneMapping, 1), null);
// Join to key table
SQLTable keySqlTbl = subStmt.join(JoinType.INNER_JOIN, subStmt.getPrimaryTable(), valTbl.getIdMapping(), keyTbl, null, keyTbl.getMemberMapping(keyValMmd), null, null, true);
// Restrict to map owner (on key table)
SQLExpression ownerExpr = exprFactory.newExpression(subStmt, keySqlTbl, ownerMapping);
SQLExpression ownerIdExpr = exprFactory.newExpression(stmt, mapExpr.getSQLTable(), mapExpr.getSQLTable().getTable().getIdMapping());
subStmt.whereAnd(ownerExpr.eq(ownerIdExpr), true);
if (valIsUnbound) {
// Bind the variable in the QueryGenerator
valExpr = exprFactory.newExpression(subStmt, subStmt.getPrimaryTable(), valTbl.getIdMapping());
stmt.getQueryGenerator().bindVariable(varName, valCmd, valExpr.getSQLTable(), valExpr.getJavaTypeMapping());
} else {
// Add restrict to value
SQLExpression valIdExpr = exprFactory.newExpression(subStmt, subStmt.getPrimaryTable(), valTbl.getIdMapping());
subStmt.whereAnd(valIdExpr.eq(valExpr), true);
}
}
}
return new BooleanSubqueryExpression(stmt, "EXISTS", subStmt);
}
Aggregations