use of org.datanucleus.store.rdbms.mapping.java.ReferenceMapping in project datanucleus-rdbms by datanucleus.
the class BackingStoreHelper method populateElementForWhereClauseInStatement.
/**
* Convenience method to populate the passed PreparedStatement with the value for the element in a WHERE clause.
* Like the above method except handles reference mappings where you want have some implementations as "IS NULL"
* in the SQL, and just want to set the actual implementation FK for the element.
* Not used with embedded PC elements.
* @param ec execution context
* @param ps The PreparedStatement
* @param element The element
* @param jdbcPosition Position in JDBC statement to populate
* @param elementMapping mapping for the element
* @return The next position in the JDBC statement
*/
public static int populateElementForWhereClauseInStatement(ExecutionContext ec, PreparedStatement ps, Object element, int jdbcPosition, JavaTypeMapping elementMapping) {
if (elementMapping.getColumnMapping(0).insertValuesOnInsert()) {
if (elementMapping instanceof ReferenceMapping && elementMapping.getNumberOfColumnMappings() > 1) {
ReferenceMapping elemRefMapping = (ReferenceMapping) elementMapping;
JavaTypeMapping[] elemFkMappings = elemRefMapping.getJavaTypeMapping();
int[] positions = null;
for (int i = 0; i < elemFkMappings.length; i++) {
if (elemFkMappings[i].getType().equals(element.getClass().getName())) {
// The FK for the element in question, so populate this
positions = new int[elemFkMappings[i].getNumberOfColumnMappings()];
for (int j = 0; j < positions.length; j++) {
positions[j] = jdbcPosition++;
}
}
}
if (positions != null) {
elementMapping.setObject(ec, ps, positions, element);
jdbcPosition = jdbcPosition + positions.length;
}
} else {
elementMapping.setObject(ec, ps, MappingHelper.getMappingIndices(jdbcPosition, elementMapping), element);
jdbcPosition = jdbcPosition + elementMapping.getNumberOfColumnMappings();
}
}
return jdbcPosition;
}
use of org.datanucleus.store.rdbms.mapping.java.ReferenceMapping in project datanucleus-rdbms by datanucleus.
the class FKMapStore method getValue.
/**
* Method to retrieve a value from the Map given the key.
* @param ownerSM StateManager for the owner of the map.
* @param key The key to retrieve the value for.
* @return The value for this key
* @throws NoSuchElementException if the key was not found
*/
protected V getValue(DNStateManager ownerSM, Object key) throws NoSuchElementException {
if (!validateKeyForReading(ownerSM, key)) {
return null;
}
ExecutionContext ec = ownerSM.getExecutionContext();
if (getStmtLocked == null) {
synchronized (// Make sure this completes in case another thread needs the same info
this) {
// Generate the statement, and statement mapping/parameter information
SQLStatement sqlStmt = getSQLStatementForGet(ownerSM);
getStmtUnlocked = sqlStmt.getSQLText().toSQL();
sqlStmt.addExtension(SQLStatement.EXTENSION_LOCK_FOR_UPDATE, true);
getStmtLocked = sqlStmt.getSQLText().toSQL();
}
}
Boolean serializeRead = ec.getTransaction().getSerializeRead();
String stmt = (serializeRead != null && serializeRead ? getStmtLocked : getStmtUnlocked);
Object value = null;
try {
ManagedConnection mconn = storeMgr.getConnectionManager().getConnection(ec);
SQLController sqlControl = storeMgr.getSQLController();
try {
// Create the statement and supply owner/key params
PreparedStatement ps = sqlControl.getStatementForQuery(mconn, stmt);
StatementMappingIndex ownerIdx = getMappingParams.getMappingForParameter("owner");
int numParams = ownerIdx.getNumberOfParameterOccurrences();
for (int paramInstance = 0; paramInstance < numParams; paramInstance++) {
ownerIdx.getMapping().setObject(ec, ps, ownerIdx.getParameterPositionsForOccurrence(paramInstance), ownerSM.getObject());
}
StatementMappingIndex keyIdx = getMappingParams.getMappingForParameter("key");
numParams = keyIdx.getNumberOfParameterOccurrences();
for (int paramInstance = 0; paramInstance < numParams; paramInstance++) {
keyIdx.getMapping().setObject(ec, ps, keyIdx.getParameterPositionsForOccurrence(paramInstance), key);
}
try {
ResultSet rs = sqlControl.executeStatementQuery(ec, mconn, stmt, ps);
try {
boolean found = rs.next();
if (!found) {
throw new NoSuchElementException();
}
if (valuesAreEmbedded || valuesAreSerialised) {
// Embedded/serialised into table of key
int[] param = new int[valueMapping.getNumberOfColumnMappings()];
for (int i = 0; i < param.length; ++i) {
param[i] = i + 1;
}
if (valueMapping instanceof SerialisedPCMapping || valueMapping instanceof SerialisedReferenceMapping || valueMapping instanceof EmbeddedKeyPCMapping) {
// Value = Serialised
String msg = "You appear to have a map (persistable) value serialised/embedded into the key of the map at " + getOwnerMemberMetaData().getFullFieldName() + " Not supported";
NucleusLogger.PERSISTENCE.error(msg);
throw new NucleusDataStoreException(msg);
}
// Value = Non-PC
value = valueMapping.getObject(ec, rs, param);
} else if (valueMapping instanceof ReferenceMapping) {
// Value = Reference (Interface/Object)
int[] param = new int[valueMapping.getNumberOfColumnMappings()];
for (int i = 0; i < param.length; ++i) {
param[i] = i + 1;
}
value = valueMapping.getObject(ec, rs, param);
} else {
// Value = PC
value = new PersistentClassROF(ec, rs, false, ec.getFetchPlan(), getMappingDef, valueCmd, clr.classForName(valueType)).getObject();
}
JDBCUtils.logWarnings(rs);
} finally {
rs.close();
}
} finally {
sqlControl.closeStatement(mconn, ps);
}
} finally {
mconn.release();
}
} catch (SQLException e) {
throw new NucleusDataStoreException(Localiser.msg("056014", stmt), e);
}
return (V) value;
}
use of org.datanucleus.store.rdbms.mapping.java.ReferenceMapping in project datanucleus-rdbms by datanucleus.
the class CollectionContainsMethod method containsAsJoin.
/**
* Method to return an expression for Collection.contains using INNER JOIN to the element.
* This is only for use when there are no "!contains" and no "OR" operations.
* Creates SQL by adding INNER JOIN to the join table (where it exists), and also to the element table
* adding an AND condition on the element (with value of the elemExpr).
* Returns a BooleanExpression "TRUE" (since the INNER JOIN will guarantee if the element is
* contained of not).
* @param stmt SQLStatement
* @param collExpr Collection expression
* @param elemExpr Expression for the element
* @param joinType Join type
* @return Contains expression
*/
protected SQLExpression containsAsJoin(SQLStatement stmt, CollectionExpression collExpr, SQLExpression elemExpr, SQLJoin.JoinType joinType) {
boolean elemIsUnbound = (elemExpr instanceof UnboundExpression);
String varName = null;
String elemAlias = null;
String elemType = null;
if (elemIsUnbound) {
varName = ((UnboundExpression) elemExpr).getVariableName();
NucleusLogger.QUERY.debug("collection.contains(" + elemExpr + ") binding unbound variable " + varName + " using INNER JOIN");
} else if (!stmt.getQueryGenerator().hasExplicitJoins()) {
if (stmt.getJoinTypeForTable(elemExpr.getSQLTable()) == JoinType.CROSS_JOIN) {
elemAlias = stmt.removeCrossJoin(elemExpr.getSQLTable());
elemIsUnbound = true;
elemType = elemExpr.getJavaTypeMapping().getType();
NucleusLogger.QUERY.debug("collection.contains(" + elemExpr + ") 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 = collExpr.getJavaTypeMapping().getMemberMetaData();
AbstractClassMetaData elemCmd = mmd.getCollection().getElementClassMetaData(clr);
CollectionTable joinTbl = (CollectionTable) storeMgr.getTable(mmd);
if (elemIsUnbound) {
Class varType = stmt.getQueryGenerator().getTypeOfVariable(varName);
if (varType != null) {
elemType = varType.getName();
elemCmd = storeMgr.getMetaDataManager().getMetaDataForClass(elemType, clr);
}
}
if (elemType == null) {
elemType = mmd.getCollection().getElementType();
}
if (joinTbl != null) {
// JoinTable Collection - join from owner to join, then from join to element
if (elemCmd == null) {
// Collection<Non-PC>
SQLTable joinSqlTbl = stmt.join(joinType, collExpr.getSQLTable(), collExpr.getSQLTable().getTable().getIdMapping(), joinTbl, elemAlias, joinTbl.getOwnerMapping(), null, null);
SQLExpression elemIdExpr = exprFactory.newExpression(stmt, joinSqlTbl, joinTbl.getElementMapping());
if (elemIsUnbound) {
// Bind the variable in the QueryGenerator
stmt.getQueryGenerator().bindVariable(varName, null, elemIdExpr.getSQLTable(), elemIdExpr.getJavaTypeMapping());
} else {
// Add restrict to element
addRestrictionOnElement(stmt, elemIdExpr, elemExpr);
}
} else {
// Collection<PC>
SQLTable joinSqlTbl = stmt.join(joinType, collExpr.getSQLTable(), collExpr.getSQLTable().getTable().getIdMapping(), joinTbl, null, joinTbl.getOwnerMapping(), null, null);
if (!mmd.getCollection().isEmbeddedElement()) {
DatastoreClass elemTbl = storeMgr.getDatastoreClass(elemType, clr);
SQLTable elemSqlTbl = null;
if (joinTbl.getElementMapping() instanceof ReferenceMapping && ((ReferenceMapping) joinTbl.getElementMapping()).getMappingStrategy() == ReferenceMapping.PER_IMPLEMENTATION_MAPPING) {
JavaTypeMapping elemMapping = null;
JavaTypeMapping[] elemImplMappings = ((ReferenceMapping) joinTbl.getElementMapping()).getJavaTypeMapping();
for (int i = 0; i < elemImplMappings.length; i++) {
if (elemImplMappings[i].getType().equals(elemCmd.getFullClassName())) {
elemMapping = elemImplMappings[i];
break;
}
}
elemSqlTbl = stmt.join(joinType, joinSqlTbl, elemMapping, joinTbl.getElementMapping(), elemTbl, elemAlias, elemTbl.getIdMapping(), null, null, null, true, null);
} else {
elemSqlTbl = stmt.join(joinType, joinSqlTbl, joinTbl.getElementMapping(), elemTbl, elemAlias, elemTbl.getIdMapping(), null, null);
}
SQLExpression elemIdExpr = exprFactory.newExpression(stmt, elemSqlTbl, elemTbl.getIdMapping());
if (elemIsUnbound) {
// Bind the variable in the QueryGenerator
stmt.getQueryGenerator().bindVariable(varName, elemCmd, elemIdExpr.getSQLTable(), elemIdExpr.getJavaTypeMapping());
} else {
// Add restrict to element
addRestrictionOnElement(stmt, elemIdExpr, elemExpr);
}
} else {
SQLExpression elemIdExpr = exprFactory.newExpression(stmt, joinSqlTbl, joinTbl.getElementMapping());
if (elemIsUnbound) {
// Bind the variable in the QueryGenerator
stmt.getQueryGenerator().bindVariable(varName, elemCmd, elemIdExpr.getSQLTable(), elemIdExpr.getJavaTypeMapping());
} else {
// Add restrict to element
addRestrictionOnElement(stmt, elemIdExpr, elemExpr);
}
}
}
} else {
// FK Collection - join from owner to element
DatastoreClass elemTbl = storeMgr.getDatastoreClass(mmd.getCollection().getElementType(), clr);
JavaTypeMapping ownerMapping = null;
if (mmd.getMappedBy() != null) {
ownerMapping = elemTbl.getMemberMapping(mmd.getRelatedMemberMetaData(clr)[0]);
} else {
ownerMapping = elemTbl.getExternalMapping(mmd, MappingType.EXTERNAL_FK);
}
SQLTable elemSqlTbl = stmt.join(joinType, collExpr.getSQLTable(), collExpr.getSQLTable().getTable().getIdMapping(), elemTbl, elemAlias, ownerMapping, null, null);
if (elemIsUnbound) {
SQLExpression elemIdExpr = null;
if (!elemType.equals(mmd.getCollection().getElementType())) {
// Variable is defined as a subclass of the declared type so add extra join to variable type
DatastoreClass varTbl = storeMgr.getDatastoreClass(elemType, clr);
SQLTable varSqlTbl = stmt.join(joinType, elemSqlTbl, elemTbl.getIdMapping(), varTbl, null, varTbl.getIdMapping(), null, null);
elemIdExpr = exprFactory.newExpression(stmt, varSqlTbl, varTbl.getIdMapping());
} else {
elemIdExpr = exprFactory.newExpression(stmt, elemSqlTbl, elemTbl.getIdMapping());
}
// Bind the variable in the QueryGenerator
stmt.getQueryGenerator().bindVariable(varName, elemCmd, elemIdExpr.getSQLTable(), elemIdExpr.getJavaTypeMapping());
} else {
// Add restrict to element
SQLExpression elemIdExpr = exprFactory.newExpression(stmt, elemSqlTbl, elemTbl.getIdMapping());
addRestrictionOnElement(stmt, elemIdExpr, elemExpr);
}
}
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.mapping.java.ReferenceMapping in project datanucleus-rdbms by datanucleus.
the class JDOHelperGetObjectIdMethod method getExpression.
/* (non-Javadoc)
* @see org.datanucleus.store.rdbms.sql.method.SQLMethod#getExpression(org.datanucleus.store.rdbms.sql.expression.SQLExpression, java.util.List)
*/
public SQLExpression getExpression(SQLStatement stmt, SQLExpression ignore, List<SQLExpression> args) {
if (args == null || args.size() == 0) {
throw new NucleusUserException("Cannot invoke JDOHelper.getObjectId without an argument");
}
SQLExpression expr = args.get(0);
if (expr == null) {
return new NullLiteral(stmt, null, null, null);
}
if (expr instanceof SQLLiteral) {
RDBMSStoreManager storeMgr = stmt.getRDBMSManager();
ApiAdapter api = storeMgr.getApiAdapter();
Object id = api.getIdForObject(((SQLLiteral) expr).getValue());
if (id == null) {
return new NullLiteral(stmt, null, null, null);
}
JavaTypeMapping m = stmt.getSQLExpressionFactory().getMappingForType(id.getClass(), true);
return new ObjectLiteral(stmt, m, id, null);
} else if (ObjectExpression.class.isAssignableFrom(expr.getClass())) {
// When the expression represents a PC object need to extract out as the identity
if (expr.getJavaTypeMapping() instanceof PersistableMapping) {
JavaTypeMapping mapping = new PersistableIdMapping((PersistableMapping) expr.getJavaTypeMapping());
return new ObjectExpression(stmt, expr.getSQLTable(), mapping);
} else if (expr.getJavaTypeMapping() instanceof ReferenceMapping) {
JavaTypeMapping mapping = new ReferenceIdMapping((ReferenceMapping) expr.getJavaTypeMapping());
return new ObjectExpression(stmt, expr.getSQLTable(), mapping);
}
return expr;
}
throw new IllegalExpressionOperationException("JDOHelper.getObjectId", expr);
}
use of org.datanucleus.store.rdbms.mapping.java.ReferenceMapping in project datanucleus-rdbms by datanucleus.
the class ObjectExpression method processComparisonOfImplementationWithReference.
protected BooleanExpression processComparisonOfImplementationWithReference(SQLExpression refExpr, SQLExpression implExpr, boolean negate) {
ReferenceMapping refMapping = (ReferenceMapping) refExpr.mapping;
JavaTypeMapping[] implMappings = refMapping.getJavaTypeMapping();
String implType = implExpr.mapping.getType();
String implActualType;
if (implExpr instanceof ObjectLiteral && ((ObjectLiteral) implExpr).getValue() != null) {
// Use type of literal directly if available. This caters for the case where we have an interface implementation and it is sharing a table with another implementation
implActualType = ((ObjectLiteral) implExpr).getValue().getClass().getName();
} else {
implActualType = implType;
}
int subExprStart = 0;
for (int i = 0; i < implMappings.length; i++) {
// Either implementation-classes is exactly implExpr or root mapping class of implExpr, but still fail if anything between
if (implMappings[i].getType().equals(implActualType) || implMappings[i].getType().equals(implType)) {
// Found implementation in question, so do AND of its column(s)
int subExprEnd = subExprStart + implMappings[i].getNumberOfColumnMappings();
int implMappingNum = 0;
BooleanExpression bExpr = refExpr.subExprs.getExpression(subExprStart).eq(implExpr.subExprs.getExpression(implMappingNum++));
for (int j = subExprStart + 1; j < subExprEnd; j++) {
bExpr = bExpr.and(refExpr.subExprs.getExpression(j).eq(implExpr.subExprs.getExpression(implMappingNum++)));
}
return (negate ? new BooleanExpression(Expression.OP_NOT, bExpr.encloseInParentheses()) : bExpr);
}
subExprStart += implMappings[i].getNumberOfColumnMappings();
}
// Implementation not found explicitly, so just treat as if "ObjectExpression.eq(ObjectExpression)". See e.g JDO TCK "companyPMInterface" test
return ExpressionUtils.getEqualityExpressionForObjectExpressions((ObjectExpression) refExpr, (ObjectExpression) implExpr, true);
}
Aggregations