use of org.datanucleus.store.rdbms.sql.expression.StringLiteral in project datanucleus-rdbms by datanucleus.
the class RDBMSQueryUtils method getStatementForCandidates.
/**
* Method to return a statement selecting the candidate table(s) required to cover all possible types for this candidates inheritance strategy.
* @param storeMgr RDBMS StoreManager
* @param parentStmt Parent statement (if there is one)
* @param cmd Metadata for the class
* @param clsMapping Mapping for the results of the statement
* @param ec ExecutionContext
* @param candidateCls Candidate class
* @param subclasses Whether to create a statement for subclasses of the candidate too
* @param result The result clause
* @param candidateAlias alias for the candidate (if any)
* @param candidateTableGroupName TableGroup name for the candidate (if any)
* @param options Any options for the statement for getting candidates. See SelectStatementGenerator for some options.
* @return The SQLStatement
* @throws NucleusException if there are no tables for concrete classes in this query (hence would return null)
*/
public static SelectStatement getStatementForCandidates(RDBMSStoreManager storeMgr, SQLStatement parentStmt, AbstractClassMetaData cmd, StatementClassMapping clsMapping, ExecutionContext ec, Class candidateCls, boolean subclasses, String result, String candidateAlias, String candidateTableGroupName, Set<String> options) {
SelectStatement stmt = null;
DatastoreIdentifier candidateAliasId = null;
if (candidateAlias != null) {
candidateAliasId = storeMgr.getIdentifierFactory().newTableIdentifier(candidateAlias);
}
ClassLoaderResolver clr = ec.getClassLoaderResolver();
List<DatastoreClass> candidateTables = new ArrayList<>();
if (cmd.getInheritanceMetaData().getStrategy() == InheritanceStrategy.COMPLETE_TABLE) {
DatastoreClass candidateTable = storeMgr.getDatastoreClass(cmd.getFullClassName(), clr);
if (candidateTable != null) {
candidateTables.add(candidateTable);
}
if (subclasses) {
Collection<String> subclassNames = storeMgr.getSubClassesForClass(cmd.getFullClassName(), subclasses, clr);
if (subclassNames != null) {
Iterator<String> subclassIter = subclassNames.iterator();
while (subclassIter.hasNext()) {
String subclassName = subclassIter.next();
DatastoreClass tbl = storeMgr.getDatastoreClass(subclassName, clr);
if (tbl != null) {
candidateTables.add(tbl);
}
}
}
}
Iterator<DatastoreClass> iter = candidateTables.iterator();
int maxClassNameLength = cmd.getFullClassName().length();
while (iter.hasNext()) {
DatastoreClass cls = iter.next();
String className = cls.getType();
if (className.length() > maxClassNameLength) {
maxClassNameLength = className.length();
}
}
iter = candidateTables.iterator();
while (iter.hasNext()) {
DatastoreClass cls = iter.next();
SelectStatement tblStmt = new SelectStatement(parentStmt, storeMgr, cls, candidateAliasId, candidateTableGroupName);
tblStmt.setClassLoaderResolver(clr);
tblStmt.setCandidateClassName(cls.getType());
// Add SELECT of dummy column accessible as "DN_TYPE" containing the classname
JavaTypeMapping m = storeMgr.getMappingManager().getMapping(String.class);
String nuctypeName = cls.getType();
if (maxClassNameLength > nuctypeName.length()) {
nuctypeName = StringUtils.leftAlignedPaddedString(nuctypeName, maxClassNameLength);
}
StringLiteral lit = new StringLiteral(tblStmt, m, nuctypeName, null);
tblStmt.select(lit, UnionStatementGenerator.DN_TYPE_COLUMN);
if (stmt == null) {
stmt = tblStmt;
} else {
stmt.union(tblStmt);
}
}
if (clsMapping != null) {
clsMapping.setNucleusTypeColumnName(UnionStatementGenerator.DN_TYPE_COLUMN);
}
} else {
// "new-table", "superclass-table", "subclass-table"
List<Class> candidateClasses = new ArrayList<>();
if (ClassUtils.isReferenceType(candidateCls)) {
// Persistent interface, so find all persistent implementations
String[] clsNames = storeMgr.getNucleusContext().getMetaDataManager().getClassesImplementingInterface(candidateCls.getName(), clr);
for (int i = 0; i < clsNames.length; i++) {
Class cls = clr.classForName(clsNames[i]);
DatastoreClass table = storeMgr.getDatastoreClass(clsNames[i], clr);
candidateClasses.add(cls);
candidateTables.add(table);
AbstractClassMetaData implCmd = storeMgr.getNucleusContext().getMetaDataManager().getMetaDataForClass(cls, clr);
if (implCmd.getIdentityType() != cmd.getIdentityType()) {
throw new NucleusUserException("You are querying an interface (" + cmd.getFullClassName() + ") " + "yet one of its implementations (" + implCmd.getFullClassName() + ") uses a different identity type!");
} else if (cmd.getIdentityType() == IdentityType.APPLICATION) {
if (cmd.getPKMemberPositions().length != implCmd.getPKMemberPositions().length) {
throw new NucleusUserException("You are querying an interface (" + cmd.getFullClassName() + ") " + "yet one of its implementations (" + implCmd.getFullClassName() + ") has a different number of PK members!");
}
}
}
} else {
DatastoreClass candidateTable = storeMgr.getDatastoreClass(cmd.getFullClassName(), clr);
if (candidateTable != null) {
// Candidate has own table
candidateClasses.add(candidateCls);
candidateTables.add(candidateTable);
} else {
// Candidate stored in subclass tables
AbstractClassMetaData[] cmds = storeMgr.getClassesManagingTableForClass(cmd, clr);
if (cmds != null && cmds.length > 0) {
for (int i = 0; i < cmds.length; i++) {
DatastoreClass table = storeMgr.getDatastoreClass(cmds[i].getFullClassName(), clr);
Class cls = clr.classForName(cmds[i].getFullClassName());
candidateClasses.add(cls);
candidateTables.add(table);
}
} else {
throw new UnsupportedOperationException("No tables for query of " + cmd.getFullClassName());
}
}
}
for (int i = 0; i < candidateTables.size(); i++) {
DatastoreClass tbl = candidateTables.get(i);
Class cls = candidateClasses.get(i);
SelectStatementGenerator stmtGen = null;
if (tbl.getSurrogateMapping(SurrogateColumnType.DISCRIMINATOR, true) != null || QueryUtils.resultHasOnlyAggregates(result)) {
// Either has a discriminator, or only selecting aggregates so need single select
// TODO Add option to omit discriminator restriction
stmtGen = new DiscriminatorStatementGenerator(storeMgr, clr, cls, subclasses, candidateAliasId, candidateTableGroupName);
stmtGen.setOption(SelectStatementGenerator.OPTION_RESTRICT_DISCRIM);
if (options != null) {
for (String option : options) {
stmtGen.setOption(option);
}
}
} else {
// No discriminator, so try to identify using UNIONs (hopefully one per class)
stmtGen = new UnionStatementGenerator(storeMgr, clr, cls, subclasses, candidateAliasId, candidateTableGroupName);
if (options != null) {
for (String option : options) {
stmtGen.setOption(option);
}
}
if (result == null) {
// Returning one row per candidate so include distinguisher column
stmtGen.setOption(SelectStatementGenerator.OPTION_SELECT_DN_TYPE);
if (clsMapping != null) {
clsMapping.setNucleusTypeColumnName(UnionStatementGenerator.DN_TYPE_COLUMN);
}
}
}
stmtGen.setParentStatement(parentStmt);
SelectStatement tblStmt = stmtGen.getStatement(ec);
if (stmt == null) {
stmt = tblStmt;
} else {
stmt.union(tblStmt);
}
}
}
return stmt;
}
use of org.datanucleus.store.rdbms.sql.expression.StringLiteral in project datanucleus-rdbms by datanucleus.
the class MapSizeMethod 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 expr, List<SQLExpression> args) {
if (args != null && args.size() > 0) {
throw new NucleusException(Localiser.msg("060015", "size", "MapExpression"));
}
SQLExpressionFactory exprFactory = stmt.getSQLExpressionFactory();
if (expr instanceof MapLiteral) {
// Just return the map length since we have the value
Map map = (Map) ((MapLiteral) expr).getValue();
return exprFactory.newLiteral(stmt, exprFactory.getMappingForType(int.class, false), Integer.valueOf(map.size()));
}
AbstractMemberMetaData ownerMmd = expr.getJavaTypeMapping().getMemberMetaData();
RDBMSStoreManager storeMgr = stmt.getRDBMSManager();
ClassLoaderResolver clr = stmt.getQueryGenerator().getClassLoaderResolver();
// TODO Allow for interface keys/values, etc
JavaTypeMapping ownerMapping = null;
Table mapTbl = null;
if (ownerMmd.getMap().getMapType() == MapType.MAP_TYPE_JOIN) {
// JoinTable
mapTbl = storeMgr.getTable(ownerMmd);
ownerMapping = ((JoinTable) mapTbl).getOwnerMapping();
} else if (ownerMmd.getMap().getMapType() == MapType.MAP_TYPE_KEY_IN_VALUE) {
// ForeignKey from value table to key
AbstractClassMetaData valueCmd = storeMgr.getNucleusContext().getMetaDataManager().getMetaDataForClass(ownerMmd.getMap().getValueType(), clr);
mapTbl = storeMgr.getDatastoreClass(ownerMmd.getMap().getValueType(), clr);
if (ownerMmd.getMappedBy() != null) {
ownerMapping = mapTbl.getMemberMapping(valueCmd.getMetaDataForMember(ownerMmd.getMappedBy()));
} else {
ownerMapping = ((DatastoreClass) mapTbl).getExternalMapping(ownerMmd, MappingType.EXTERNAL_FK);
}
} else if (ownerMmd.getMap().getMapType() == MapType.MAP_TYPE_VALUE_IN_KEY) {
// ForeignKey from key table to value
AbstractClassMetaData keyCmd = storeMgr.getNucleusContext().getMetaDataManager().getMetaDataForClass(ownerMmd.getMap().getKeyType(), clr);
mapTbl = storeMgr.getDatastoreClass(ownerMmd.getMap().getKeyType(), clr);
if (ownerMmd.getMappedBy() != null) {
ownerMapping = mapTbl.getMemberMapping(keyCmd.getMetaDataForMember(ownerMmd.getMappedBy()));
} else {
ownerMapping = ((DatastoreClass) mapTbl).getExternalMapping(ownerMmd, MappingType.EXTERNAL_FK);
}
} else {
throw new NucleusException("Invalid map for " + expr + " in size() call");
}
SelectStatement subStmt = new SelectStatement(stmt, storeMgr, mapTbl, null, null);
subStmt.setClassLoaderResolver(clr);
JavaTypeMapping mapping = storeMgr.getMappingManager().getMappingWithDatastoreMapping(String.class, false, false, clr);
SQLExpression countExpr = exprFactory.newLiteral(subStmt, mapping, "COUNT(*)");
((StringLiteral) countExpr).generateStatementWithoutQuotes();
subStmt.select(countExpr, null);
SQLExpression elementOwnerExpr = exprFactory.newExpression(subStmt, subStmt.getPrimaryTable(), ownerMapping);
SQLExpression ownerIdExpr = exprFactory.newExpression(stmt, expr.getSQLTable(), expr.getSQLTable().getTable().getIdMapping());
subStmt.whereAnd(elementOwnerExpr.eq(ownerIdExpr), true);
JavaTypeMapping subqMapping = exprFactory.getMappingForType(Integer.class, false);
SQLExpression subqExpr = new NumericSubqueryExpression(stmt, subStmt);
subqExpr.setJavaTypeMapping(subqMapping);
return subqExpr;
}
use of org.datanucleus.store.rdbms.sql.expression.StringLiteral in project datanucleus-rdbms by datanucleus.
the class StringLength4Method 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 expr, List<SQLExpression> args) {
if (!expr.isParameter() && expr instanceof StringLiteral) {
SQLExpressionFactory exprFactory = stmt.getSQLExpressionFactory();
JavaTypeMapping m = exprFactory.getMappingForType(int.class, false);
String val = (String) ((StringLiteral) expr).getValue();
return new IntegerLiteral(stmt, m, Integer.valueOf(val.length()), null);
} else if (expr instanceof StringExpression || expr instanceof ParameterLiteral) {
ArrayList funcArgs = new ArrayList();
funcArgs.add(expr);
return new NumericExpression(stmt, stmt.getSQLExpressionFactory().getMappingForType(int.class), "LEN", funcArgs);
} else {
throw new NucleusException(Localiser.msg("060001", "length", expr));
}
}
use of org.datanucleus.store.rdbms.sql.expression.StringLiteral in project datanucleus-rdbms by datanucleus.
the class StringLengthMethod 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 expr, List<SQLExpression> args) {
if (!expr.isParameter() && expr instanceof StringLiteral) {
SQLExpressionFactory exprFactory = stmt.getSQLExpressionFactory();
JavaTypeMapping m = exprFactory.getMappingForType(int.class, false);
String val = (String) ((StringLiteral) expr).getValue();
return new IntegerLiteral(stmt, m, Integer.valueOf(val.length()), null);
} else if (expr instanceof StringExpression || expr instanceof ParameterLiteral) {
ArrayList funcArgs = new ArrayList();
funcArgs.add(expr);
return new NumericExpression(stmt, stmt.getSQLExpressionFactory().getMappingForType(int.class), "CHAR_LENGTH", funcArgs);
} else {
throw new NucleusException(Localiser.msg("060001", "length", expr));
}
}
use of org.datanucleus.store.rdbms.sql.expression.StringLiteral in project datanucleus-rdbms by datanucleus.
the class StringMatchesMethod 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 expr, List<SQLExpression> args) {
if (args == null || args.size() > 2) {
throw new NucleusException("Incorrect arguments for String.matches(StringExpression)");
} else if (!(args.get(0) instanceof StringExpression) && !(args.get(0) instanceof ParameterLiteral)) {
throw new NucleusException("Incorrect arguments for String.matches(StringExpression)");
}
SQLExpression likeExpr = args.get(0);
if (!(likeExpr instanceof StringExpression) && !(likeExpr instanceof CharacterExpression) && !(likeExpr instanceof ParameterLiteral)) {
throw new NucleusException(Localiser.msg("060003", "like/matches", "StringExpression", 0, "StringExpression/CharacterExpression/ParameterLiteral"));
}
SQLExpression escapeExpr = null;
if (args.size() > 1) {
escapeExpr = args.get(1);
}
if ((likeExpr instanceof StringLiteral || likeExpr instanceof ParameterLiteral) && likeExpr.isParameter()) {
// Argument as parameter needs translation to use SQL "LIKE" syntax, so has to be embedded as literal
stmt.getQueryGenerator().useParameterExpressionAsLiteral((SQLLiteral) likeExpr);
}
SQLExpressionFactory exprFactory = stmt.getSQLExpressionFactory();
if (expr instanceof StringLiteral && likeExpr instanceof StringLiteral) {
// String.matches(String) so evaluate in-memory
String primary = (String) ((StringLiteral) expr).getValue();
String pattern = (String) ((StringLiteral) likeExpr).getValue();
return new BooleanLiteral(stmt, exprFactory.getMappingForType(boolean.class, false), primary.matches(pattern));
} else if (expr instanceof StringLiteral) {
return getBooleanLikeExpression(stmt, expr, likeExpr, escapeExpr);
} else if (expr instanceof StringExpression && likeExpr instanceof StringLiteral) {
// Convert the pattern to use the regex constructs suitable for the datastore
String pattern = (String) ((StringLiteral) likeExpr).getValue();
if (stmt.getQueryGenerator().getQueryLanguage().equalsIgnoreCase(Query.LANGUAGE_JDOQL)) {
// JDOQL input is in java.lang.String regular expression format, so convert to SQL like
boolean caseSensitive = false;
if (pattern.startsWith("(?i)")) {
caseSensitive = true;
pattern = pattern.substring(4);
}
DatastoreAdapter dba = stmt.getDatastoreAdapter();
RegularExpressionConverter converter = new RegularExpressionConverter(dba.getPatternExpressionZeroMoreCharacters().charAt(0), dba.getPatternExpressionAnyCharacter().charAt(0), dba.getEscapeCharacter().charAt(0));
if (caseSensitive) {
SQLExpression patternExpr = exprFactory.newLiteral(stmt, likeExpr.getJavaTypeMapping(), converter.convert(pattern).toLowerCase());
return getBooleanLikeExpression(stmt, expr.invoke("toLowerCase", null), patternExpr, escapeExpr);
}
SQLExpression patternExpr = exprFactory.newLiteral(stmt, likeExpr.getJavaTypeMapping(), converter.convert(pattern));
return getBooleanLikeExpression(stmt, expr, patternExpr, escapeExpr);
}
SQLExpression patternExpr = exprFactory.newLiteral(stmt, likeExpr.getJavaTypeMapping(), pattern);
return getBooleanLikeExpression(stmt, expr, patternExpr, escapeExpr);
} else if (expr instanceof StringExpression) {
return getExpressionForStringExpressionInput(stmt, expr, likeExpr, escapeExpr);
} else {
throw new NucleusException(Localiser.msg("060001", "matches", expr));
}
}
Aggregations