use of org.datanucleus.metadata.AbstractClassMetaData in project datanucleus-rdbms by datanucleus.
the class DiscriminatorStatementGenerator method getStatement.
/**
* Accessor for the SelectStatement.
* @param ec ExecutionContext
* @return The SelectStatement for iterating through objects with a discriminator column
*/
public SelectStatement getStatement(ExecutionContext ec) {
SelectStatement stmt = null;
SQLTable discrimSqlTbl = null;
if (joinTable == null) {
// Select of candidate table
stmt = new SelectStatement(parentStmt, storeMgr, candidateTable, candidateTableAlias, candidateTableGroupName);
stmt.setClassLoaderResolver(clr);
discrimSqlTbl = stmt.getPrimaryTable();
} else {
// Select of join table, with join to element table
stmt = new SelectStatement(parentStmt, storeMgr, joinTable, joinTableAlias, candidateTableGroupName);
stmt.setClassLoaderResolver(clr);
JavaTypeMapping candidateIdMapping = candidateTable.getIdMapping();
if (hasOption(OPTION_ALLOW_NULLS)) {
// Put element table in same table group since all relates to the elements
discrimSqlTbl = stmt.join(JoinType.LEFT_OUTER_JOIN, null, joinElementMapping, candidateTable, null, candidateIdMapping, null, stmt.getPrimaryTable().getGroupName(), true);
} else {
// Put element table in same table group since all relates to the elements
discrimSqlTbl = stmt.join(JoinType.INNER_JOIN, null, joinElementMapping, candidateTable, null, candidateIdMapping, null, stmt.getPrimaryTable().getGroupName(), true);
}
}
JavaTypeMapping discMapping = candidateTable.getSurrogateMapping(SurrogateColumnType.DISCRIMINATOR, true);
if (discMapping != null) {
// Allow for discriminator being in super-table of the candidate table
discrimSqlTbl = SQLStatementHelper.getSQLTableForMappingOfTable(stmt, discrimSqlTbl, discMapping);
}
DiscriminatorMetaData dismd = discrimSqlTbl.getTable().getDiscriminatorMetaData();
boolean hasDiscriminator = (discMapping != null && dismd != null && dismd.getStrategy() != DiscriminatorStrategy.NONE);
// Check if we can omit the discriminator restriction
boolean restrictDiscriminator = hasOption(OPTION_RESTRICT_DISCRIM);
if (hasDiscriminator && restrictDiscriminator) {
// Add the discriminator expression to restrict accepted values
boolean multipleCandidates = false;
BooleanExpression discExpr = null;
if (candidates != null) {
// Multiple candidates
if (candidates.length > 1) {
multipleCandidates = true;
}
for (int i = 0; i < candidates.length; i++) {
if (Modifier.isAbstract(candidates[i].getModifiers())) {
// No point selecting this candidate since can't be instantiated
continue;
}
BooleanExpression discExprCandidate = SQLStatementHelper.getExpressionForDiscriminatorForClass(stmt, candidates[i].getName(), dismd, discMapping, discrimSqlTbl, clr);
if (discExpr != null) {
discExpr = discExpr.ior(discExprCandidate);
} else {
discExpr = discExprCandidate;
}
if (includeSubclasses) {
Collection<String> subclassNames = storeMgr.getSubClassesForClass(candidateType.getName(), true, clr);
Iterator<String> subclassIter = subclassNames.iterator();
if (!multipleCandidates) {
multipleCandidates = (subclassNames.size() > 0);
}
while (subclassIter.hasNext()) {
String subclassName = subclassIter.next();
BooleanExpression discExprSub = SQLStatementHelper.getExpressionForDiscriminatorForClass(stmt, subclassName, dismd, discMapping, discrimSqlTbl, clr);
discExpr = discExpr.ior(discExprSub);
}
}
}
} else {
// Single candidate
if (!Modifier.isAbstract(candidateType.getModifiers())) {
discExpr = SQLStatementHelper.getExpressionForDiscriminatorForClass(stmt, candidateType.getName(), dismd, discMapping, discrimSqlTbl, clr);
}
if (includeSubclasses) {
Collection<String> subclassNames = storeMgr.getSubClassesForClass(candidateType.getName(), true, clr);
Iterator<String> subclassIter = subclassNames.iterator();
multipleCandidates = (subclassNames.size() > 0);
while (subclassIter.hasNext()) {
String subclassName = subclassIter.next();
Class subclass = clr.classForName(subclassName);
if ((Modifier.isAbstract(subclass.getModifiers()))) {
continue;
}
BooleanExpression discExprCandidate = SQLStatementHelper.getExpressionForDiscriminatorForClass(stmt, subclassName, dismd, discMapping, discrimSqlTbl, clr);
if (discExpr == null) {
discExpr = discExprCandidate;
} else {
discExpr = discExpr.ior(discExprCandidate);
}
}
}
if (discExpr == null) {
// No possible candidates, so set expression as "1=0"
SQLExpressionFactory exprFactory = stmt.getSQLExpressionFactory();
JavaTypeMapping m = exprFactory.getMappingForType(boolean.class, true);
discExpr = exprFactory.newLiteral(stmt, m, true).eq(exprFactory.newLiteral(stmt, m, false));
}
}
if (discExpr != null) {
if (hasOption(OPTION_ALLOW_NULLS)) {
// Allow for null value of discriminator
SQLExpression expr = stmt.getSQLExpressionFactory().newExpression(stmt, discrimSqlTbl, discMapping);
SQLExpression val = new NullLiteral(stmt, null, null, null);
BooleanExpression nullDiscExpr = expr.eq(val);
discExpr = discExpr.ior(nullDiscExpr);
if (!multipleCandidates) {
multipleCandidates = true;
}
}
// Apply the discriminator to the query statement
if (multipleCandidates) {
discExpr.encloseInParentheses();
}
stmt.whereAnd(discExpr, true);
}
}
JavaTypeMapping multitenancyMapping = candidateTable.getSurrogateMapping(SurrogateColumnType.MULTITENANCY, false);
if (multitenancyMapping != null) {
// Multi-tenancy restriction
AbstractClassMetaData cmd = candidateTable.getClassMetaData();
SQLTable tenantSqlTbl = stmt.getTable(multitenancyMapping.getTable(), discrimSqlTbl.getGroupName());
SQLExpression tenantExpr = stmt.getSQLExpressionFactory().newExpression(stmt, tenantSqlTbl, multitenancyMapping);
SQLExpression tenantVal = stmt.getSQLExpressionFactory().newLiteral(stmt, multitenancyMapping, ec.getNucleusContext().getMultiTenancyId(ec, cmd));
stmt.whereAnd(tenantExpr.eq(tenantVal), true);
}
JavaTypeMapping softDeleteMapping = candidateTable.getSurrogateMapping(SurrogateColumnType.SOFTDELETE, false);
if (softDeleteMapping != null && !hasOption(OPTION_INCLUDE_SOFT_DELETES)) {
// Soft-delete restriction
SQLTable softDeleteSqlTbl = stmt.getTable(softDeleteMapping.getTable(), discrimSqlTbl.getGroupName());
SQLExpression softDeleteExpr = stmt.getSQLExpressionFactory().newExpression(stmt, softDeleteSqlTbl, softDeleteMapping);
SQLExpression softDeleteVal = stmt.getSQLExpressionFactory().newLiteral(stmt, softDeleteMapping, Boolean.FALSE);
stmt.whereAnd(softDeleteExpr.eq(softDeleteVal), true);
}
return stmt;
}
use of org.datanucleus.metadata.AbstractClassMetaData in project datanucleus-rdbms by datanucleus.
the class BaseContainerStore method getComponentInformationForClass.
/**
* Convenience method to find the element information relating to the element type.
* Used specifically for the "element-type" of a collection/array to find the elements which have table information.
* @param componentType Type of the component
* @param componentCmd Metadata for the root component class TODO Get rid of this
* @return Element information relating to the element type
*/
protected ComponentInfo[] getComponentInformationForClass(String componentType, AbstractClassMetaData componentCmd) {
ComponentInfo[] info = null;
DatastoreClass rootTbl;
String[] clsNames;
if (clr.classForName(componentType).isInterface()) {
// Collection<interface>, so find implementations of the interface
clsNames = storeMgr.getNucleusContext().getMetaDataManager().getClassesImplementingInterface(componentType, clr);
rootTbl = null;
} else {
clsNames = new String[] { componentType };
rootTbl = storeMgr.getDatastoreClass(componentType, clr);
}
if (componentCmd.getBaseAbstractClassMetaData().getInheritanceMetaData().getStrategy() == InheritanceStrategy.COMPLETE_TABLE) {
// Element uses COMPLETE-TABLE so need an elementInfo for each possible element that has a table
List<ComponentInfo> infos = new ArrayList<>();
if (rootTbl != null) {
infos.add(new ComponentInfo(componentCmd, rootTbl));
}
Collection<String> elementSubclassNames = storeMgr.getSubClassesForClass(componentCmd.getFullClassName(), true, clr);
if (elementSubclassNames != null) {
for (String elementSubclassName : elementSubclassNames) {
AbstractClassMetaData elemSubCmd = storeMgr.getMetaDataManager().getMetaDataForClass(elementSubclassName, clr);
DatastoreClass elemSubTbl = storeMgr.getDatastoreClass(elementSubclassName, clr);
if (elemSubTbl != null) {
infos.add(new ComponentInfo(elemSubCmd, elemSubTbl));
}
}
}
info = new ComponentInfo[infos.size()];
int infoNo = 0;
for (ComponentInfo ci : infos) {
info[infoNo++] = ci;
}
} else {
if (rootTbl == null) {
// Root class has no table (abstract, or subclass-table)
if (clr.classForName(componentType).isInterface()) {
info = new ComponentInfo[clsNames.length];
for (int i = 0; i < clsNames.length; i++) {
AbstractClassMetaData implCmd = storeMgr.getMetaDataManager().getMetaDataForClass(clsNames[i], clr);
DatastoreClass table = storeMgr.getDatastoreClass(clsNames[i], clr);
info[i] = new ComponentInfo(implCmd, table);
}
} else {
AbstractClassMetaData[] subclassCmds = storeMgr.getClassesManagingTableForClass(componentCmd, clr);
info = new ComponentInfo[subclassCmds.length];
for (int i = 0; i < subclassCmds.length; i++) {
DatastoreClass table = storeMgr.getDatastoreClass(subclassCmds[i].getFullClassName(), clr);
info[i] = new ComponentInfo(subclassCmds[i], table);
}
}
} else {
info = new ComponentInfo[clsNames.length];
for (int i = 0; i < clsNames.length; i++) {
AbstractClassMetaData cmd = storeMgr.getNucleusContext().getMetaDataManager().getMetaDataForClass(clsNames[i], clr);
DatastoreClass table = storeMgr.getDatastoreClass(cmd.getFullClassName(), clr);
info[i] = new ComponentInfo(cmd, table);
}
}
}
return info;
}
use of org.datanucleus.metadata.AbstractClassMetaData 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.metadata.AbstractClassMetaData in project datanucleus-rdbms by datanucleus.
the class UnionStatementGenerator method getStatement.
/**
* Accessor for the SelectStatement for the candidate [+ subclasses].
* @param ec ExecutionContext
* @return The SelectStatement returning objects with a UNION statement.
*/
public SelectStatement getStatement(ExecutionContext ec) {
// Find set of possible candidates (including subclasses of subclasses)
Collection<String> candidateClassNames = new ArrayList<>();
AbstractClassMetaData acmd = storeMgr.getMetaDataManager().getMetaDataForClass(candidateType, clr);
candidateClassNames.add(acmd.getFullClassName());
if (includeSubclasses) {
Collection<String> subclasses = storeMgr.getSubClassesForClass(candidateType.getName(), true, clr);
candidateClassNames.addAll(subclasses);
}
// Eliminate any classes that are not instantiable
Iterator<String> iter = candidateClassNames.iterator();
while (iter.hasNext()) {
String className = iter.next();
try {
Class cls = clr.classForName(className);
if (Modifier.isAbstract(cls.getModifiers())) {
// Remove since abstract hence not instantiable
iter.remove();
}
} catch (Exception e) {
// Remove since class not found
iter.remove();
}
}
if (hasOption(OPTION_SELECT_DN_TYPE)) {
// Get the length of the longest class name
iter = candidateClassNames.iterator();
while (iter.hasNext()) {
String className = iter.next();
if (className.length() > maxClassNameLength) {
maxClassNameLength = className.length();
}
}
}
if (candidateClassNames.isEmpty()) {
// Either passed invalid classes, or no concrete classes with available tables present!
throw new NucleusException("Attempt to generate SQL statement using UNIONs for " + candidateType.getName() + " yet there are no concrete classes with their own table available");
}
SelectStatement stmt = null;
for (String candidateClassName : candidateClassNames) {
SelectStatement candidateStmt = null;
if (joinTable == null) {
// Select of candidate table
candidateStmt = getSelectStatementForCandidate(candidateClassName, ec);
} else {
// Select of join table and join to element
candidateStmt = getSQLStatementForCandidateViaJoin(candidateClassName);
}
if (candidateStmt != null) {
if (stmt == null) {
stmt = candidateStmt;
} else {
stmt.union(candidateStmt);
}
}
}
return stmt;
}
use of org.datanucleus.metadata.AbstractClassMetaData in project datanucleus-rdbms by datanucleus.
the class SQLStatementHelper method getDiscriminatorValuesForMember.
/**
* Method to return all possible discriminator values for the supplied class and its subclasses.
* @param className Name of the class
* @param discMapping The discriminator mapping
* @param storeMgr StoreManager
* @param clr ClassLoader resolver
* @return The possible discriminator values
*/
public static List getDiscriminatorValuesForMember(String className, JavaTypeMapping discMapping, RDBMSStoreManager storeMgr, ClassLoaderResolver clr) {
List discrimValues = new ArrayList();
DiscriminatorStrategy strategy = discMapping.getTable().getDiscriminatorMetaData().getStrategy();
if (strategy != DiscriminatorStrategy.NONE) {
MetaDataManager mmgr = storeMgr.getMetaDataManager();
AbstractClassMetaData cmd = mmgr.getMetaDataForClass(className, clr);
discrimValues.add(cmd.getDiscriminatorValue());
Collection<String> subclasses = storeMgr.getSubClassesForClass(className, true, clr);
if (subclasses != null && subclasses.size() > 0) {
Iterator<String> subclassesIter = subclasses.iterator();
while (subclassesIter.hasNext()) {
String subclassName = subclassesIter.next();
AbstractClassMetaData subclassCmd = mmgr.getMetaDataForClass(subclassName, clr);
discrimValues.add(subclassCmd.getDiscriminatorValue());
}
}
}
return discrimValues;
}
Aggregations