use of org.datanucleus.store.rdbms.RDBMSStoreManager in project datanucleus-rdbms by datanucleus.
the class LocateBulkRequest method execute.
/**
* Method performing the location of the records in the datastore.
* @param ops ObjectProviders to be located
* @throws NucleusObjectNotFoundException with nested exceptions for each of missing objects (if any)
*/
public void execute(ObjectProvider[] ops) {
if (ops == null || ops.length == 0) {
return;
}
if (NucleusLogger.PERSISTENCE.isDebugEnabled()) {
// Debug information about what we are retrieving
StringBuilder str = new StringBuilder();
for (int i = 0; i < ops.length; i++) {
if (i > 0) {
str.append(", ");
}
str.append(ops[i].getInternalObjectId());
}
NucleusLogger.PERSISTENCE.debug(Localiser.msg("052223", str.toString(), table));
}
ExecutionContext ec = ops[0].getExecutionContext();
RDBMSStoreManager storeMgr = table.getStoreManager();
AbstractClassMetaData cmd = ops[0].getClassMetaData();
boolean locked = ec.getSerializeReadForClass(cmd.getFullClassName());
LockMode lockType = ec.getLockManager().getLockMode(ops[0].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 = getStatement(table, ops, locked);
try {
ManagedConnection mconn = storeMgr.getConnectionManager().getConnection(ec);
SQLController sqlControl = storeMgr.getSQLController();
try {
PreparedStatement ps = sqlControl.getStatementForQuery(mconn, statement);
try {
// Provide the primary key field(s)
for (int i = 0; i < ops.length; i++) {
if (cmd.getIdentityType() == IdentityType.DATASTORE) {
StatementMappingIndex datastoreIdx = mappingDefinitions[i].getMappingForMemberPosition(SurrogateColumnType.DATASTORE_ID.getFieldNumber());
for (int j = 0; j < datastoreIdx.getNumberOfParameterOccurrences(); j++) {
table.getSurrogateMapping(SurrogateColumnType.DATASTORE_ID, false).setObject(ec, ps, datastoreIdx.getParameterPositionsForOccurrence(j), ops[i].getInternalObjectId());
}
} else if (cmd.getIdentityType() == IdentityType.APPLICATION) {
ops[i].provideFields(cmd.getPKMemberPositions(), new ParameterSetter(ops[i], ps, mappingDefinitions[i]));
}
}
// Execute the statement
ResultSet rs = sqlControl.executeStatementQuery(ec, mconn, statement, ps);
try {
ObjectProvider[] missingOps = processResults(rs, ops);
if (missingOps != null && missingOps.length > 0) {
NucleusObjectNotFoundException[] nfes = new NucleusObjectNotFoundException[missingOps.length];
for (int i = 0; i < nfes.length; i++) {
nfes[i] = new NucleusObjectNotFoundException("Object not found", missingOps[i].getInternalObjectId());
}
throw new NucleusObjectNotFoundException("Some objects were not found. Look at nested exceptions for details", nfes);
}
} finally {
rs.close();
}
} finally {
sqlControl.closeStatement(mconn, ps);
}
} finally {
mconn.release();
}
} catch (SQLException sqle) {
String msg = Localiser.msg("052220", ops[0].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 MapMapping method postUpdate.
/**
* Method to be called after any update of the owner class element.
* @param ownerOP ObjectProvider of the owner
*/
public void postUpdate(ObjectProvider ownerOP) {
ExecutionContext ec = ownerOP.getExecutionContext();
RDBMSStoreManager storeMgr = table.getStoreManager();
java.util.Map value = (java.util.Map) ownerOP.provideField(getAbsoluteFieldNumber());
if (containerIsStoredInSingleColumn()) {
// Do nothing when serialised since we are handled in the main request
if (value != null) {
if (mmd.getMap().keyIsPersistent() || mmd.getMap().valueIsPersistent()) {
// Make sure all persistable keys/values have ObjectProviders
Set entries = value.entrySet();
Iterator iter = entries.iterator();
while (iter.hasNext()) {
Map.Entry entry = (Map.Entry) iter.next();
if (mmd.getMap().keyIsPersistent() && entry.getKey() != null) {
Object key = entry.getKey();
if (ec.findObjectProvider(key) == null || ec.getApiAdapter().getExecutionContext(key) == null) {
ec.getNucleusContext().getObjectProviderFactory().newForEmbedded(ec, key, false, ownerOP, mmd.getAbsoluteFieldNumber());
}
}
if (mmd.getMap().valueIsPersistent() && entry.getValue() != null) {
Object val = entry.getValue();
if (ec.findObjectProvider(val) == null || ec.getApiAdapter().getExecutionContext(val) == null) {
ec.getNucleusContext().getObjectProviderFactory().newForEmbedded(ec, val, false, ownerOP, mmd.getAbsoluteFieldNumber());
}
}
}
}
}
return;
}
if (value == null) {
// remove any entries in the map and replace it with an empty SCO wrapper
((MapStore) storeMgr.getBackingStoreForField(ec.getClassLoaderResolver(), mmd, null)).clear(ownerOP);
replaceFieldWithWrapper(ownerOP, null);
return;
}
if (value instanceof BackedSCO) {
// Already have a SCO value, so flush outstanding updates
ownerOP.getExecutionContext().flushOperationsForBackingStore(((BackedSCO) value).getBackingStore(), ownerOP);
return;
}
if (mmd.isCascadeUpdate()) {
if (NucleusLogger.PERSISTENCE.isDebugEnabled()) {
NucleusLogger.PERSISTENCE.debug(Localiser.msg("007009", mmd.getFullFieldName()));
}
// Update the datastore with this value of map (clear old entries and add new ones)
// This method could be called in two situations
// 1). Update a map field of an object, so UpdateRequest is called, which calls here
// 2). Persist a new object, and it needed to wait til the element was inserted so
// goes into dirty state and then flush() triggers UpdateRequest, which comes here
MapStore store = ((MapStore) storeMgr.getBackingStoreForField(ec.getClassLoaderResolver(), mmd, value.getClass()));
// TODO Consider making this more efficient picking the ones to remove/add
// e.g use an update() method on the backing store like for CollectionStore
store.clear(ownerOP);
store.putAll(ownerOP, value);
// Replace the field with a wrapper containing these entries
replaceFieldWithWrapper(ownerOP, value);
} else {
// User doesnt want to update by reachability
if (NucleusLogger.PERSISTENCE.isDebugEnabled()) {
NucleusLogger.PERSISTENCE.debug(Localiser.msg("007008", mmd.getFullFieldName()));
}
return;
}
}
use of org.datanucleus.store.rdbms.RDBMSStoreManager in project datanucleus-rdbms by datanucleus.
the class RDBMSSchemaHandler method getRDBMSSchemasInfo.
/**
* Convenience method to read the schemas information for this datastore.
* @param conn Connection to the datastore
* @param schemaName Name of the schema to check for
* @param catalogName Name of the catalog to check for
* @return The RDBMSTypesInfo
*/
protected RDBMSSchemaInfo getRDBMSSchemasInfo(Connection conn, String schemaName, String catalogName) {
try {
if (conn == null) {
// No connection provided so nothing to return
return null;
}
DatabaseMetaData dmd = conn.getMetaData();
ResultSet rs = dmd.getSchemas();
try {
String inputSchema = getNameWithoutQuotes(schemaName);
String inputCatalog = getNameWithoutQuotes(catalogName);
while (rs.next()) {
String schema = rs.getString("TABLE_SCHEM");
String foundSchema = getNameWithoutQuotes(schema);
boolean schemaCorrect = false;
if (StringUtils.isWhitespace(inputSchema) && StringUtils.isWhitespace(foundSchema)) {
schemaCorrect = true;
} else {
if (inputSchema != null && inputSchema.equals(foundSchema)) {
schemaCorrect = true;
} else if (foundSchema != null && StringUtils.isWhitespace(inputSchema) && foundSchema.equals(((RDBMSStoreManager) storeMgr).getSchemaName())) {
schemaCorrect = true;
}
}
boolean catalogCorrect = false;
String catalog = inputCatalog;
try {
catalog = rs.getString("TABLE_CATALOG");
String foundCatalog = getNameWithoutQuotes(catalog);
if (StringUtils.isWhitespace(inputCatalog) && StringUtils.isWhitespace(foundCatalog)) {
catalogCorrect = true;
} else if (inputCatalog != null && inputCatalog.equals(foundCatalog)) {
catalogCorrect = true;
} else if (foundCatalog != null && StringUtils.isWhitespace(inputCatalog) && foundCatalog.equals(((RDBMSStoreManager) storeMgr).getCatalogName())) {
catalogCorrect = true;
}
} catch (SQLException sqle) {
// This datastore doesn't return catalog (e.g Oracle)
if (catalogName == null) {
catalogCorrect = true;
}
}
if (schemaCorrect && catalogCorrect) {
return new RDBMSSchemaInfo(catalog, schema);
}
}
} finally {
rs.close();
}
} catch (SQLException sqle) {
throw new NucleusDataStoreException("Exception thrown retrieving schema information from datastore", sqle);
}
return null;
}
use of org.datanucleus.store.rdbms.RDBMSStoreManager in project datanucleus-rdbms by datanucleus.
the class SQLText method applyParametersToStatement.
/**
* Method to set the parameters in the supplied PreparedStatement using their mappings and
* provided values.
* @param ec execution context
* @param ps The PreparedStatement
*/
public void applyParametersToStatement(ExecutionContext ec, PreparedStatement ps) {
if (parameters != null) {
int num = 1;
Iterator<SQLStatementParameter> i = parameters.iterator();
while (i.hasNext()) {
SQLStatementParameter param = i.next();
JavaTypeMapping mapping = param.getMapping();
if (mapping != null) {
Object value = param.getValue();
if (param.getColumnNumber() >= 0) {
Object colValue = null;
if (value != null) {
// Parameter is for a particular column of the overall object/mapping
// so assume that the object is persistable (or id of persistable)
ClassLoaderResolver clr = ec.getClassLoaderResolver();
AbstractClassMetaData cmd = ec.getMetaDataManager().getMetaDataForClass(mapping.getType(), clr);
RDBMSStoreManager storeMgr = mapping.getStoreManager();
if (cmd.getIdentityType() == IdentityType.DATASTORE) {
colValue = mapping.getValueForDatastoreMapping(ec.getNucleusContext(), param.getColumnNumber(), value);
} else if (cmd.getIdentityType() == IdentityType.APPLICATION) {
colValue = SQLStatementHelper.getValueForPrimaryKeyIndexOfObjectUsingReflection(value, param.getColumnNumber(), cmd, storeMgr, clr);
}
}
mapping.getDatastoreMapping(param.getColumnNumber()).setObject(ps, num, colValue);
num++;
} else {
mapping.setObject(ec, ps, MappingHelper.getMappingIndices(num, mapping), value);
if (mapping.getNumberOfDatastoreMappings() > 0) {
num += mapping.getNumberOfDatastoreMappings();
} else {
num += 1;
}
}
}
}
}
}
use of org.datanucleus.store.rdbms.RDBMSStoreManager 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++;
}
}
}
Aggregations