use of org.datanucleus.store.rdbms.sql.UpdateStatement in project datanucleus-rdbms by datanucleus.
the class JDOQLQuery method compileQueryUpdate.
/**
* Method to compile the query for RDBMS for a bulk update.
* @param parameterValues The parameter values (if any)
* @param candidateCmd Meta-data for the candidate class
*/
protected void compileQueryUpdate(Map parameterValues, AbstractClassMetaData candidateCmd) {
Expression[] updateExprs = compilation.getExprUpdate();
if (updateExprs == null || updateExprs.length == 0) {
// Nothing to update
return;
}
// Generate statement for candidate
RDBMSStoreManager storeMgr = (RDBMSStoreManager) getStoreManager();
DatastoreClass candidateTbl = storeMgr.getDatastoreClass(candidateCmd.getFullClassName(), clr);
if (candidateTbl == null) {
throw new NucleusDataStoreException("Bulk update of " + candidateCmd.getFullClassName() + " not supported since candidate has no table of its own");
}
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(new BulkTable(tbl, false));
}
}
List<SQLStatement> stmts = new ArrayList<>();
List<Boolean> stmtCountFlags = new ArrayList<>();
for (BulkTable bulkTable : tables) {
// Generate statement for candidate
DatastoreClass table = bulkTable.table;
Map<String, Object> extensions = null;
if (!storeMgr.getDatastoreAdapter().supportsOption(DatastoreAdapter.UPDATE_DELETE_STATEMENT_ALLOW_TABLE_ALIAS_IN_WHERE_CLAUSE)) {
extensions = new HashMap<>();
extensions.put(SQLStatement.EXTENSION_SQL_TABLE_NAMING_STRATEGY, "table-name");
}
UpdateStatement stmt = new UpdateStatement(storeMgr, table, null, null, extensions);
stmt.setClassLoaderResolver(clr);
stmt.setCandidateClassName(candidateCmd.getFullClassName());
JavaTypeMapping multitenancyMapping = table.getSurrogateMapping(SurrogateColumnType.MULTITENANCY, false);
if (multitenancyMapping != null) {
// Multi-tenancy restriction
SQLExpression tenantExpr = stmt.getSQLExpressionFactory().newExpression(stmt, stmt.getPrimaryTable(), multitenancyMapping);
SQLExpression tenantVal = stmt.getSQLExpressionFactory().newLiteral(stmt, multitenancyMapping, ec.getNucleusContext().getMultiTenancyId(ec, candidateCmd));
stmt.whereAnd(tenantExpr.eq(tenantVal), true);
}
// TODO Discriminator restriction?
JavaTypeMapping softDeleteMapping = table.getSurrogateMapping(SurrogateColumnType.SOFTDELETE, false);
if (softDeleteMapping != null) {
// Soft-delete restriction
SQLExpression softDeleteExpr = stmt.getSQLExpressionFactory().newExpression(stmt, stmt.getPrimaryTable(), softDeleteMapping);
SQLExpression softDeleteVal = stmt.getSQLExpressionFactory().newLiteral(stmt, softDeleteMapping, Boolean.FALSE);
stmt.whereAnd(softDeleteExpr.eq(softDeleteVal), true);
}
Set<String> options = new HashSet<>();
if (getBooleanExtensionProperty(EXTENSION_USE_IS_NULL_WHEN_EQUALS_NULL_PARAM, true)) {
options.add(QueryToSQLMapper.OPTION_NULL_PARAM_USE_IS_NULL);
}
QueryToSQLMapper sqlMapper = new QueryToSQLMapper(stmt, compilation, parameterValues, null, null, candidateCmd, subclasses, getFetchPlan(), ec, null, options, extensions);
setMapperJoinTypes(sqlMapper);
sqlMapper.compile();
if (stmt.hasUpdates()) {
stmts.add(stmt);
stmtCountFlags.add(bulkTable.useInCount);
datastoreCompilation.setStatementParameters(stmt.getSQLText().getParametersForStatement());
datastoreCompilation.setPrecompilable(sqlMapper.isPrecompilable());
}
}
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.store.rdbms.sql.UpdateStatement in project datanucleus-rdbms by datanucleus.
the class QueryToSQLMapper method compile.
/**
* Method to update the supplied SQLStatement with the components of the specified query.
* During the compilation process this updates the SQLStatement "compileComponent" to the
* component of the query being compiled.
*/
public void compile() {
if (NucleusLogger.QUERY.isDebugEnabled() && parentMapper == null) {
// Give debug output of compilation
StringBuilder str = new StringBuilder("JoinType : navigation(default=");
str.append(defaultJoinType != null ? defaultJoinType : "(using nullability)");
str.append(", filter=");
str.append(defaultJoinTypeFilter != null ? defaultJoinTypeFilter : "(using nullability)");
str.append(")");
if (extensionsByName != null) {
Iterator<Map.Entry<String, Object>> extensionsIter = extensionsByName.entrySet().iterator();
while (extensionsIter.hasNext()) {
Map.Entry<String, Object> entry = extensionsIter.next();
String key = entry.getKey();
if (key.startsWith("datanucleus.query.jdoql.") && key.endsWith(".join")) {
// Alias join definition
String alias = key.substring("datanucleus.query.jdoql.".length(), key.lastIndexOf(".join"));
str.append(", ").append(alias).append("=").append(entry.getValue());
}
}
}
NucleusLogger.QUERY.debug("Compile of " + compilation.getQueryLanguage() + " into SQL - " + str);
}
compileFrom();
compileFilter();
if (stmt instanceof UpdateStatement) {
compileUpdate((UpdateStatement) stmt);
} else if (stmt instanceof SelectStatement) {
SelectStatement selectStmt = (SelectStatement) stmt;
// the datastore doesn't allow select of some field types when used with DISTINCT
if (compilation.getResultDistinct()) {
selectStmt.setDistinct(true);
} else if (!options.contains(OPTION_EXPLICIT_JOINS) && compilation.getExprResult() == null) {
// Joins are made implicitly and no result so set distinct based on whether joining to other table groups
if (selectStmt.getNumberOfTableGroups() > 1) {
// Queries against an extent always consider only distinct candidate instances, regardless of whether distinct is specified (JDO spec)
if (!options.contains(OPTION_NON_DISTINCT_IMPLICIT_JOINS)) {
// If user can guarantee distinct w/ query no reason to take performance hit of distinct clause
selectStmt.setDistinct(true);
}
}
}
compileResult(selectStmt);
compileGrouping(selectStmt);
compileHaving(selectStmt);
compileOrdering(selectStmt);
}
// Check for variables that haven't been bound to the query (declared but not used)
for (String symbol : compilation.getSymbolTable().getSymbolNames()) {
Symbol sym = compilation.getSymbolTable().getSymbol(symbol);
if (sym.getType() == Symbol.VARIABLE) {
if (compilation.getCompilationForSubquery(sym.getQualifiedName()) == null && !hasSQLTableMappingForAlias(sym.getQualifiedName())) {
// Variable not a subquery, nor had its table allocated
throw new QueryCompilerSyntaxException("Query has variable \"" + sym.getQualifiedName() + "\" which is not bound to the query");
}
}
}
}
use of org.datanucleus.store.rdbms.sql.UpdateStatement in project datanucleus-rdbms by datanucleus.
the class JPQLQuery method compileQueryUpdate.
/**
* Method to compile the query for RDBMS for a bulk update.
* @param parameterValues The parameter values (if any)
* @param candidateCmd Meta-data for the candidate class
*/
protected void compileQueryUpdate(Map parameterValues, AbstractClassMetaData candidateCmd) {
Expression[] updateExprs = compilation.getExprUpdate();
if (updateExprs == null || updateExprs.length == 0) {
// Nothing to update
return;
}
// 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 update of " + candidateCmd.getFullClassName() + " not supported since candidate has no table of its own");
}
// Find tables potentially affected by this UPDATE statement
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(new BulkTable(tbl, false));
}
}
List<SQLStatement> stmts = new ArrayList<>();
List<Boolean> stmtCountFlags = new ArrayList<>();
for (BulkTable bulkTable : tables) {
// Generate statement for candidate
DatastoreClass table = bulkTable.table;
Map<String, Object> extensions = null;
if (!storeMgr.getDatastoreAdapter().supportsOption(DatastoreAdapter.UPDATE_DELETE_STATEMENT_ALLOW_TABLE_ALIAS_IN_WHERE_CLAUSE)) {
extensions = new HashMap<>();
extensions.put(SQLStatement.EXTENSION_SQL_TABLE_NAMING_STRATEGY, "table-name");
}
UpdateStatement stmt = new UpdateStatement(storeMgr, table, null, null, extensions);
stmt.setClassLoaderResolver(clr);
stmt.setCandidateClassName(candidateCmd.getFullClassName());
JavaTypeMapping multitenancyMapping = table.getSurrogateMapping(SurrogateColumnType.MULTITENANCY, false);
if (multitenancyMapping != null) {
// Multi-tenancy restriction
SQLExpression tenantExpr = stmt.getSQLExpressionFactory().newExpression(stmt, stmt.getPrimaryTable(), multitenancyMapping);
SQLExpression tenantVal = stmt.getSQLExpressionFactory().newLiteral(stmt, multitenancyMapping, ec.getNucleusContext().getMultiTenancyId(ec, candidateCmd));
stmt.whereAnd(tenantExpr.eq(tenantVal), true);
}
// TODO Discriminator restriction?
JavaTypeMapping softDeleteMapping = table.getSurrogateMapping(SurrogateColumnType.SOFTDELETE, false);
if (softDeleteMapping != null) {
// Soft-delete restriction
SQLExpression softDeleteExpr = stmt.getSQLExpressionFactory().newExpression(stmt, stmt.getPrimaryTable(), softDeleteMapping);
SQLExpression softDeleteVal = stmt.getSQLExpressionFactory().newLiteral(stmt, softDeleteMapping, Boolean.FALSE);
stmt.whereAnd(softDeleteExpr.eq(softDeleteVal), true);
}
Set<String> options = new HashSet<>();
options.add(QueryToSQLMapper.OPTION_CASE_INSENSITIVE);
options.add(QueryToSQLMapper.OPTION_EXPLICIT_JOINS);
if (// Default to false for "IS NULL" with null param
getBooleanExtensionProperty(EXTENSION_USE_IS_NULL_WHEN_EQUALS_NULL_PARAM, false)) {
options.add(QueryToSQLMapper.OPTION_NULL_PARAM_USE_IS_NULL);
}
QueryToSQLMapper sqlMapper = new QueryToSQLMapper(stmt, compilation, parameterValues, null, null, candidateCmd, subclasses, getFetchPlan(), ec, null, options, extensions);
setMapperJoinTypes(sqlMapper);
sqlMapper.compile();
if (stmt.hasUpdates()) {
stmts.add(stmt);
stmtCountFlags.add(bulkTable.useInCount);
datastoreCompilation.setStatementParameters(stmt.getSQLText().getParametersForStatement());
datastoreCompilation.setPrecompilable(sqlMapper.isPrecompilable());
}
}
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);
}
}
Aggregations