use of org.datanucleus.metadata.AbstractMemberMetaData in project datanucleus-rdbms by datanucleus.
the class AbstractRDBMSQueryResult method registerMemberBulkResultSet.
public void registerMemberBulkResultSet(IteratorStatement iterStmt, ResultSet rs) {
if (bulkLoadedValueByMemberNumber == null) {
bulkLoadedValueByMemberNumber = new HashMap<>();
}
try {
ExecutionContext ec = query.getExecutionContext();
AbstractMemberMetaData mmd = iterStmt.getBackingStore().getOwnerMemberMetaData();
if (mmd.hasCollection() || mmd.hasArray()) {
ElementContainerStore backingStore = (ElementContainerStore) iterStmt.getBackingStore();
if (backingStore.isElementsAreEmbedded() || backingStore.isElementsAreSerialised()) {
int[] param = new int[backingStore.getElementMapping().getNumberOfDatastoreMappings()];
for (int i = 0; i < param.length; ++i) {
param[i] = i + 1;
}
if (backingStore.getElementMapping() instanceof SerialisedPCMapping || backingStore.getElementMapping() instanceof SerialisedReferenceMapping || backingStore.getElementMapping() instanceof EmbeddedElementPCMapping) {
// Element = Serialised
while (rs.next()) {
Object owner = iterStmt.getOwnerMapIndex().getMapping().getObject(ec, rs, iterStmt.getOwnerMapIndex().getColumnPositions());
Object element = backingStore.getElementMapping().getObject(ec, rs, param, ec.findObjectProvider(owner), backingStore.getOwnerMemberMetaData().getAbsoluteFieldNumber());
addOwnerMemberValue(mmd, owner, element);
}
} else {
// Element = Non-PC
while (rs.next()) {
Object owner = iterStmt.getOwnerMapIndex().getMapping().getObject(ec, rs, iterStmt.getOwnerMapIndex().getColumnPositions());
Object element = backingStore.getElementMapping().getObject(ec, rs, param);
addOwnerMemberValue(mmd, owner, element);
}
}
} else if (backingStore.getElementMapping() instanceof ReferenceMapping) {
// Element is Reference (interface/Object) so just use elementMapping
int[] param = new int[backingStore.getElementMapping().getNumberOfDatastoreMappings()];
for (int i = 0; i < param.length; ++i) {
param[i] = i + 1;
}
while (rs.next()) {
Object owner = iterStmt.getOwnerMapIndex().getMapping().getObject(ec, rs, iterStmt.getOwnerMapIndex().getColumnPositions());
Object element = backingStore.getElementMapping().getObject(ec, rs, param);
addOwnerMemberValue(mmd, owner, element);
}
} else {
String elementType = mmd.hasCollection() ? backingStore.getOwnerMemberMetaData().getCollection().getElementType() : backingStore.getOwnerMemberMetaData().getArray().getElementType();
ResultObjectFactory<E> scoROF = new PersistentClassROF(ec, rs, query.getIgnoreCache(), iterStmt.getStatementClassMapping(), backingStore.getElementClassMetaData(), ec.getClassLoaderResolver().classForName(elementType));
while (rs.next()) {
Object owner = iterStmt.getOwnerMapIndex().getMapping().getObject(ec, rs, iterStmt.getOwnerMapIndex().getColumnPositions());
Object element = scoROF.getObject();
addOwnerMemberValue(mmd, owner, element);
}
}
} else if (mmd.hasMap()) {
// TODO Cater for maps
}
} catch (SQLException sqle) {
NucleusLogger.DATASTORE.error("Exception thrown processing bulk loaded field " + iterStmt.getBackingStore().getOwnerMemberMetaData().getFullFieldName(), sqle);
} finally {
// Close the ResultSet (and its Statement)
try {
Statement stmt = null;
try {
stmt = rs.getStatement();
// Close the result set
rs.close();
} catch (SQLException e) {
NucleusLogger.DATASTORE.error(Localiser.msg("052605", e));
} finally {
try {
if (stmt != null) {
// Close the original statement
stmt.close();
}
} catch (SQLException e) {
// Do nothing
}
}
} finally {
rs = null;
}
}
}
use of org.datanucleus.metadata.AbstractMemberMetaData 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.metadata.AbstractMemberMetaData in project datanucleus-rdbms by datanucleus.
the class JDOQLQuery method compileQueryFull.
/**
* Method to set the (native) query statement for the compiled query as a whole.
* @param parameters Input parameters (if known)
* @param candidateCmd Metadata for the candidate class
*/
private void compileQueryFull(Map parameters, AbstractClassMetaData candidateCmd) {
if (type != QueryType.SELECT) {
return;
}
long startTime = 0;
if (NucleusLogger.QUERY.isDebugEnabled()) {
startTime = System.currentTimeMillis();
NucleusLogger.QUERY.debug(Localiser.msg("021083", getLanguage(), toString()));
}
if (result != null) {
datastoreCompilation.setResultDefinition(new StatementResultMapping());
} else {
datastoreCompilation.setResultDefinitionForClass(new StatementClassMapping());
}
// Generate statement for candidate(s)
SelectStatement stmt = null;
try {
boolean includeSoftDeletes = getBooleanExtensionProperty("include-soft-deletes", false);
Set<String> options = null;
if (includeSoftDeletes) {
options = new HashSet<>();
options.add(SelectStatementGenerator.OPTION_INCLUDE_SOFT_DELETES);
}
stmt = RDBMSQueryUtils.getStatementForCandidates((RDBMSStoreManager) getStoreManager(), null, candidateCmd, datastoreCompilation.getResultDefinitionForClass(), ec, candidateClass, subclasses, result, null, null, options);
} 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 : " + StringUtils.getMessageFromRootCauseOfThrowable(ne));
statementReturnsEmpty = true;
return;
}
// Update the SQLStatement with filter, ordering, result etc
Set<String> options = new HashSet<>();
options.add(QueryToSQLMapper.OPTION_BULK_UPDATE_VERSION);
if (getBooleanExtensionProperty(EXTENSION_USE_IS_NULL_WHEN_EQUALS_NULL_PARAM, true)) {
options.add(QueryToSQLMapper.OPTION_NULL_PARAM_USE_IS_NULL);
}
if (getBooleanExtensionProperty(EXTENSION_NON_DISTINCT_IMPLICIT_JOIN, false)) {
options.add(QueryToSQLMapper.OPTION_NON_DISTINCT_IMPLICIT_JOINS);
}
QueryToSQLMapper sqlMapper = new QueryToSQLMapper(stmt, compilation, parameters, datastoreCompilation.getResultDefinitionForClass(), datastoreCompilation.getResultDefinition(), candidateCmd, subclasses, getFetchPlan(), ec, getParsedImports(), options, extensions);
setMapperJoinTypes(sqlMapper);
sqlMapper.compile();
datastoreCompilation.setParameterNameByPosition(sqlMapper.getParameterNameByPosition());
datastoreCompilation.setPrecompilable(sqlMapper.isPrecompilable());
if (!getResultDistinct() && stmt.isDistinct()) {
setResultDistinct(true);
compilation.setResultDistinct();
}
if (candidateCollection != null) {
// Restrict to the supplied candidate ids
BooleanExpression candidateExpr = null;
Iterator iter = candidateCollection.iterator();
JavaTypeMapping idMapping = stmt.getPrimaryTable().getTable().getIdMapping();
while (iter.hasNext()) {
Object candidate = iter.next();
SQLExpression idExpr = stmt.getSQLExpressionFactory().newExpression(stmt, stmt.getPrimaryTable(), idMapping);
SQLExpression idVal = stmt.getSQLExpressionFactory().newLiteral(stmt, idMapping, candidate);
if (candidateExpr == null) {
candidateExpr = idExpr.eq(idVal);
} else {
candidateExpr = candidateExpr.ior(idExpr.eq(idVal));
}
}
stmt.whereAnd(candidateExpr, true);
}
// Apply any range
if (range != null) {
long lower = fromInclNo;
long upper = toExclNo;
if (fromInclParam != null) {
if (parameters.containsKey(fromInclParam)) {
lower = ((Number) parameters.get(fromInclParam)).longValue();
} else {
// Must be numbered input so take penultimate
lower = ((Number) parameters.get(Integer.valueOf(parameters.size() - 2))).longValue();
}
}
if (toExclParam != null) {
if (parameters.containsKey(toExclParam)) {
upper = ((Number) parameters.get(toExclParam)).longValue();
} else {
// Must be numbered input so take ultimate
upper = ((Number) parameters.get(Integer.valueOf(parameters.size() - 1))).longValue();
}
}
stmt.setRange(lower, upper - lower);
}
// Set any extensions
boolean useUpdateLock = RDBMSQueryUtils.useUpdateLockForQuery(this);
stmt.addExtension(SQLStatement.EXTENSION_LOCK_FOR_UPDATE, Boolean.valueOf(useUpdateLock));
if (getBooleanExtensionProperty(EXTENSION_FOR_UPDATE_NOWAIT, false)) {
stmt.addExtension(SQLStatement.EXTENSION_LOCK_FOR_UPDATE_NOWAIT, Boolean.TRUE);
}
datastoreCompilation.addStatement(stmt, stmt.getSQLText().toSQL(), false);
datastoreCompilation.setStatementParameters(stmt.getSQLText().getParametersForStatement());
if (result == null && !(resultClass != null && resultClass != candidateClass)) {
// Select of candidates, so check for any immediate multi-valued fields that are marked for fetching
// TODO If the query joins to a 1-1/N-1 and then we have a multi-valued field, we should allow that too
FetchPlanForClass fpc = getFetchPlan().getFetchPlanForClass(candidateCmd);
int[] fpMembers = fpc.getMemberNumbers();
for (int i = 0; i < fpMembers.length; i++) {
AbstractMemberMetaData fpMmd = candidateCmd.getMetaDataForManagedMemberAtAbsolutePosition(fpMembers[i]);
RelationType fpRelType = fpMmd.getRelationType(clr);
if (RelationType.isRelationMultiValued(fpRelType)) {
if (fpMmd.hasCollection() && SCOUtils.collectionHasSerialisedElements(fpMmd)) {
// Ignore collections serialised into the owner (retrieved in main query)
} else if (fpMmd.hasMap() && SCOUtils.mapHasSerialisedKeysAndValues(fpMmd)) {
// Ignore maps serialised into the owner (retrieved in main query)
} else if (fpMmd.hasMap()) {
// Ignore maps for now until we support them
} else {
String multifetchType = getStringExtensionProperty(RDBMSPropertyNames.PROPERTY_RDBMS_QUERY_MULTIVALUED_FETCH, null);
if (multifetchType == null) {
// Default to bulk-fetch EXISTS, so advise the user of why this is happening and how to turn it off
NucleusLogger.QUERY.debug("You have selected field " + fpMmd.getFullFieldName() + " for fetching by this query. We will fetch it using 'EXISTS'." + " To disable this set the query extension/hint '" + RDBMSPropertyNames.PROPERTY_RDBMS_QUERY_MULTIVALUED_FETCH + "' as 'none' or remove the field" + " from the query FetchPlan. If this bulk-fetch generates an invalid or unoptimised query, please report it with a way of reproducing it");
multifetchType = "exists";
}
if (multifetchType.equalsIgnoreCase("exists")) {
// Fetch container contents for all candidate owners
BulkFetchExistsHandler helper = new BulkFetchExistsHandler();
IteratorStatement iterStmt = helper.getStatementToBulkFetchField(candidateCmd, fpMmd, this, parameters, datastoreCompilation, options);
if (iterStmt != null) {
datastoreCompilation.setSCOIteratorStatement(fpMmd.getFullFieldName(), iterStmt);
} else {
NucleusLogger.GENERAL.debug("Note that query has field " + fpMmd.getFullFieldName() + " marked in the FetchPlan, yet this is currently not fetched by this query");
}
} else if (multifetchType.equalsIgnoreCase("join")) {
// Fetch container contents for all candidate owners
BulkFetchJoinHandler helper = new BulkFetchJoinHandler();
IteratorStatement iterStmt = helper.getStatementToBulkFetchField(candidateCmd, fpMmd, this, parameters, datastoreCompilation, options);
if (iterStmt != null) {
datastoreCompilation.setSCOIteratorStatement(fpMmd.getFullFieldName(), iterStmt);
} else {
NucleusLogger.GENERAL.debug("Note that query has field " + fpMmd.getFullFieldName() + " marked in the FetchPlan, yet this is currently not fetched by this query");
}
} else {
NucleusLogger.GENERAL.debug("Note that query has field " + fpMmd.getFullFieldName() + " marked in the FetchPlan, yet this is not fetched by this query.");
}
// TODO Continue this bulk fetch process to multivalued fields of this field
}
} else if (RelationType.isRelationSingleValued(fpRelType)) {
// TODO Check for multivalued fields of this 1-1/N-1 field
}
}
}
if (NucleusLogger.QUERY.isDebugEnabled()) {
NucleusLogger.QUERY.debug(Localiser.msg("021084", getLanguage(), System.currentTimeMillis() - startTime));
}
}
use of org.datanucleus.metadata.AbstractMemberMetaData in project datanucleus-rdbms by datanucleus.
the class JPQLQuery method compileQueryInsert.
/**
* Method to compile the query for RDBMS for a bulk INSERT.
* @param parameterValues The parameter values (if any)
* @param candidateCmd Meta-data for the candidate class
*/
protected void compileQueryInsert(Map parameterValues, AbstractClassMetaData candidateCmd) {
if (StringUtils.isWhitespace(insertFields) || StringUtils.isWhitespace(insertSelectQuery)) {
// Nothing to INSERT
return;
}
List<String> fieldNames = new ArrayList<>();
StringTokenizer fieldTokenizer = new StringTokenizer(insertFields, ",");
while (fieldTokenizer.hasMoreTokens()) {
String token = fieldTokenizer.nextToken().trim();
fieldNames.add(token);
}
// Generate statement for candidate and related classes in this inheritance tree
RDBMSStoreManager storeMgr = (RDBMSStoreManager) getStoreManager();
DatastoreClass candidateTbl = storeMgr.getDatastoreClass(candidateCmd.getFullClassName(), clr);
if (candidateTbl == null) {
// TODO Using subclass-table, so find the table(s) it can be persisted into
throw new NucleusDataStoreException("Bulk INSERT of " + candidateCmd.getFullClassName() + " not supported since candidate has no table of its own");
}
// Find table(s) that need populating with this information
List<BulkTable> tables = new ArrayList<>();
tables.add(new BulkTable(candidateTbl, true));
if (candidateTbl.getSuperDatastoreClass() != null) {
DatastoreClass tbl = candidateTbl;
while (tbl.getSuperDatastoreClass() != null) {
tbl = tbl.getSuperDatastoreClass();
tables.add(0, new BulkTable(tbl, false));
}
}
if (tables.size() > 1) {
throw new NucleusUserException("BULK INSERT only currently allows a single table, but this query implies INSERT into " + tables.size() + " tables!");
}
List<SQLStatement> stmts = new ArrayList<>();
List<Boolean> stmtCountFlags = new ArrayList<>();
for (BulkTable bulkTable : tables) {
// Generate statement for candidate
InsertStatement stmt = new InsertStatement(storeMgr, bulkTable.table, null, null, null);
stmt.setClassLoaderResolver(clr);
stmt.setCandidateClassName(candidateCmd.getFullClassName());
// Set columns for this table
for (String fieldName : fieldNames) {
AbstractMemberMetaData fieldMmd = candidateCmd.getMetaDataForMember(fieldName);
if (fieldMmd == null) {
// No such field
} else {
JavaTypeMapping fieldMapping = bulkTable.table.getMemberMapping(fieldMmd);
if (fieldMapping != null) {
SQLExpression fieldExpr = stmt.getSQLExpressionFactory().newExpression(stmt, stmt.getPrimaryTable(), fieldMapping);
for (int i = 0; i < fieldExpr.getNumberOfSubExpressions(); i++) {
ColumnExpression fieldColExpr = fieldExpr.getSubExpression(i);
fieldColExpr.setOmitTableFromString(true);
}
stmt.addColumn(fieldExpr);
} else {
// Not in this table
}
}
}
// Generate the select query and add it to the InsertStatement
JPQLQuery selectQuery = new JPQLQuery(storeMgr, ec, insertSelectQuery);
selectQuery.compile();
stmt.setSelectStatement((SelectStatement) selectQuery.getDatastoreCompilation().getStatementCompilations().get(0).getStatement());
selectQuery.closeAll();
// TODO if we have multiple tables then this will mean only using some of the columns in the selectSQL
stmts.add(stmt);
stmtCountFlags.add(bulkTable.useInCount);
datastoreCompilation.setStatementParameters(stmt.getSQLText().getParametersForStatement());
}
datastoreCompilation.clearStatements();
Iterator<SQLStatement> stmtIter = stmts.iterator();
Iterator<Boolean> stmtCountFlagsIter = stmtCountFlags.iterator();
while (stmtIter.hasNext()) {
SQLStatement stmt = stmtIter.next();
Boolean useInCount = stmtCountFlagsIter.next();
if (stmts.size() == 1) {
useInCount = true;
}
datastoreCompilation.addStatement(stmt, stmt.getSQLText().toSQL(), useInCount);
}
}
use of org.datanucleus.metadata.AbstractMemberMetaData in project datanucleus-rdbms by datanucleus.
the class JPQLQuery method compileInternal.
/**
* Method to compile the JPQL 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;
}
// Compile the generic query expressions
super.compileInternal(parameterValues);
boolean inMemory = evaluateInMemory();
if (candidateCollection != null) {
// TODO Maybe apply the result class checks ?
return;
}
if (candidateClass == null || candidateClassName == null) {
candidateClass = compilation.getCandidateClass();
candidateClassName = candidateClass.getName();
}
// Create the SQL statement, and its result/parameter definitions
RDBMSStoreManager storeMgr = (RDBMSStoreManager) getStoreManager();
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
return;
}
}
}
// No cached compilation for this query in this datastore so compile it
AbstractClassMetaData acmd = getCandidateClassMetaData();
if (type == QueryType.BULK_INSERT) {
datastoreCompilation = new RDBMSQueryCompilation();
compileQueryInsert(parameterValues, acmd);
} else 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();
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) {
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 && result != null) {
// Do as 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);
// TODO Handle StatementNewObjectMapping
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 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 (!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 {
if (useCaching() && queryCacheKey != null) {
qm.addDatastoreQueryCompilation(datastoreKey, getLanguage(), queryCacheKey, datastoreCompilation);
}
}
}
}
Aggregations