use of org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping in project datanucleus-rdbms by datanucleus.
the class SQLStatementHelper method applyParametersToStatement.
/**
* Convenience method to apply parameter values to the provided statement.
* @param ps The prepared statement
* @param ec ExecutionContext
* @param parameters The parameters
* @param paramNameByPosition Optional map of parameter names keyed by the position
* @param paramValuesByName Value of parameter keyed by name (or position)
*/
public static void applyParametersToStatement(PreparedStatement ps, ExecutionContext ec, List<SQLStatementParameter> parameters, Map<Integer, String> paramNameByPosition, Map paramValuesByName) {
if (parameters != null) {
int num = 1;
Map<String, Integer> paramNumberByName = null;
int nextParamNumber = 0;
Iterator<SQLStatementParameter> i = parameters.iterator();
while (i.hasNext()) {
SQLStatementParameter param = i.next();
JavaTypeMapping mapping = param.getMapping();
RDBMSStoreManager storeMgr = mapping.getStoreManager();
// Find the overall parameter value for this parameter
Object value = null;
if (paramNumberByName != null) {
// Parameters are numbered but the query has named, so use lookup
Integer position = paramNumberByName.get("" + param.getName());
if (position == null) {
value = paramValuesByName.get(Integer.valueOf(nextParamNumber));
paramNumberByName.put(param.getName(), nextParamNumber);
nextParamNumber++;
} else {
value = paramValuesByName.get(position);
}
} else {
if (paramValuesByName.containsKey(param.getName())) {
// Named parameter has value in the input map
value = paramValuesByName.get(param.getName());
} else {
// Named parameter doesn't have value, so maybe using numbered input params
if (paramNameByPosition != null) {
int paramPosition = -1;
Set<String> paramNamesEncountered = new HashSet<>();
for (Map.Entry<Integer, String> entry : paramNameByPosition.entrySet()) {
String paramName = entry.getValue();
if (!paramNamesEncountered.contains(paramName)) {
paramPosition++;
paramNamesEncountered.add(paramName);
}
if (paramName.equals(param.getName())) {
value = paramValuesByName.get(paramPosition);
break;
}
}
paramNamesEncountered.clear();
paramNamesEncountered = null;
} else {
try {
value = paramValuesByName.get(Integer.valueOf(param.getName()));
} catch (NumberFormatException nfe) {
value = paramValuesByName.get(Integer.valueOf(nextParamNumber));
paramNumberByName = new HashMap<>();
paramNumberByName.put(param.getName(), Integer.valueOf(nextParamNumber));
nextParamNumber++;
}
}
}
}
AbstractClassMetaData cmd = ec.getMetaDataManager().getMetaDataForClass(mapping.getType(), ec.getClassLoaderResolver());
if (param.getColumnNumber() >= 0 && cmd != null) {
// Apply the value for this column of the mapping
Object colValue = null;
if (value != null) {
if (cmd.getIdentityType() == IdentityType.DATASTORE) {
colValue = mapping.getValueForDatastoreMapping(ec.getNucleusContext(), param.getColumnNumber(), value);
} else if (cmd.getIdentityType() == IdentityType.APPLICATION) {
colValue = getValueForPrimaryKeyIndexOfObjectUsingReflection(value, param.getColumnNumber(), cmd, storeMgr, ec.getClassLoaderResolver());
}
}
mapping.getDatastoreMapping(param.getColumnNumber()).setObject(ps, num, colValue);
} else {
// Apply the value as a whole
if (ec.getApiAdapter().isPersistable(value)) {
if (!ec.getApiAdapter().isPersistent(value) && !ec.getApiAdapter().isDetached(value)) {
// Transient persistable object passed in as query parameter! We cannot simply use mapping.setObject since it will PERSIST the object
// See also JDO TCK Assertion ID: A14.6.2-44 "Comparisons between persistent and non-persistent instances return not equal"
boolean supported = false;
if (!supported) {
// Transient persistable object, so don't use (use null instead) since would cause its persistence
NucleusLogger.QUERY.warn("Attempt to use transient object as parameter in query. Not supported, so using NULL for parameter value");
mapping.setObject(ec, ps, MappingHelper.getMappingIndices(num, mapping), null);
}
} else if (ec.getApiAdapter().isDetached(value)) {
// Detached, so avoid re-attaching
Object id = ec.getApiAdapter().getIdForObject(value);
PersistableIdMapping idMapping = new PersistableIdMapping((PersistableMapping) mapping);
idMapping.setObject(ec, ps, MappingHelper.getMappingIndices(num, idMapping), id);
} else {
mapping.setObject(ec, ps, MappingHelper.getMappingIndices(num, mapping), value);
}
} else {
if (mapping.getNumberOfDatastoreMappings() == 1) {
// Set whole object and only 1 column
mapping.setObject(ec, ps, MappingHelper.getMappingIndices(num, mapping), value);
} else if (mapping.getNumberOfDatastoreMappings() > 1 && param.getColumnNumber() == (mapping.getNumberOfDatastoreMappings() - 1)) {
// Set whole object and this is the last parameter entry for it, so set now
mapping.setObject(ec, ps, MappingHelper.getMappingIndices(num - mapping.getNumberOfDatastoreMappings() + 1, mapping), value);
}
}
}
num++;
}
}
}
use of org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping 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.mapping.java.JavaTypeMapping in project datanucleus-rdbms by datanucleus.
the class CollectionLiteral method invoke.
public SQLExpression invoke(String methodName, List args) {
if (methodName.equals("get") && args.size() == 1 && value instanceof List) {
// List.get
SQLExpression argExpr = (SQLExpression) args.get(0);
if (argExpr instanceof SQLLiteral) {
// List.get(SQLLiteral)
Object val = ((List) value).get((Integer) ((SQLLiteral) argExpr).getValue());
if (val == null) {
return new NullLiteral(stmt, null, null, null);
}
JavaTypeMapping m = stmt.getRDBMSManager().getSQLExpressionFactory().getMappingForType(val.getClass(), false);
return new ObjectLiteral(stmt, m, val, null);
}
// Don't support List.get(SQLExpression)
throw new IllegalExpressionOperationException(this, "get", argExpr);
}
return super.invoke(methodName, args);
}
use of org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping 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.mapping.java.JavaTypeMapping in project datanucleus-rdbms by datanucleus.
the class MapContainsKeyMethod 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 expr, List<SQLExpression> args) {
if (args == null || args.size() == 0 || args.size() > 1) {
throw new NucleusException(Localiser.msg("060016", "containsKey", "MapExpression", 1));
}
MapExpression mapExpr = (MapExpression) expr;
SQLExpression keyExpr = args.get(0);
if (keyExpr.isParameter()) {
// Key is a parameter so make sure its type is set
AbstractMemberMetaData mmd = mapExpr.getJavaTypeMapping().getMemberMetaData();
if (mmd != null && mmd.getMap() != null) {
Class keyCls = stmt.getQueryGenerator().getClassLoaderResolver().classForName(mmd.getMap().getKeyType());
stmt.getQueryGenerator().bindParameter(keyExpr.getParameterName(), keyCls);
}
}
SQLExpressionFactory exprFactory = stmt.getSQLExpressionFactory();
ClassLoaderResolver clr = stmt.getQueryGenerator().getClassLoaderResolver();
if (expr instanceof MapLiteral) {
// Literal Map
MapLiteral lit = (MapLiteral) expr;
Map map = (Map) lit.getValue();
JavaTypeMapping m = exprFactory.getMappingForType(boolean.class, true);
if (map == null || map.size() == 0) {
return exprFactory.newLiteral(stmt, m, true).eq(exprFactory.newLiteral(stmt, m, false));
}
boolean useInExpression = false;
List<SQLExpression> mapKeyExprs = lit.getKeyLiteral().getKeyExpressions();
if (mapKeyExprs != null && !mapKeyExprs.isEmpty()) {
// Make sure the the map key(s) are compatible with the keyExpr
boolean incompatible = true;
Class elemtype = clr.classForName(keyExpr.getJavaTypeMapping().getType());
Iterator<SQLExpression> mapKeyExprIter = mapKeyExprs.iterator();
while (mapKeyExprIter.hasNext()) {
SQLExpression mapKeyExpr = mapKeyExprIter.next();
Class mapKeyType = clr.classForName(mapKeyExpr.getJavaTypeMapping().getType());
if (keyTypeCompatible(elemtype, mapKeyType)) {
incompatible = false;
break;
}
}
if (incompatible) {
// The provided element type isn't assignable to any of the input collection elements!
return exprFactory.newLiteral(stmt, m, true).eq(exprFactory.newLiteral(stmt, m, false));
}
// Check if we should compare using an "IN (...)" expression
SQLExpression mapKeyExpr = mapKeyExprs.get(0);
if (mapKeyExpr instanceof StringExpression || mapKeyExpr instanceof NumericExpression || mapKeyExpr instanceof TemporalExpression || mapKeyExpr instanceof CharacterExpression || mapKeyExpr instanceof EnumExpression) {
useInExpression = true;
}
}
if (useInExpression) {
// Return "key IN (val1, val2, ...)"
SQLExpression[] exprs = (mapKeyExprs != null ? mapKeyExprs.toArray(new SQLExpression[mapKeyExprs.size()]) : null);
return new InExpression(keyExpr, exprs);
}
// TODO If keyExpr is a parameter and mapExpr is derived from a parameter ?
MapKeyLiteral mapKeyLiteral = lit.getKeyLiteral();
BooleanExpression bExpr = null;
List<SQLExpression> elementExprs = mapKeyLiteral.getKeyExpressions();
for (int i = 0; i < elementExprs.size(); i++) {
if (bExpr == null) {
bExpr = (elementExprs.get(i)).eq(keyExpr);
} else {
bExpr = bExpr.ior((elementExprs.get(i)).eq(keyExpr));
}
}
if (bExpr != null) {
bExpr.encloseInParentheses();
}
return bExpr;
}
if (stmt.getQueryGenerator().getCompilationComponent() == CompilationComponent.FILTER) {
boolean useSubquery = getNeedsSubquery(stmt);
JoinType joinType = JoinType.INNER_JOIN;
if (keyExpr instanceof UnboundExpression) {
// See if the user has defined what should be used
String varName = ((UnboundExpression) keyExpr).getVariableName();
String extensionName = "datanucleus.query.jdoql." + varName + ".join";
String extensionValue = (String) stmt.getQueryGenerator().getValueForExtension(extensionName);
if (extensionValue != null) {
if (extensionValue.equalsIgnoreCase("SUBQUERY")) {
useSubquery = true;
} else if (extensionValue.equalsIgnoreCase("INNERJOIN")) {
useSubquery = false;
} else if (extensionValue.equalsIgnoreCase("LEFTOUTERJOIN")) {
joinType = JoinType.LEFT_OUTER_JOIN;
}
}
}
// TODO Check if *this* "containsKey" is negated, not any of them (and remove above check)
if (useSubquery) {
return containsAsSubquery(stmt, mapExpr, keyExpr);
}
return containsAsJoin(stmt, mapExpr, keyExpr, joinType);
}
return containsAsSubquery(stmt, mapExpr, keyExpr);
}
Aggregations