use of org.datanucleus.store.rdbms.query.StatementMappingIndex in project datanucleus-rdbms by datanucleus.
the class MappingHelper method getApplicationIdentityForResultSetRow.
/**
* Get the application identity for the persistable instance from the passed result set row.
* @param ec ExecutionContext
* @param mapping The Java Type mapping for the instance
* @param rs the ResultSet
* @param resultIndexes indexes of the ResultSet for the PK field(s)
* @param cmd the AbstractClassMetaData
* @return the id
*/
public static Object getApplicationIdentityForResultSetRow(final ExecutionContext ec, JavaTypeMapping mapping, final ResultSet rs, int[] resultIndexes, AbstractClassMetaData cmd) {
// Check for null FK
if (((RDBMSStoreManager) ec.getStoreManager()).getResultValueAtPosition(rs, mapping, resultIndexes[0]) == null) {
// Assumption : if the first param is null, then the field is null
return null;
}
// Abstract class
if (((ClassMetaData) cmd).isAbstract() && cmd.getObjectidClass() != null) {
return getObjectForAbstractClass(ec, mapping, rs, resultIndexes, cmd);
}
int totalFieldCount = cmd.getNoOfManagedMembers() + cmd.getNoOfInheritedManagedMembers();
final StatementMappingIndex[] statementExpressionIndex = new StatementMappingIndex[totalFieldCount];
ClassLoaderResolver clr = ec.getClassLoaderResolver();
DatastoreClass datastoreClass = mapping.getStoreManager().getDatastoreClass(cmd.getFullClassName(), clr);
final int[] pkFieldNumbers = cmd.getPKMemberPositions();
int paramIndex = 0;
for (int i = 0; i < pkFieldNumbers.length; ++i) {
AbstractMemberMetaData fmd = cmd.getMetaDataForManagedMemberAtAbsolutePosition(pkFieldNumbers[i]);
JavaTypeMapping m = datastoreClass.getMemberMapping(fmd);
statementExpressionIndex[fmd.getAbsoluteFieldNumber()] = new StatementMappingIndex(m);
int[] expressionsIndex = new int[m.getNumberOfColumnMappings()];
for (int j = 0; j < expressionsIndex.length; j++) {
expressionsIndex[j] = resultIndexes[paramIndex++];
}
statementExpressionIndex[fmd.getAbsoluteFieldNumber()].setColumnPositions(expressionsIndex);
}
final StatementClassMapping resultMappings = new StatementClassMapping();
for (int i = 0; i < pkFieldNumbers.length; i++) {
resultMappings.addMappingForMember(pkFieldNumbers[i], statementExpressionIndex[pkFieldNumbers[i]]);
}
final FieldManager resultsFM = new ResultSetGetter(ec, rs, resultMappings, cmd);
return IdentityUtils.getApplicationIdentityForResultSetRow(ec, cmd, null, false, resultsFM);
}
use of org.datanucleus.store.rdbms.query.StatementMappingIndex in project datanucleus-rdbms by datanucleus.
the class ResultSetGetter method fetchObjectField.
public Object fetchObjectField(int fieldNumber) {
StatementMappingIndex mapIdx = resultMappings.getMappingForMemberPosition(fieldNumber);
JavaTypeMapping mapping = mapIdx.getMapping();
AbstractMemberMetaData mmd = cmd.getMetaDataForManagedMemberAtAbsolutePosition(fieldNumber);
RelationType relationType = mmd.getRelationType(ec.getClassLoaderResolver());
Object value;
if (mapping instanceof EmbeddedPCMapping || mapping instanceof SerialisedPCMapping || mapping instanceof SerialisedReferenceMapping) {
value = mapping.getObject(ec, rs, mapIdx.getColumnPositions(), sm, fieldNumber);
} else {
if (mmd.isSingleCollection()) {
StatementClassMapping relationMappings = resultMappings.getMappingDefinitionForMemberPosition(fieldNumber);
if (relationMappings != null) {
Class type = ec.getClassLoaderResolver().classForName(mmd.getCollection().getElementType());
value = processSubObjectFields(mapping, type, relationMappings);
ElementContainerHandler containerHandler = ec.getTypeManager().getContainerHandler(mmd.getType());
value = containerHandler.newContainer(mmd, value);
} else {
value = mapping.getObject(ec, rs, mapIdx.getColumnPositions());
}
} else if (RelationType.isRelationSingleValued(relationType)) {
// Process fields of sub-object if available in this result set
StatementClassMapping relationMappings = resultMappings.getMappingDefinitionForMemberPosition(fieldNumber);
if (relationMappings != null) {
value = processSubObjectFields(mapping, mmd.getType(), relationMappings);
} else {
value = mapping.getObject(ec, rs, mapIdx.getColumnPositions());
}
} else {
value = mapping.getObject(ec, rs, mapIdx.getColumnPositions());
}
}
if (sm != null) {
if (relationType == RelationType.ONE_TO_ONE_BI && value != null) {
// Store the value at the other side of the 1-1 BI for use later if required
DNStateManager otherSM = ec.findStateManager(value);
if (otherSM != null) {
AbstractMemberMetaData[] relMmds = mmd.getRelatedMemberMetaData(ec.getClassLoaderResolver());
if (!otherSM.isFieldLoaded(relMmds[0].getAbsoluteFieldNumber()) && relMmds[0].getType().isAssignableFrom(sm.getObject().getClass())) {
otherSM.storeFieldValue(relMmds[0].getAbsoluteFieldNumber(), sm.getExternalObjectId());
}
}
}
if (cmd.getSCOMutableMemberFlags()[fieldNumber]) {
// Wrap any SCO mutable fields
return SCOUtils.wrapSCOField(sm, fieldNumber, value, false);
} else if (RelationType.isRelationSingleValued(relationType) && (mmd.getEmbeddedMetaData() != null && mmd.getEmbeddedMetaData().getOwnerMember() != null)) {
// Embedded PC, so make sure the field is wrapped where appropriate TODO This should be part of ManagedRelationships
sm.updateOwnerFieldInEmbeddedField(fieldNumber, value);
return value;
}
}
return value;
}
use of org.datanucleus.store.rdbms.query.StatementMappingIndex in project datanucleus-rdbms by datanucleus.
the class ParameterSetter method storeObjectField.
public void storeObjectField(int fieldNumber, Object value) {
StatementMappingIndex mapIdx = stmtMappings.getMappingForMemberPosition(fieldNumber);
if (value == null && mapIdx.getMapping().getMemberMetaData().getNullValue() == NullValue.EXCEPTION) {
throw new NucleusUserException(Localiser.msg("052400", mapIdx.getMapping().getMemberMetaData().getFullFieldName()));
}
try {
JavaTypeMapping mapping = mapIdx.getMapping();
boolean provideOwner = false;
if (mapping instanceof EmbeddedPCMapping || mapping instanceof SerialisedPCMapping || mapping instanceof SerialisedReferenceMapping || mapping instanceof PersistableMapping || mapping instanceof InterfaceMapping) {
// Pass in the owner StateManager/field for any mappings that have relations
provideOwner = true;
}
if (mapIdx.getNumberOfParameterOccurrences() > 0) {
for (int i = 0; i < mapIdx.getNumberOfParameterOccurrences(); i++) {
// Set this value for all occurrences of this parameter
if (provideOwner) {
mapping.setObject(ec, statement, mapIdx.getParameterPositionsForOccurrence(i), value, sm, fieldNumber);
} else {
mapping.setObject(ec, statement, mapIdx.getParameterPositionsForOccurrence(i), value);
}
}
} else {
// Important : call setObject even if the paramIndices is null (reachability)
if (provideOwner) {
mapping.setObject(ec, statement, null, value, sm, fieldNumber);
} else {
mapping.setObject(ec, statement, null, value);
}
}
AbstractMemberMetaData mmd = sm.getClassMetaData().getMetaDataForManagedMemberAtAbsolutePosition(fieldNumber);
RelationType relationType = mmd.getRelationType(ec.getClassLoaderResolver());
if (sm.getClassMetaData().getSCOMutableMemberFlags()[fieldNumber]) {
SCOUtils.wrapSCOField(sm, fieldNumber, value, true);
} else if (RelationType.isRelationSingleValued(relationType) && (mmd.getEmbeddedMetaData() != null && mmd.getEmbeddedMetaData().getOwnerMember() != null)) {
// Embedded PC, so make sure the field is wrapped where appropriate TODO This should be part of ManagedRelationships
sm.updateOwnerFieldInEmbeddedField(fieldNumber, value);
}
} catch (NotYetFlushedException e) {
if (sm.getClassMetaData().getMetaDataForManagedMemberAtAbsolutePosition(fieldNumber).getNullValue() == NullValue.EXCEPTION) {
throw e;
}
sm.updateFieldAfterInsert(e.getPersistable(), fieldNumber);
}
}
use of org.datanucleus.store.rdbms.query.StatementMappingIndex in project datanucleus-rdbms by datanucleus.
the class OracleClobColumnMapping method setPostProcessing.
@SuppressWarnings("deprecation")
@Override
public void setPostProcessing(DNStateManager sm, Object value) {
String stringValue = (String) value;
ExecutionContext ec = sm.getExecutionContext();
Table table = column.getTable();
RDBMSStoreManager storeMgr = table.getStoreManager();
if (table instanceof DatastoreClass) {
// CLOB within a primary table
DatastoreClass classTable = (DatastoreClass) table;
// Generate "SELECT {clobColumn} 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);
sqlStmt.select(blobSqlTbl, column, null);
StatementClassMapping mappingDefinition = new StatementClassMapping();
AbstractClassMetaData cmd = sm.getClassMetaData();
SQLExpressionFactory exprFactory = storeMgr.getSQLExpressionFactory();
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.getNumberOfColumnMappings()];
for (int j = 0; j < pkMapping.getNumberOfColumnMappings(); j++) {
inputParams[j] = inputParamNum++;
}
pkIdx.addParameterOccurrence(inputParams);
}
}
String textStmt = sqlStmt.getSQLText().toSQL();
if (sm.isEmbedded()) {
// This mapping is embedded, so navigate back to the real owner since that is the "id" in the table
DNStateManager embeddedOwner = ec.getOwnerForEmbeddedStateManager(sm);
if (embeddedOwner != null) {
// TODO Should check if the owner is stored in this table
sm = embeddedOwner;
}
}
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), sm.getInternalObjectId());
}
} else if (cmd.getIdentityType() == IdentityType.APPLICATION) {
sm.provideFields(cmd.getPKMemberPositions(), new ParameterSetter(sm, ps, mappingDefinition));
}
ResultSet rs = sqlControl.executeStatementQuery(ec, mconn, textStmt, ps);
try {
if (!rs.next()) {
throw new NucleusObjectNotFoundException(Localiser.msg("050018", IdentityUtils.getPersistableIdentityForId(sm.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 CLOB type
oracle.sql.CLOB clob = (oracle.sql.CLOB) rs.getClob(1);
if (clob != null) {
// Deprecated but what can you do
clob.putString(1, stringValue);
}
} else {
// Oracle JDBC drivers 10 and above supposedly use the JDBC standard class for Clobs
java.sql.Clob clob = rs.getClob(1);
if (clob != null) {
clob.setString(1, stringValue);
}
}
} finally {
rs.close();
}
} finally {
sqlControl.closeStatement(mconn, ps);
}
} finally {
mconn.release();
}
} catch (SQLException e) {
throw new NucleusDataStoreException("Update of CLOB value failed: " + textStmt, e);
}
} else {
// TODO Support join table
throw new NucleusDataStoreException("We do not support INSERT/UPDATE CLOB post processing of non-primary table " + table);
}
}
use of org.datanucleus.store.rdbms.query.StatementMappingIndex in project datanucleus-rdbms by datanucleus.
the class JoinMapStore method getSQLStatementForGet.
/**
* Method to return an SQLStatement for retrieving the value for a key.
* Selects the join table and optionally joins to the value table if it has its own table.
* @param ownerSM StateManager for the owning object
* @return The SQLStatement
*/
protected SelectStatement getSQLStatementForGet(DNStateManager ownerSM) {
SelectStatement sqlStmt = null;
ExecutionContext ec = ownerSM.getExecutionContext();
final ClassLoaderResolver clr = ownerSM.getExecutionContext().getClassLoaderResolver();
Class<?> valueCls = clr.classForName(this.valueType);
if (valuesAreEmbedded || valuesAreSerialised) {
// Value is stored in join table
sqlStmt = new SelectStatement(storeMgr, mapTable, null, null);
sqlStmt.setClassLoaderResolver(clr);
sqlStmt.select(sqlStmt.getPrimaryTable(), valueMapping, null);
} else {
// Value is stored in own table
getMappingDef = new StatementClassMapping();
if (!valueCmd.getFullClassName().equals(valueCls.getName())) {
valueCls = clr.classForName(valueCmd.getFullClassName());
}
UnionStatementGenerator stmtGen = new UnionStatementGenerator(storeMgr, clr, valueCls, true, null, null, mapTable, null, valueMapping);
stmtGen.setOption(SelectStatementGenerator.OPTION_SELECT_DN_TYPE);
getMappingDef.setNucleusTypeColumnName(UnionStatementGenerator.DN_TYPE_COLUMN);
sqlStmt = stmtGen.getStatement(ec);
// Select the value field(s)
SQLTable valueSqlTbl = sqlStmt.getTable(valueTable, sqlStmt.getPrimaryTable().getGroupName());
if (valueSqlTbl == null) {
// Root value candidate has no table, so try to find a value candidate with a table that exists in this statement
Collection<String> valueSubclassNames = storeMgr.getSubClassesForClass(valueType, true, clr);
if (valueSubclassNames != null && !valueSubclassNames.isEmpty()) {
for (String valueSubclassName : valueSubclassNames) {
DatastoreClass valueTbl = storeMgr.getDatastoreClass(valueSubclassName, clr);
if (valueTbl != null) {
valueSqlTbl = sqlStmt.getTable(valueTbl, sqlStmt.getPrimaryTable().getGroupName());
if (valueSqlTbl != null) {
break;
}
}
}
}
}
SQLStatementHelper.selectFetchPlanOfSourceClassInStatement(sqlStmt, getMappingDef, ec.getFetchPlan(), valueSqlTbl, valueCmd, ec.getFetchPlan().getMaxFetchDepth());
}
// Apply condition on owner field to filter by owner
SQLExpressionFactory exprFactory = storeMgr.getSQLExpressionFactory();
SQLTable ownerSqlTbl = SQLStatementHelper.getSQLTableForMappingOfTable(sqlStmt, sqlStmt.getPrimaryTable(), ownerMapping);
SQLExpression ownerExpr = exprFactory.newExpression(sqlStmt, ownerSqlTbl, ownerMapping);
SQLExpression ownerVal = exprFactory.newLiteralParameter(sqlStmt, ownerMapping, null, "OWNER");
sqlStmt.whereAnd(ownerExpr.eq(ownerVal), true);
// Apply condition on key
if (keyMapping instanceof SerialisedMapping) {
// if the keyMapping contains a BLOB column (or any other column not supported by the database as primary key), uses like instead of the operator OP_EQ (=)
// in future do not check if the keyMapping is of ObjectMapping, but use the database adapter to check the data types not supported as primary key
// if object mapping (BLOB) use like
SQLExpression keyExpr = exprFactory.newExpression(sqlStmt, sqlStmt.getPrimaryTable(), keyMapping);
SQLExpression keyVal = exprFactory.newLiteralParameter(sqlStmt, keyMapping, null, "KEY");
sqlStmt.whereAnd(new org.datanucleus.store.rdbms.sql.expression.BooleanExpression(keyExpr, Expression.OP_LIKE, keyVal), true);
} else {
SQLExpression keyExpr = exprFactory.newExpression(sqlStmt, sqlStmt.getPrimaryTable(), keyMapping);
SQLExpression keyVal = exprFactory.newLiteralParameter(sqlStmt, keyMapping, null, "KEY");
sqlStmt.whereAnd(keyExpr.eq(keyVal), true);
}
// Input parameter(s) - owner, key
int inputParamNum = 1;
StatementMappingIndex ownerIdx = new StatementMappingIndex(ownerMapping);
StatementMappingIndex keyIdx = new StatementMappingIndex(keyMapping);
int numberOfUnions = sqlStmt.getNumberOfUnions();
// Add parameter occurrence for each union of statement
for (int j = 0; j < numberOfUnions + 1; j++) {
int[] ownerPositions = new int[ownerMapping.getNumberOfColumnMappings()];
for (int k = 0; k < ownerPositions.length; k++) {
ownerPositions[k] = inputParamNum++;
}
ownerIdx.addParameterOccurrence(ownerPositions);
int[] keyPositions = new int[keyMapping.getNumberOfColumnMappings()];
for (int k = 0; k < keyPositions.length; k++) {
keyPositions[k] = inputParamNum++;
}
keyIdx.addParameterOccurrence(keyPositions);
}
getMappingParams = new StatementParameterMapping();
getMappingParams.addMappingForParameter("owner", ownerIdx);
getMappingParams.addMappingForParameter("key", keyIdx);
return sqlStmt;
}
Aggregations