use of org.datanucleus.store.rdbms.table.ClassTable in project datanucleus-rdbms by datanucleus.
the class QueryToSQLMapper method compileUpdate.
/**
* Method to compile the result clause of the query into the SQLStatement.
* @param stmt UPDATE statement
*/
protected void compileUpdate(UpdateStatement stmt) {
if (compilation.getExprUpdate() != null) {
// Update statement, so generate update expression(s)
compileComponent = CompilationComponent.UPDATE;
Expression[] updateExprs = compilation.getExprUpdate();
SQLExpression[] updateSqlExprs = new SQLExpression[updateExprs.length];
// TODO If the field being set is in a different table omit it
boolean performingUpdate = false;
for (int i = 0; i < updateExprs.length; i++) {
// "field = value"
DyadicExpression updateExpr = (DyadicExpression) updateExprs[i];
// Left-side has to be PrimaryExpression
SQLExpression leftSqlExpr = null;
if (updateExpr.getLeft() instanceof PrimaryExpression) {
processPrimaryExpression((PrimaryExpression) updateExpr.getLeft());
leftSqlExpr = stack.pop();
if (leftSqlExpr.getSQLTable() != stmt.getPrimaryTable()) {
// Set left to null to signify that it is not applicable to the table of this UPDATE statement
leftSqlExpr = null;
}
} else {
throw new NucleusException("Dont currently support update clause containing left expression of type " + updateExpr.getLeft());
}
if (leftSqlExpr != null) {
if (!stmt.getDatastoreAdapter().supportsOption(DatastoreAdapter.UPDATE_STATEMENT_ALLOW_TABLE_ALIAS_IN_SET_CLAUSE)) {
// This datastore doesn't allow table alias in UPDATE SET clause, so just use column name
for (int j = 0; j < leftSqlExpr.getNumberOfSubExpressions(); j++) {
ColumnExpression colExpr = leftSqlExpr.getSubExpression(j);
colExpr.setOmitTableFromString(true);
}
}
performingUpdate = true;
SQLExpression rightSqlExpr = null;
if (updateExpr.getRight() instanceof Literal) {
processLiteral((Literal) updateExpr.getRight());
rightSqlExpr = stack.pop();
} else if (updateExpr.getRight() instanceof ParameterExpression) {
ParameterExpression paramExpr = (ParameterExpression) updateExpr.getRight();
paramMappingForName.put(paramExpr.getId(), leftSqlExpr.getJavaTypeMapping());
processParameterExpression(paramExpr);
rightSqlExpr = stack.pop();
} else if (updateExpr.getRight() instanceof PrimaryExpression) {
processPrimaryExpression((PrimaryExpression) updateExpr.getRight());
rightSqlExpr = stack.pop();
} else if (updateExpr.getRight() instanceof DyadicExpression) {
updateExpr.getRight().evaluate(this);
rightSqlExpr = stack.pop();
} else if (updateExpr.getRight() instanceof CaseExpression) {
CaseExpression caseExpr = (CaseExpression) updateExpr.getRight();
processCaseExpression(caseExpr, leftSqlExpr);
rightSqlExpr = stack.pop();
} else if (updateExpr.getRight() instanceof VariableExpression) {
// Subquery?
processVariableExpression((VariableExpression) updateExpr.getRight());
rightSqlExpr = stack.pop();
if (rightSqlExpr instanceof UnboundExpression) {
// TODO Support whatever this is
throw new NucleusException("Found UnboundExpression in UPDATE clause!");
}
} else {
throw new NucleusException("Dont currently support update clause containing right expression of type " + updateExpr.getRight());
}
if (rightSqlExpr != null) {
updateSqlExprs[i] = leftSqlExpr.eq(rightSqlExpr);
}
}
}
if (candidateCmd.isVersioned() && options.contains(OPTION_BULK_UPDATE_VERSION)) {
SQLExpression updateSqlExpr = null;
ClassTable table = (ClassTable) stmt.getPrimaryTable().getTable();
JavaTypeMapping verMapping = table.getSurrogateMapping(SurrogateColumnType.VERSION, true);
ClassTable verTable = table.getTableManagingMapping(verMapping);
if (verTable == stmt.getPrimaryTable().getTable()) {
VersionMetaData vermd = candidateCmd.getVersionMetaDataForClass();
if (vermd.getVersionStrategy() == VersionStrategy.VERSION_NUMBER) {
// Increment the version
SQLTable verSqlTbl = stmt.getTable(verTable, stmt.getPrimaryTable().getGroupName());
SQLExpression verExpr = new NumericExpression(stmt, verSqlTbl, verMapping);
SQLExpression incrExpr = verExpr.add(new IntegerLiteral(stmt, exprFactory.getMappingForType(Integer.class, false), Integer.valueOf(1), null));
updateSqlExpr = verExpr.eq(incrExpr);
SQLExpression[] oldArray = updateSqlExprs;
updateSqlExprs = new SQLExpression[oldArray.length + 1];
System.arraycopy(oldArray, 0, updateSqlExprs, 0, oldArray.length);
updateSqlExprs[oldArray.length] = updateSqlExpr;
performingUpdate = true;
} else if (vermd.getVersionStrategy() == VersionStrategy.DATE_TIME) {
// Set version to the time of update
SQLTable verSqlTbl = stmt.getTable(verTable, stmt.getPrimaryTable().getGroupName());
SQLExpression verExpr = new NumericExpression(stmt, verSqlTbl, verMapping);
Object newVersion = ec.getLockManager().getNextVersion(vermd, null);
JavaTypeMapping valMapping = exprFactory.getMappingForType(newVersion.getClass(), false);
SQLExpression valExpr = new TemporalLiteral(stmt, valMapping, newVersion, null);
updateSqlExpr = verExpr.eq(valExpr);
SQLExpression[] oldArray = updateSqlExprs;
updateSqlExprs = new SQLExpression[oldArray.length + 1];
System.arraycopy(oldArray, 0, updateSqlExprs, 0, oldArray.length);
updateSqlExprs[oldArray.length] = updateSqlExpr;
performingUpdate = true;
}
}
}
if (performingUpdate) {
// Only set the updates component of the SQLStatement if anything to update in this table
stmt.setUpdates(updateSqlExprs);
}
}
compileComponent = null;
}
use of org.datanucleus.store.rdbms.table.ClassTable in project datanucleus-rdbms by datanucleus.
the class IndexFunction 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 ignore, List args) {
if (ignore == null) {
if (args == null || args.size() != 2) {
throw new NucleusException("INDEX can only be used with 2 arguments - the element expression, and the collection expression");
}
SQLExpression elemSqlExpr = (SQLExpression) args.get(0);
SQLExpression collSqlExpr = (SQLExpression) args.get(1);
AbstractMemberMetaData mmd = collSqlExpr.getJavaTypeMapping().getMemberMetaData();
if (!mmd.hasCollection()) {
throw new NucleusException("INDEX expression for field " + mmd.getFullFieldName() + " does not represent a collection!");
} else if (!mmd.getOrderMetaData().isIndexedList()) {
throw new NucleusException("INDEX expression for field " + mmd.getFullFieldName() + " does not represent an indexed list!");
}
JavaTypeMapping orderMapping = null;
SQLTable orderTable = null;
Table joinTbl = stmt.getRDBMSManager().getTable(mmd);
if (joinTbl != null) {
// 1-N via join table
CollectionTable collTable = (CollectionTable) joinTbl;
orderTable = stmt.getTableForDatastoreContainer(collTable);
// TODO If the join table is not yet referenced, or referenced multiple times then fix this
orderMapping = collTable.getOrderMapping();
} else {
// 1-N via FK
orderTable = elemSqlExpr.getSQLTable();
orderMapping = ((ClassTable) elemSqlExpr.getSQLTable().getTable()).getExternalMapping(mmd, MappingType.EXTERNAL_INDEX);
}
return new NumericExpression(stmt, orderTable, orderMapping);
}
throw new NucleusException(Localiser.msg("060002", "INDEX", ignore));
}
use of org.datanucleus.store.rdbms.table.ClassTable in project datanucleus-rdbms by datanucleus.
the class RDBMSStoreManager method resolveIdentifierMacro.
/**
* Resolves an identifier macro. The public fields <var>className</var>, <var>fieldName </var>,
* and <var>subfieldName </var> of the given macro are taken as inputs, and the public
* <var>value </var> field is set to the SQL identifier of the corresponding database table or column.
* @param im The macro to resolve.
* @param clr The ClassLoaderResolver
*/
public void resolveIdentifierMacro(MacroString.IdentifierMacro im, ClassLoaderResolver clr) {
DatastoreClass ct = getDatastoreClass(im.className, clr);
if (im.fieldName == null) {
im.value = ct.getIdentifier().toString();
return;
}
JavaTypeMapping m;
if (// TODO This should be candidate alias or something, not hardcoded "this"
im.fieldName.equals("this")) {
if (!(ct instanceof ClassTable)) {
throw new NucleusUserException(Localiser.msg("050034", im.className));
}
if (im.subfieldName != null) {
throw new NucleusUserException(Localiser.msg("050035", im.className, im.fieldName, im.subfieldName));
}
m = ((Table) ct).getIdMapping();
} else {
AbstractClassMetaData cmd = getMetaDataManager().getMetaDataForClass(im.className, clr);
AbstractMemberMetaData mmd = cmd.getMetaDataForMember(im.fieldName);
m = ct.getMemberMapping(mmd);
Table t = getTable(mmd);
if (im.subfieldName == null) {
if (t != null) {
im.value = t.getIdentifier().toString();
return;
}
} else {
if (t instanceof CollectionTable) {
CollectionTable collTable = (CollectionTable) t;
if (im.subfieldName.equals("owner")) {
m = collTable.getOwnerMapping();
} else if (im.subfieldName.equals("element")) {
m = collTable.getElementMapping();
} else if (im.subfieldName.equals("index")) {
m = collTable.getOrderMapping();
} else {
throw new NucleusUserException(Localiser.msg("050036", im.subfieldName, im));
}
} else if (t instanceof MapTable) {
MapTable mt = (MapTable) t;
if (im.subfieldName.equals("owner")) {
m = mt.getOwnerMapping();
} else if (im.subfieldName.equals("key")) {
m = mt.getKeyMapping();
} else if (im.subfieldName.equals("value")) {
m = mt.getValueMapping();
} else {
throw new NucleusUserException(Localiser.msg("050037", im.subfieldName, im));
}
} else {
throw new NucleusUserException(Localiser.msg("050035", im.className, im.fieldName, im.subfieldName));
}
}
}
im.value = m.getDatastoreMapping(0).getColumn().getIdentifier().toString();
}
use of org.datanucleus.store.rdbms.table.ClassTable in project datanucleus-rdbms by datanucleus.
the class FlushReferential method isClassSuitableForBatching.
private boolean isClassSuitableForBatching(ExecutionContext ec, AbstractClassMetaData cmd) {
if (cmd.hasRelations(ec.getClassLoaderResolver())) {
return false;
}
RDBMSStoreManager storeMgr = (RDBMSStoreManager) ec.getStoreManager();
ClassTable table = (ClassTable) storeMgr.getDatastoreClass(cmd.getFullClassName(), ec.getClassLoaderResolver());
while (true) {
if (!isTableSuitableForBatching(table)) {
return false;
}
table = (ClassTable) table.getSuperDatastoreClass();
if (table == null) {
// No more tables for this class
break;
}
}
return true;
}
use of org.datanucleus.store.rdbms.table.ClassTable in project datanucleus-rdbms by datanucleus.
the class DeleteTablesSchemaTransaction method run.
/* (non-Javadoc)
* @see org.datanucleus.store.rdbms.AbstractSchemaTransaction#run(org.datanucleus.ClassLoaderResolver)
*/
protected void run(ClassLoaderResolver clr) throws SQLException {
synchronized (rdbmsMgr) {
boolean success = true;
try {
NucleusLogger.DATASTORE_SCHEMA.debug(Localiser.msg("050045", rdbmsMgr.getCatalogName(), rdbmsMgr.getSchemaName()));
// Build up map of tables and views TODO Why use maps?
Map baseTablesByName = new HashMap();
Map viewsByName = new HashMap();
for (Iterator i = storeDataMgr.getManagedStoreData().iterator(); i.hasNext(); ) {
RDBMSStoreData data = (RDBMSStoreData) i.next();
if (NucleusLogger.DATASTORE_SCHEMA.isDebugEnabled()) {
NucleusLogger.DATASTORE_SCHEMA.debug(Localiser.msg("050046", data.getName()));
}
// If the class has a table/view to remove, add it to the list
if (data.hasTable()) {
if (data.mapsToView()) {
viewsByName.put(data.getDatastoreIdentifier(), data.getTable());
} else {
baseTablesByName.put(data.getDatastoreIdentifier(), data.getTable());
}
}
}
// Remove views
Iterator viewsIter = viewsByName.values().iterator();
while (viewsIter.hasNext()) {
ViewImpl view = (ViewImpl) viewsIter.next();
if (writer != null) {
try {
if (view instanceof ClassView) {
writer.write("-- ClassView " + view.toString() + " for classes " + StringUtils.objectArrayToString(((ClassView) view).getManagedClasses()) + "\n");
}
} catch (IOException ioe) {
NucleusLogger.DATASTORE_SCHEMA.error("error writing DDL into file", ioe);
}
((ViewImpl) viewsIter.next()).drop(getCurrentConnection());
} else {
// Drop view if exists in the datastore
StoreSchemaData info = rdbmsMgr.getSchemaHandler().getSchemaData(getCurrentConnection(), RDBMSSchemaHandler.TYPE_COLUMNS, new Object[] { view });
if (info != null) {
((ViewImpl) viewsIter.next()).drop(getCurrentConnection());
}
}
}
// Remove table constraints
Map<TableImpl, Boolean> schemaExistsForTableMap = new HashMap();
Iterator tablesIter = baseTablesByName.values().iterator();
while (tablesIter.hasNext()) {
TableImpl tbl = (TableImpl) tablesIter.next();
if (writer != null) {
try {
if (tbl instanceof ClassTable) {
writer.write("-- Constraints for ClassTable " + tbl.toString() + " for classes " + StringUtils.objectArrayToString(((ClassTable) tbl).getManagedClasses()) + "\n");
} else if (tbl instanceof JoinTable) {
writer.write("-- Constraints for JoinTable " + tbl.toString() + " for join relationship\n");
}
} catch (IOException ioe) {
NucleusLogger.DATASTORE_SCHEMA.error("error writing DDL into file", ioe);
}
tbl.dropConstraints(getCurrentConnection());
} else {
// Drop constraints if exists in the datastore
boolean exists = false;
try {
// Check table type as way of detecting existence
String tableType = ((RDBMSSchemaHandler) rdbmsMgr.getSchemaHandler()).getTableType(getCurrentConnection(), tbl);
if (tableType != null) {
exists = true;
}
} catch (Exception e) {
exists = false;
}
schemaExistsForTableMap.put(tbl, exists);
if (exists) {
tbl.dropConstraints(getCurrentConnection());
}
}
}
// Remove tables
tablesIter = baseTablesByName.values().iterator();
while (tablesIter.hasNext()) {
TableImpl tbl = (TableImpl) tablesIter.next();
if (writer != null) {
try {
if (tbl instanceof ClassTable) {
writer.write("-- ClassTable " + tbl.toString() + " for classes " + StringUtils.objectArrayToString(((ClassTable) tbl).getManagedClasses()) + "\n");
} else if (tbl instanceof JoinTable) {
writer.write("-- JoinTable " + tbl.toString() + " for join relationship\n");
}
} catch (IOException ioe) {
NucleusLogger.DATASTORE_SCHEMA.error("error writing DDL into file", ioe);
}
tbl.drop(getCurrentConnection());
} else {
// Drop table if exists in the datastore
Boolean schemaExists = schemaExistsForTableMap.get(tbl);
if (schemaExists != null && schemaExists == Boolean.TRUE) {
tbl.drop(getCurrentConnection());
}
}
}
} catch (Exception e) {
success = false;
String errorMsg = Localiser.msg("050047", e);
NucleusLogger.DATASTORE_SCHEMA.error(errorMsg);
throw new NucleusUserException(errorMsg, e);
}
if (!success) {
throw new NucleusException("DeleteTables operation failed");
}
}
}
Aggregations