use of org.datanucleus.store.rdbms.RDBMSStoreManager in project datanucleus-rdbms by datanucleus.
the class BulkFetchExistsHandler method getStatementToBulkFetchField.
/**
* Convenience method to generate a bulk-fetch statement for the specified multi-valued field of the owning query.
* @param candidateCmd Metadata for the candidate
* @param parameters Parameters for the query
* @param mmd Metadata for the multi-valued field
* @param datastoreCompilation The datastore compilation of the query
* @param mapperOptions Any options for the query to SQL mapper
* @return The bulk-fetch statement for retrieving this multi-valued field.
*/
public IteratorStatement getStatementToBulkFetchField(AbstractClassMetaData candidateCmd, AbstractMemberMetaData mmd, Query query, Map parameters, RDBMSQueryCompilation datastoreCompilation, Set<String> mapperOptions) {
IteratorStatement iterStmt = null;
ExecutionContext ec = query.getExecutionContext();
ClassLoaderResolver clr = ec.getClassLoaderResolver();
RDBMSStoreManager storeMgr = (RDBMSStoreManager) query.getStoreManager();
Store backingStore = storeMgr.getBackingStoreForField(clr, mmd, null);
if (backingStore instanceof JoinSetStore || backingStore instanceof JoinListStore || backingStore instanceof JoinArrayStore) {
// Set/List/array using join-table : Generate an iterator query of the form
if (backingStore instanceof JoinSetStore) {
iterStmt = ((JoinSetStore) backingStore).getIteratorStatement(ec, ec.getFetchPlan(), false);
} else if (backingStore instanceof JoinListStore) {
iterStmt = ((JoinListStore) backingStore).getIteratorStatement(ec, ec.getFetchPlan(), false, -1, -1);
} else if (backingStore instanceof JoinArrayStore) {
iterStmt = ((JoinArrayStore) backingStore).getIteratorStatement(ec, ec.getFetchPlan(), false);
} else {
throw new NucleusUserException("We do not support BulkFetch using EXISTS for backingStore = " + backingStore);
}
// SELECT ELEM_TBL.COL1, ELEM_TBL.COL2, ... FROM JOIN_TBL INNER_JOIN ELEM_TBL WHERE JOIN_TBL.ELEMENT_ID = ELEM_TBL.ID
// AND EXISTS (SELECT OWNER_TBL.ID FROM OWNER_TBL WHERE (queryWhereClause) AND JOIN_TBL.OWNER_ID = OWNER_TBL.ID)
SelectStatement sqlStmt = iterStmt.getSelectStatement();
JoinTable joinTbl = (JoinTable) sqlStmt.getPrimaryTable().getTable();
JavaTypeMapping joinOwnerMapping = joinTbl.getOwnerMapping();
// Generate the EXISTS subquery (based on the JDOQL/JPQL query)
SelectStatement existsStmt = RDBMSQueryUtils.getStatementForCandidates(storeMgr, sqlStmt, candidateCmd, datastoreCompilation.getResultDefinitionForClass(), ec, query.getCandidateClass(), query.isSubclasses(), query.getResult(), null, null, null);
Set<String> options = new HashSet<>();
if (mapperOptions != null) {
options.addAll(mapperOptions);
}
options.add(QueryToSQLMapper.OPTION_SELECT_CANDIDATE_ID_ONLY);
QueryToSQLMapper sqlMapper = new QueryToSQLMapper(existsStmt, query.getCompilation(), parameters, null, null, candidateCmd, query.isSubclasses(), query.getFetchPlan(), ec, query.getParsedImports(), options, query.getExtensions());
sqlMapper.compile();
// Add EXISTS clause on iterator statement so we can restrict to just the owners in this query
// ORDER BY in EXISTS is forbidden by some RDBMS
existsStmt.setOrdering(null, null);
BooleanExpression existsExpr = new BooleanSubqueryExpression(sqlStmt, "EXISTS", existsStmt);
sqlStmt.whereAnd(existsExpr, true);
// Join to outer statement so we restrict to collection elements for the query candidates
SQLExpression joinTblOwnerExpr = sqlStmt.getRDBMSManager().getSQLExpressionFactory().newExpression(sqlStmt, sqlStmt.getPrimaryTable(), joinOwnerMapping);
SQLExpression existsOwnerExpr = sqlStmt.getRDBMSManager().getSQLExpressionFactory().newExpression(existsStmt, existsStmt.getPrimaryTable(), existsStmt.getPrimaryTable().getTable().getIdMapping());
existsStmt.whereAnd(joinTblOwnerExpr.eq(existsOwnerExpr), true);
// Select the owner candidate so we can separate the collection elements out to their owner
int[] ownerColIndexes = sqlStmt.select(joinTblOwnerExpr, null);
StatementMappingIndex ownerMapIdx = new StatementMappingIndex(existsStmt.getPrimaryTable().getTable().getIdMapping());
ownerMapIdx.setColumnPositions(ownerColIndexes);
iterStmt.setOwnerMapIndex(ownerMapIdx);
} else if (backingStore instanceof FKSetStore || backingStore instanceof FKListStore || backingStore instanceof FKArrayStore) {
if (backingStore instanceof FKSetStore) {
iterStmt = ((FKSetStore) backingStore).getIteratorStatement(ec, ec.getFetchPlan(), false);
} else if (backingStore instanceof FKListStore) {
iterStmt = ((FKListStore) backingStore).getIteratorStatement(ec, ec.getFetchPlan(), false, -1, -1);
} else if (backingStore instanceof FKArrayStore) {
iterStmt = ((FKArrayStore) backingStore).getIteratorStatement(ec, ec.getFetchPlan(), false);
} else {
throw new NucleusUserException("We do not support BulkFetch using EXISTS for backingStore = " + backingStore);
}
// Set/List/array using foreign-key : Generate an iterator query of the form
// SELECT ELEM_TBL.COL1, ELEM_TBL.COL2, ... FROM ELEM_TBL
// WHERE EXISTS (SELECT OWNER_TBL.ID FROM OWNER_TBL WHERE (queryWhereClause) AND ELEM_TBL.OWNER_ID = OWNER_TBL.ID)
SelectStatement sqlStmt = iterStmt.getSelectStatement();
// Generate the EXISTS subquery (based on the JDOQL/JPQL query)
SelectStatement existsStmt = RDBMSQueryUtils.getStatementForCandidates(storeMgr, sqlStmt, candidateCmd, datastoreCompilation.getResultDefinitionForClass(), ec, query.getCandidateClass(), query.isSubclasses(), query.getResult(), null, null, null);
Set<String> options = new HashSet<>();
if (mapperOptions != null) {
options.addAll(mapperOptions);
}
options.add(QueryToSQLMapper.OPTION_SELECT_CANDIDATE_ID_ONLY);
QueryToSQLMapper sqlMapper = new QueryToSQLMapper(existsStmt, query.getCompilation(), parameters, null, null, candidateCmd, query.isSubclasses(), query.getFetchPlan(), ec, query.getParsedImports(), options, query.getExtensions());
sqlMapper.compile();
// Add EXISTS clause on iterator statement so we can restrict to just the owners in this query
// ORDER BY in EXISTS is forbidden by some RDBMS
existsStmt.setOrdering(null, null);
BooleanExpression existsExpr = new BooleanSubqueryExpression(sqlStmt, "EXISTS", existsStmt);
sqlStmt.whereAnd(existsExpr, true);
// Join to outer statement so we restrict to collection elements for the query candidates
SQLExpression elemTblOwnerExpr = sqlStmt.getRDBMSManager().getSQLExpressionFactory().newExpression(sqlStmt, sqlStmt.getPrimaryTable(), ((BaseContainerStore) backingStore).getOwnerMapping());
SQLExpression existsOwnerExpr = sqlStmt.getRDBMSManager().getSQLExpressionFactory().newExpression(existsStmt, existsStmt.getPrimaryTable(), existsStmt.getPrimaryTable().getTable().getIdMapping());
existsStmt.whereAnd(elemTblOwnerExpr.eq(existsOwnerExpr), true);
// Select the owner candidate so we can separate the collection elements out to their owner
int[] ownerColIndexes = sqlStmt.select(elemTblOwnerExpr, null);
StatementMappingIndex ownerMapIdx = new StatementMappingIndex(existsStmt.getPrimaryTable().getTable().getIdMapping());
ownerMapIdx.setColumnPositions(ownerColIndexes);
iterStmt.setOwnerMapIndex(ownerMapIdx);
}
return iterStmt;
}
use of org.datanucleus.store.rdbms.RDBMSStoreManager in project datanucleus-rdbms by datanucleus.
the class BulkFetchJoinHandler method getStatementToBulkFetchField.
/**
* Convenience method to generate a bulk-fetch statement for the specified multi-valued field of the owning query.
* @param candidateCmd Metadata for the candidate
* @param mmd Metadata for the member we are bulk-fetching the value(s) for
* @param query The query
* @param parameters Parameters for the query
* @param datastoreCompilation The datastore compilation of the query
* @param mapperOptions Any mapper options for query generation
* @return The statement to use for bulk fetching, together with mappings for extracting the results of the elements
*/
public IteratorStatement getStatementToBulkFetchField(AbstractClassMetaData candidateCmd, AbstractMemberMetaData mmd, Query query, Map parameters, RDBMSQueryCompilation datastoreCompilation, Set<String> mapperOptions) {
ExecutionContext ec = query.getExecutionContext();
ClassLoaderResolver clr = ec.getClassLoaderResolver();
RDBMSStoreManager storeMgr = (RDBMSStoreManager) query.getStoreManager();
Store backingStore = storeMgr.getBackingStoreForField(clr, mmd, null);
if (backingStore instanceof JoinSetStore || backingStore instanceof JoinListStore || backingStore instanceof JoinArrayStore) {
// Set/List/array using join-table : Generate an iterator query of the form
// SELECT ELEM_TBL.COL1, ELEM_TBL.COL2, ... FROM CANDIDATE_TBL T1 INNER JOIN JOIN_TBL T2 ON T2.OWNER_ID = T1.ID INNER_JOIN ELEM_TBL T3 ON T3.ID = T2.ELEM_ID
// WHERE (queryWhereClause)
// TODO Start from the original query, and remove any grouping, having, ordering etc, and join to join table + element table.
} else if (backingStore instanceof FKSetStore || backingStore instanceof FKListStore || backingStore instanceof FKArrayStore) {
// Set/List/array using foreign-key : Generate an iterator query of the form
// SELECT ELEM_TBL.COL1, ELEM_TBL.COL2, ... FROM ELEM_TBL
// WHERE EXISTS (SELECT OWNER_TBL.ID FROM OWNER_TBL WHERE (queryWhereClause) AND ELEM_TBL.OWNER_ID = OWNER_TBL.ID)
// TODO Start from the original query, and remove any grouping, having, ordering etc, and join to element table.
}
throw new NucleusException("BulkFetch via JOIN is not yet implemented");
// return iterStmt;
}
use of org.datanucleus.store.rdbms.RDBMSStoreManager in project datanucleus-rdbms by datanucleus.
the class JDOQLQuery method compileInternal.
/**
* Method to compile the JDOQL query.
* Uses the superclass to compile the generic query populating the "compilation", and then generates
* the datastore-specific "datastoreCompilation".
* @param parameterValues Map of param values keyed by param name (if available at compile time)
*/
protected synchronized void compileInternal(Map parameterValues) {
if (isCompiled()) {
return;
}
if (getExtension("include-soft-deletes") != null) {
// If using an extension that can change the datastore query then evict any existing compilation
QueryManager qm = getQueryManager();
qm.removeQueryCompilation(Query.LANGUAGE_JDOQL, getQueryCacheKey());
}
// Compile the generic query expressions
super.compileInternal(parameterValues);
boolean inMemory = evaluateInMemory();
if (candidateCollection != null && inMemory) {
// TODO Maybe apply the result class checks ?
return;
}
// Create the SQL statement, and its result/parameter definitions
RDBMSStoreManager storeMgr = (RDBMSStoreManager) getStoreManager();
if (candidateClass == null) {
throw new NucleusUserException(Localiser.msg("021009", candidateClassName));
}
// Make sure any persistence info is loaded
ec.hasPersistenceInformationForClass(candidateClass);
if (parameterValues != null) {
// Check for null values on primitive parameters
Set paramNames = parameterValues.entrySet();
Iterator<Map.Entry> iter = paramNames.iterator();
while (iter.hasNext()) {
Map.Entry entry = iter.next();
Object paramName = entry.getKey();
if (paramName instanceof String) {
Symbol sym = compilation.getSymbolTable().getSymbol((String) paramName);
Object value = entry.getValue();
if (value == null) {
// so omit the check for that case
if (sym != null && sym.getValueType() != null && sym.getValueType().isPrimitive()) {
throw new NucleusUserException(Localiser.msg("021117", paramName, sym.getValueType().getName()));
}
}
}
}
}
QueryManager qm = getQueryManager();
String datastoreKey = storeMgr.getQueryCacheKey();
String queryCacheKey = getQueryCacheKey();
if (useCaching() && queryCacheKey != null) {
// Check if we have any parameters set to null, since this can invalidate a datastore compilation
// e.g " field == :val" can be "COL IS NULL" or "COL = <val>"
boolean nullParameter = false;
if (parameterValues != null) {
Iterator iter = parameterValues.values().iterator();
while (iter.hasNext()) {
Object val = iter.next();
if (val == null) {
nullParameter = true;
break;
}
}
}
if (!nullParameter) {
// Allowing caching so try to find compiled (datastore) query
datastoreCompilation = (RDBMSQueryCompilation) qm.getDatastoreQueryCompilation(datastoreKey, getLanguage(), queryCacheKey);
if (datastoreCompilation != null) {
// Cached compilation exists for this datastore so reuse it
setResultDistinct(compilation.getResultDistinct());
return;
}
}
}
// Compile the query for the datastore since not cached
AbstractClassMetaData acmd = getCandidateClassMetaData();
if (type == QueryType.BULK_UPDATE) {
datastoreCompilation = new RDBMSQueryCompilation();
compileQueryUpdate(parameterValues, acmd);
} else if (type == QueryType.BULK_DELETE) {
datastoreCompilation = new RDBMSQueryCompilation();
compileQueryDelete(parameterValues, acmd);
} else {
datastoreCompilation = new RDBMSQueryCompilation();
synchronized (datastoreCompilation) {
if (inMemory) {
// Generate statement to just retrieve all candidate objects for later processing
compileQueryToRetrieveCandidates(parameterValues, acmd);
} else {
// Generate statement to perform the full query in the datastore
compileQueryFull(parameterValues, acmd);
if (result != null) {
// Check existence of invalid selections in the result
StatementResultMapping resultMapping = datastoreCompilation.getResultDefinition();
for (int i = 0; i < resultMapping.getNumberOfResultExpressions(); i++) {
Object stmtMap = resultMapping.getMappingForResultExpression(i);
if (stmtMap instanceof StatementMappingIndex) {
StatementMappingIndex idx = (StatementMappingIndex) stmtMap;
AbstractMemberMetaData mmd = idx.getMapping().getMemberMetaData();
if (mmd != null) {
if (idx.getMapping() instanceof AbstractContainerMapping && idx.getMapping().getNumberOfDatastoreMappings() != 1) {
throw new NucleusUserException(Localiser.msg("021213"));
}
}
}
}
if (resultClass != null) {
if (// Don't apply checks when user has specified the default (no result class)
!resultClass.getName().equals(Object[].class.getName())) {
// Check validity of resultClass for the result (PrivilegedAction since uses reflection)
AccessController.doPrivileged(new PrivilegedAction() {
public Object run() {
// Check that this class has the necessary constructor/setters/fields to be used
StatementResultMapping resultMapping = datastoreCompilation.getResultDefinition();
if (QueryUtils.resultClassIsSimple(resultClass.getName())) {
if (resultMapping.getNumberOfResultExpressions() > 1) {
// Invalid number of result expressions
throw new NucleusUserException(Localiser.msg("021201", resultClass.getName()));
}
Object stmtMap = resultMapping.getMappingForResultExpression(0);
if (stmtMap instanceof StatementMappingIndex) {
StatementMappingIndex idx = (StatementMappingIndex) stmtMap;
Class exprType = idx.getMapping().getJavaType();
boolean typeConsistent = false;
if (exprType == resultClass) {
typeConsistent = true;
} else if (exprType.isPrimitive()) {
Class resultClassPrimitive = ClassUtils.getPrimitiveTypeForType(resultClass);
if (resultClassPrimitive == exprType) {
typeConsistent = true;
}
}
if (!typeConsistent) {
// Inconsistent expression type not matching the result class type
throw new NucleusUserException(Localiser.msg("021202", resultClass.getName(), exprType));
}
} else {
// TODO Handle StatementNewObjectMapping
throw new NucleusUserException("Don't support result clause of " + result + " with resultClass of " + resultClass.getName());
}
} else if (QueryUtils.resultClassIsUserType(resultClass.getName())) {
// Check for valid constructor (either using param types, or using default ctr)
Class[] ctrTypes = new Class[resultMapping.getNumberOfResultExpressions()];
for (int i = 0; i < ctrTypes.length; i++) {
Object stmtMap = resultMapping.getMappingForResultExpression(i);
if (stmtMap instanceof StatementMappingIndex) {
ctrTypes[i] = ((StatementMappingIndex) stmtMap).getMapping().getJavaType();
} else if (stmtMap instanceof StatementNewObjectMapping) {
// TODO Handle this
}
}
Constructor ctr = ClassUtils.getConstructorWithArguments(resultClass, ctrTypes);
if (ctr == null && !ClassUtils.hasDefaultConstructor(resultClass)) {
// No valid constructor found!
throw new NucleusUserException(Localiser.msg("021205", resultClass.getName()));
} else if (ctr == null) {
// We are using default constructor, so check the types of the result expressions for means of input
for (int i = 0; i < resultMapping.getNumberOfResultExpressions(); i++) {
Object stmtMap = resultMapping.getMappingForResultExpression(i);
if (stmtMap instanceof StatementMappingIndex) {
StatementMappingIndex mapIdx = (StatementMappingIndex) stmtMap;
AbstractMemberMetaData mmd = mapIdx.getMapping().getMemberMetaData();
String fieldName = mapIdx.getColumnAlias();
Class fieldType = mapIdx.getMapping().getJavaType();
if (fieldName == null && mmd != null) {
fieldName = mmd.getName();
}
if (fieldName != null) {
// Check for the field of that name in the result class
Class resultFieldType = null;
boolean publicField = true;
try {
Field fld = resultClass.getDeclaredField(fieldName);
resultFieldType = fld.getType();
// Check the type of the field
if (!ClassUtils.typesAreCompatible(fieldType, resultFieldType) && !ClassUtils.typesAreCompatible(resultFieldType, fieldType)) {
throw new NucleusUserException(Localiser.msg("021211", fieldName, fieldType.getName(), resultFieldType.getName()));
}
if (!Modifier.isPublic(fld.getModifiers())) {
publicField = false;
}
} catch (NoSuchFieldException nsfe) {
publicField = false;
}
// Check for a public set method
if (!publicField) {
Method setMethod = QueryUtils.getPublicSetMethodForFieldOfResultClass(resultClass, fieldName, resultFieldType);
if (setMethod == null) {
// No setter, so check for a public put(Object, Object) method
Method putMethod = QueryUtils.getPublicPutMethodForResultClass(resultClass);
if (putMethod == null) {
throw new NucleusUserException(Localiser.msg("021212", resultClass.getName(), fieldName));
}
}
}
}
} else if (stmtMap instanceof StatementNewObjectMapping) {
// TODO Handle this
}
}
}
}
return null;
}
});
}
}
}
}
boolean hasParams = false;
if (explicitParameters != null) {
hasParams = true;
} else if (parameterValues != null && parameterValues.size() > 0) {
hasParams = true;
}
if (!statementReturnsEmpty && queryCacheKey != null && useCaching()) {
// TODO Allow caching of queries with subqueries
if (!datastoreCompilation.isPrecompilable() || (datastoreCompilation.getSQL().indexOf('?') < 0 && hasParams)) {
// Some parameters had their clauses evaluated during compilation so the query didn't gain any parameters, so don't cache it
NucleusLogger.QUERY.debug(Localiser.msg("021075"));
} else {
qm.addDatastoreQueryCompilation(datastoreKey, getLanguage(), queryCacheKey, datastoreCompilation);
}
}
}
}
}
use of org.datanucleus.store.rdbms.RDBMSStoreManager in project datanucleus-rdbms by datanucleus.
the class JDOQLQuery method compileQueryToRetrieveCandidates.
/**
* Method to set the statement (and parameter/results definitions) to retrieve all candidates.
* This is used when we want to evaluate in-memory and so just retrieve all possible candidates
* first.
* @param parameters Input parameters (if known)
* @param candidateCmd Metadata for the candidate class
*/
private void compileQueryToRetrieveCandidates(Map parameters, AbstractClassMetaData candidateCmd) {
if (type != QueryType.SELECT) {
return;
}
StatementClassMapping resultsDef = new StatementClassMapping();
datastoreCompilation.setResultDefinitionForClass(resultsDef);
// Generate statement for candidate(s)
SelectStatement stmt = null;
try {
stmt = RDBMSQueryUtils.getStatementForCandidates((RDBMSStoreManager) getStoreManager(), null, candidateCmd, datastoreCompilation.getResultDefinitionForClass(), ec, candidateClass, subclasses, result, null, null, null);
} catch (NucleusException ne) {
// Statement would result in no results, so just catch it and avoid generating the statement
NucleusLogger.QUERY.warn("Query for candidates of " + candidateClass.getName() + (subclasses ? " and subclasses" : "") + " resulted in no possible candidates", ne);
statementReturnsEmpty = true;
return;
}
if (stmt.allUnionsForSamePrimaryTable()) {
// Select fetch-plan fields of candidate class
SQLStatementHelper.selectFetchPlanOfCandidateInStatement(stmt, datastoreCompilation.getResultDefinitionForClass(), candidateCmd, getFetchPlan(), 1);
} else {
// Select id only since tables don't have same mappings or column names
// TODO complete-table will come through here but maybe ought to be treated differently
SQLStatementHelper.selectIdentityOfCandidateInStatement(stmt, datastoreCompilation.getResultDefinitionForClass(), candidateCmd);
}
datastoreCompilation.addStatement(stmt, stmt.getSQLText().toSQL(), false);
datastoreCompilation.setStatementParameters(stmt.getSQLText().getParametersForStatement());
}
use of org.datanucleus.store.rdbms.RDBMSStoreManager in project datanucleus-rdbms by datanucleus.
the class JDOQLQuery method performExecute.
protected Object performExecute(Map parameters) {
if (statementReturnsEmpty) {
return Collections.EMPTY_LIST;
}
boolean inMemory = evaluateInMemory();
if (candidateCollection != null) {
// Supplied collection of instances, so evaluate in-memory
if (candidateCollection.isEmpty()) {
return Collections.EMPTY_LIST;
} else if (inMemory) {
return new JDOQLInMemoryEvaluator(this, new ArrayList(candidateCollection), compilation, parameters, clr).execute(true, true, true, true, true);
}
} else if (type == QueryType.SELECT) {
// Query results are cached, so return those
List<Object> cachedResults = getQueryManager().getQueryResult(this, parameters);
if (cachedResults != null) {
return new CandidateIdsQueryResult(this, cachedResults);
}
}
Object results = null;
RDBMSStoreManager storeMgr = (RDBMSStoreManager) getStoreManager();
ManagedConnection mconn = storeMgr.getConnectionManager().getConnection(ec);
try {
// Execute the query
long startTime = System.currentTimeMillis();
if (NucleusLogger.QUERY.isDebugEnabled()) {
NucleusLogger.QUERY.debug(Localiser.msg("021046", getLanguage(), getSingleStringQuery(), null));
}
AbstractClassMetaData acmd = ec.getMetaDataManager().getMetaDataForClass(candidateClass, clr);
SQLController sqlControl = storeMgr.getSQLController();
PreparedStatement ps = null;
try {
if (type == QueryType.SELECT) {
// Create PreparedStatement and apply parameters, result settings etc
ps = RDBMSQueryUtils.getPreparedStatementForQuery(mconn, datastoreCompilation.getSQL(), this);
SQLStatementHelper.applyParametersToStatement(ps, ec, datastoreCompilation.getStatementParameters(), datastoreCompilation.getParameterNameByPosition(), parameters);
RDBMSQueryUtils.prepareStatementForExecution(ps, this, true);
registerTask(ps);
ResultSet rs = null;
try {
rs = sqlControl.executeStatementQuery(ec, mconn, toString(), ps);
} finally {
deregisterTask();
}
AbstractRDBMSQueryResult qr = null;
try {
if (inMemory) {
// IN-MEMORY EVALUATION
ResultObjectFactory rof = new PersistentClassROF(ec, rs, ignoreCache, datastoreCompilation.getResultDefinitionForClass(), acmd, candidateClass);
// Just instantiate the candidates for later in-memory processing
// TODO Use a queryResult rather than an ArrayList so we load when required
List candidates = new ArrayList();
while (rs.next()) {
candidates.add(rof.getObject());
}
// Perform in-memory filter/result/order etc
results = new JDOQLInMemoryEvaluator(this, candidates, compilation, parameters, clr).execute(true, true, true, true, true);
} else {
// IN-DATASTORE EVALUATION
ResultObjectFactory rof = null;
if (result != null) {
// Each result row is of a result type
rof = new ResultClassROF(ec, rs, ignoreCache, resultClass, datastoreCompilation.getResultDefinition());
} else if (resultClass != null && resultClass != candidateClass) {
rof = new ResultClassROF(ec, rs, ignoreCache, resultClass, datastoreCompilation.getResultDefinitionForClass());
} else {
// Each result row is a candidate object
rof = new PersistentClassROF(ec, rs, ignoreCache, datastoreCompilation.getResultDefinitionForClass(), acmd, candidateClass);
}
// Create the required type of QueryResult
qr = RDBMSQueryUtils.getQueryResultForQuery(this, rof, rs, getResultDistinct() ? null : candidateCollection);
// Register any bulk loaded member resultSets that need loading
Map<String, IteratorStatement> scoIterStmts = datastoreCompilation.getSCOIteratorStatements();
if (scoIterStmts != null) {
Iterator<Map.Entry<String, IteratorStatement>> scoStmtIter = scoIterStmts.entrySet().iterator();
while (scoStmtIter.hasNext()) {
Map.Entry<String, IteratorStatement> stmtIterEntry = scoStmtIter.next();
IteratorStatement iterStmt = stmtIterEntry.getValue();
String iterStmtSQL = iterStmt.getSelectStatement().getSQLText().toSQL();
NucleusLogger.DATASTORE_RETRIEVE.debug("JDOQL Bulk-Fetch of " + iterStmt.getBackingStore().getOwnerMemberMetaData().getFullFieldName());
try {
PreparedStatement psSco = sqlControl.getStatementForQuery(mconn, iterStmtSQL);
if (datastoreCompilation.getStatementParameters() != null) {
BulkFetchHandler.applyParametersToStatement(ec, psSco, datastoreCompilation, iterStmt.getSelectStatement(), parameters);
}
ResultSet rsSCO = sqlControl.executeStatementQuery(ec, mconn, iterStmtSQL, psSco);
qr.registerMemberBulkResultSet(iterStmt, rsSCO);
} catch (SQLException e) {
throw new NucleusDataStoreException(Localiser.msg("056006", iterStmtSQL), e);
}
}
}
// Initialise the QueryResult for use
qr.initialise();
// Add hooks for closing query resources
final QueryResult qr1 = qr;
final ManagedConnection mconn1 = mconn;
ManagedConnectionResourceListener listener = new ManagedConnectionResourceListener() {
public void transactionFlushed() {
}
public void transactionPreClose() {
// Tx : disconnect query from ManagedConnection (read in unread rows etc)
qr1.disconnect();
}
public void managedConnectionPreClose() {
if (!ec.getTransaction().isActive()) {
// Non-Tx : disconnect query from ManagedConnection (read in unread rows etc)
qr1.disconnect();
}
}
public void managedConnectionPostClose() {
}
public void resourcePostClose() {
mconn1.removeListener(this);
}
};
mconn.addListener(listener);
qr.addConnectionListener(listener);
results = qr;
}
} finally {
if (qr == null) {
rs.close();
}
}
} else if (type == QueryType.BULK_UPDATE || type == QueryType.BULK_DELETE) {
long bulkResult = 0;
List<StatementCompilation> stmtCompilations = datastoreCompilation.getStatementCompilations();
Iterator<StatementCompilation> stmtCompileIter = stmtCompilations.iterator();
while (stmtCompileIter.hasNext()) {
StatementCompilation stmtCompile = stmtCompileIter.next();
ps = sqlControl.getStatementForUpdate(mconn, stmtCompile.getSQL(), false);
SQLStatementHelper.applyParametersToStatement(ps, ec, datastoreCompilation.getStatementParameters(), datastoreCompilation.getParameterNameByPosition(), parameters);
RDBMSQueryUtils.prepareStatementForExecution(ps, this, false);
int[] execResults = sqlControl.executeStatementUpdate(ec, mconn, toString(), ps, true);
if (stmtCompile.useInCount()) {
bulkResult += execResults[0];
}
}
try {
// Evict all objects of this type from the cache
ec.getNucleusContext().getLevel2Cache().evictAll(candidateClass, subclasses);
} catch (UnsupportedOperationException uoe) {
// Do nothing
}
results = bulkResult;
}
} catch (SQLException sqle) {
if (storeMgr.getDatastoreAdapter().isStatementCancel(sqle)) {
throw new QueryInterruptedException("Query has been interrupted", sqle);
} else if (storeMgr.getDatastoreAdapter().isStatementTimeout(sqle)) {
throw new QueryTimeoutException("Query has been timed out", sqle);
}
throw new NucleusException(Localiser.msg("021042", datastoreCompilation.getSQL()), sqle);
}
if (NucleusLogger.QUERY.isDebugEnabled()) {
NucleusLogger.QUERY.debug(Localiser.msg("021074", getLanguage(), "" + (System.currentTimeMillis() - startTime)));
}
return results;
} finally {
mconn.release();
}
}
Aggregations