use of org.datanucleus.exceptions.NucleusException in project datanucleus-rdbms by datanucleus.
the class ArrayContainsMethod method containsAsSubquery.
/**
* Method to return an expression for Collection.contains using a subquery "EXISTS".
* This is for use when there are "!contains" or "OR" operations in the filter.
* Creates the following SQL,
* <ul>
* <li><b>Collection of NonPC using join table</b>
* <pre>
* SELECT 1 FROM JOIN_TBL A0_SUB
* WHERE A0_SUB.JOIN_OWN_ID = A0.ID AND A0_SUB.JOIN_ELEM_ID = {elemExpr}
* </pre>
* </li>
* <li><b>Collection of PC using join table</b>
* <pre>
* SELECT 1 FROM ELEM_TABLE A0_SUB INNER JOIN JOIN_TBL B0 ON ...
* WHERE B0.JOIN_OWN_ID = A0.ID AND A0_SUB.ID = {elemExpr}
* </pre>
* </li>
* </ul>
* and returns a BooleanSubqueryExpression ("EXISTS (subquery)")
* @param stmt SQLStatement
* @param arrExpr Collection expression
* @param elemExpr Expression for the element
* @return Contains expression
*/
protected SQLExpression containsAsSubquery(SQLStatement stmt, ArrayExpression arrExpr, SQLExpression elemExpr) {
boolean elemIsUnbound = (elemExpr instanceof UnboundExpression);
String varName = null;
if (elemIsUnbound) {
varName = ((UnboundExpression) elemExpr).getVariableName();
NucleusLogger.QUERY.debug(">> Array.contains binding unbound variable " + varName + " using SUBQUERY");
}
RDBMSStoreManager storeMgr = stmt.getRDBMSManager();
SQLExpressionFactory exprFactory = stmt.getSQLExpressionFactory();
ClassLoaderResolver clr = stmt.getQueryGenerator().getClassLoaderResolver();
AbstractMemberMetaData mmd = arrExpr.getJavaTypeMapping().getMemberMetaData();
AbstractClassMetaData elemCmd = mmd.getArray().getElementClassMetaData(clr);
ArrayTable joinTbl = (ArrayTable) storeMgr.getTable(mmd);
SelectStatement subStmt = null;
if (joinTbl != null) {
// JoinTable array
if (elemCmd == null) {
// Array<Non-PC>
subStmt = new SelectStatement(stmt, storeMgr, joinTbl, null, null);
subStmt.setClassLoaderResolver(clr);
JavaTypeMapping oneMapping = storeMgr.getMappingManager().getMapping(Integer.class);
subStmt.select(exprFactory.newLiteral(subStmt, oneMapping, 1), null);
// Restrict to array owner
JavaTypeMapping ownerMapping = ((JoinTable) joinTbl).getOwnerMapping();
SQLExpression ownerExpr = exprFactory.newExpression(subStmt, subStmt.getPrimaryTable(), ownerMapping);
SQLExpression ownerIdExpr = exprFactory.newExpression(stmt, arrExpr.getSQLTable(), arrExpr.getSQLTable().getTable().getIdMapping());
subStmt.whereAnd(ownerExpr.eq(ownerIdExpr), true);
SQLExpression elemIdExpr = exprFactory.newExpression(subStmt, subStmt.getPrimaryTable(), joinTbl.getElementMapping());
if (elemIsUnbound) {
// Bind the variable in the QueryGenerator
stmt.getQueryGenerator().bindVariable(varName, null, elemIdExpr.getSQLTable(), elemIdExpr.getJavaTypeMapping());
} else {
// Add restrict to element
subStmt.whereAnd(elemIdExpr.eq(elemExpr), true);
}
} else {
// Array<PC>
DatastoreClass elemTbl = storeMgr.getDatastoreClass(mmd.getArray().getElementType(), clr);
subStmt = new SelectStatement(stmt, storeMgr, elemTbl, null, null);
subStmt.setClassLoaderResolver(clr);
JavaTypeMapping oneMapping = storeMgr.getMappingManager().getMapping(Integer.class);
subStmt.select(exprFactory.newLiteral(subStmt, oneMapping, 1), null);
// Join to join table
SQLTable joinSqlTbl = subStmt.join(JoinType.INNER_JOIN, subStmt.getPrimaryTable(), elemTbl.getIdMapping(), null, joinTbl, null, joinTbl.getElementMapping(), null, null, null, true, null);
// Restrict to array owner
JavaTypeMapping ownerMapping = ((JoinTable) joinTbl).getOwnerMapping();
SQLExpression ownerExpr = exprFactory.newExpression(subStmt, joinSqlTbl, ownerMapping);
SQLExpression ownerIdExpr = exprFactory.newExpression(stmt, arrExpr.getSQLTable(), arrExpr.getSQLTable().getTable().getIdMapping());
subStmt.whereAnd(ownerExpr.eq(ownerIdExpr), true);
SQLExpression elemIdExpr = exprFactory.newExpression(subStmt, subStmt.getPrimaryTable(), elemTbl.getIdMapping());
if (elemIsUnbound) {
// Bind the variable in the QueryGenerator
stmt.getQueryGenerator().bindVariable(varName, elemCmd, elemIdExpr.getSQLTable(), elemIdExpr.getJavaTypeMapping());
} else {
// Add restrict to element
subStmt.whereAnd(elemIdExpr.eq(elemExpr), true);
}
}
} else {
// TODO Support FK array ?
throw new NucleusException("Dont support evaluation of ARRAY.contains when no join table is used");
}
return new BooleanSubqueryExpression(stmt, "EXISTS", subStmt);
}
use of org.datanucleus.exceptions.NucleusException in project datanucleus-rdbms by datanucleus.
the class ArraySizeMethod 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/length", "ArrayExpression"));
}
SQLExpressionFactory exprFactory = stmt.getSQLExpressionFactory();
if (expr instanceof ArrayLiteral) {
// Just return the array length since we have the value
return exprFactory.newLiteral(stmt, exprFactory.getMappingForType(int.class, false), Integer.valueOf(Array.getLength(((ArrayLiteral) expr).getValue())));
}
AbstractMemberMetaData ownerMmd = expr.getJavaTypeMapping().getMemberMetaData();
String elementType = ownerMmd.getArray().getElementType();
RDBMSStoreManager storeMgr = stmt.getRDBMSManager();
ClassLoaderResolver clr = stmt.getQueryGenerator().getClassLoaderResolver();
// TODO Allow for interface elements, etc
JavaTypeMapping ownerMapping = null;
Table arrayTbl = null;
if (ownerMmd.getMappedBy() != null) {
// Bidirectional
AbstractMemberMetaData elementMmd = ownerMmd.getRelatedMemberMetaData(clr)[0];
if (ownerMmd.getJoinMetaData() != null || elementMmd.getJoinMetaData() != null) {
// JoinTable
arrayTbl = storeMgr.getTable(ownerMmd);
ownerMapping = ((JoinTable) arrayTbl).getOwnerMapping();
} else {
// ForeignKey
arrayTbl = storeMgr.getDatastoreClass(elementType, clr);
ownerMapping = arrayTbl.getMemberMapping(elementMmd);
}
} else {
// Unidirectional
if (ownerMmd.getJoinMetaData() != null) {
// JoinTable
arrayTbl = storeMgr.getTable(ownerMmd);
ownerMapping = ((JoinTable) arrayTbl).getOwnerMapping();
} else {
// ForeignKey
arrayTbl = storeMgr.getDatastoreClass(elementType, clr);
ownerMapping = ((DatastoreClass) arrayTbl).getExternalMapping(ownerMmd, MappingType.EXTERNAL_FK);
}
}
SelectStatement subStmt = new SelectStatement(stmt, storeMgr, arrayTbl, null, null);
subStmt.setClassLoaderResolver(clr);
JavaTypeMapping mapping = storeMgr.getMappingManager().getMappingWithColumnMapping(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.exceptions.NucleusException in project datanucleus-rdbms by datanucleus.
the class SQLExpressionFactory method getMethod.
/**
* Accessor for the method defined by the class/method names and supplied args.
* Throws a NucleusException is the method is not supported.
* Note that if the class name passed in is not for a listed class with that method defined then will check all remaining defined methods for a superclass.
* @param className Class we are invoking the method on
* @param methodName Name of the method
* @param args Any arguments to the method call (ignored currently) TODO Check the arguments
* @return The method
*/
protected SQLMethod getMethod(String className, String methodName, List args) {
String datastoreId = storeMgr.getDatastoreAdapter().getVendorID();
// Try to find datastore-dependent evaluator for class+method
MethodKey methodKey1 = getSQLMethodKey(datastoreId, className, methodName);
MethodKey methodKey2 = null;
SQLMethod method = sqlMethodsByKey.get(methodKey1);
if (method == null) {
// Try to find datastore-independent evaluator for class+method
methodKey2 = getSQLMethodKey(null, className, methodName);
method = sqlMethodsByKey.get(methodKey2);
}
if (method != null) {
return method;
}
// No existing instance, so check the built-in SQLMethods from DatastoreAdapter
Class sqlMethodCls = storeMgr.getDatastoreAdapter().getSQLMethodClass(className, methodName, clr);
if (sqlMethodCls != null) {
// Built-in SQLMethod found, so instantiate it, cache it and return it
try {
method = (SQLMethod) sqlMethodCls.getDeclaredConstructor().newInstance();
MethodKey key = getSQLMethodKey(datastoreId, className, methodName);
sqlMethodsByKey.put(key, method);
return method;
} catch (Exception e) {
throw new NucleusException("Error creating SQLMethod of type " + sqlMethodCls.getName() + " for class=" + className + " method=" + methodName);
}
}
// Check the plugin mechanism
// 1). Try datastore-dependent key
boolean datastoreDependent = true;
if (!pluginSqlMethodsKeysSupported.contains(methodKey1)) {
// 2). No datastore-dependent method, so try a datastore-independent key
datastoreDependent = false;
if (!pluginSqlMethodsKeysSupported.contains(methodKey2)) {
// Not listed as supported for this particular class+method, so maybe is for a superclass
boolean unsupported = true;
if (!StringUtils.isWhitespace(className)) {
Class cls = clr.classForName(className);
// Try datastore-dependent
for (MethodKey methodKey : pluginSqlMethodsKeysSupported) {
if (methodKey.methodName.equals(methodName) && methodKey.datastoreName.equals(datastoreId)) {
Class methodCls = null;
try {
methodCls = clr.classForName(methodKey.clsName);
} catch (ClassNotResolvedException cnre) {
// Maybe generic array support?
}
if (methodCls != null && methodCls.isAssignableFrom(cls)) {
// This one is usable here, for superclass
method = sqlMethodsByKey.get(methodKey);
if (method != null) {
MethodKey superMethodKey = new MethodKey();
superMethodKey.clsName = className;
superMethodKey.methodName = methodKey.methodName;
superMethodKey.datastoreName = methodKey.datastoreName;
// Cache the same method under this class also
sqlMethodsByKey.put(superMethodKey, method);
return method;
}
className = methodKey.clsName;
datastoreId = methodKey.datastoreName;
datastoreDependent = true;
unsupported = false;
break;
}
}
}
if (unsupported) {
// Try datastore-independent
for (MethodKey methodKey : pluginSqlMethodsKeysSupported) {
if (methodKey.methodName.equals(methodName) && methodKey.datastoreName.equals("ALL")) {
Class methodCls = null;
try {
methodCls = clr.classForName(methodKey.clsName);
} catch (ClassNotResolvedException cnre) {
// Maybe generic array support?
}
if (methodCls != null && methodCls.isAssignableFrom(cls)) {
// This one is usable here, for superclass
method = sqlMethodsByKey.get(methodKey);
if (method != null) {
MethodKey superMethodKey = new MethodKey();
superMethodKey.clsName = className;
superMethodKey.methodName = methodKey.methodName;
superMethodKey.datastoreName = methodKey.datastoreName;
// Cache the same method under this class also
sqlMethodsByKey.put(superMethodKey, method);
return method;
}
className = methodKey.clsName;
datastoreId = methodKey.datastoreName;
datastoreDependent = false;
unsupported = false;
break;
}
}
}
}
}
if (unsupported) {
if (className != null) {
throw new NucleusUserException(Localiser.msg("060008", methodName, className));
}
throw new NucleusUserException(Localiser.msg("060009", methodName));
}
}
}
// Fallback to plugin lookup of class+method[+datastore]
PluginManager pluginMgr = storeMgr.getNucleusContext().getPluginManager();
String[] attrNames = (datastoreDependent ? new String[] { "class", "method", "datastore" } : new String[] { "class", "method" });
String[] attrValues = (datastoreDependent ? new String[] { className, methodName, datastoreId } : new String[] { className, methodName });
try {
method = (SQLMethod) pluginMgr.createExecutableExtension("org.datanucleus.store.rdbms.sql_method", attrNames, attrValues, "evaluator", new Class[] {}, new Object[] {});
// Register the method
sqlMethodsByKey.put(getSQLMethodKey(datastoreDependent ? datastoreId : null, className, methodName), method);
return method;
} catch (Exception e) {
throw new NucleusUserException(Localiser.msg("060011", "class=" + className + " method=" + methodName), e);
}
}
use of org.datanucleus.exceptions.NucleusException in project datanucleus-rdbms by datanucleus.
the class SQLExpressionFactory method invokeOperation.
/**
* Accessor for the result of an SQLOperation call on the supplied expression with the supplied args.
* Throws a NucleusException is the method is not supported.
* @param name Operation to be invoked
* @param expr The first expression to perform the operation on
* @param expr2 The second expression to perform the operation on
* @return The result
* @throws UnsupportedOperationException if the operation is not specified
*/
public SQLExpression invokeOperation(String name, SQLExpression expr, SQLExpression expr2) {
// Check for instantiated plugin SQLOperation
DatastoreAdapter dba = storeMgr.getDatastoreAdapter();
SQLOperation operation = sqlOperationsByName.get(name);
if (operation != null) {
return operation.getExpression(expr, expr2);
}
// Check for built-in SQLOperation class definition
Class sqlOpClass = dba.getSQLOperationClass(name);
if (sqlOpClass != null) {
try {
// Instantiate it
operation = (SQLOperation) sqlOpClass.getDeclaredConstructor().newInstance();
sqlOperationsByName.put(name, operation);
return operation.getExpression(expr, expr2);
} catch (Exception e) {
throw new NucleusException("Error creating SQLOperation of type " + sqlOpClass.getName() + " for operation " + name);
}
}
// Check for plugin definition of this operation for this datastore
// 1). Try datastore-dependent key
String datastoreId = dba.getVendorID();
String key = getSQLOperationKey(datastoreId, name);
boolean datastoreDependent = true;
if (!pluginSqlOperationKeysSupported.contains(key)) {
// 2). No datastore-dependent method, so try a datastore-independent key
key = getSQLOperationKey(null, name);
datastoreDependent = false;
if (!pluginSqlOperationKeysSupported.contains(key)) {
throw new UnsupportedOperationException("Operation " + name + " on datastore=" + datastoreId + " not supported");
}
}
PluginManager pluginMgr = storeMgr.getNucleusContext().getPluginManager();
String[] attrNames = (datastoreDependent ? new String[] { "name", "datastore" } : new String[] { "name" });
String[] attrValues = (datastoreDependent ? new String[] { name, datastoreId } : new String[] { name });
try {
operation = (SQLOperation) pluginMgr.createExecutableExtension("org.datanucleus.store.rdbms.sql_operation", attrNames, attrValues, "evaluator", null, null);
synchronized (operation) {
sqlOperationsByName.put(key, operation);
return operation.getExpression(expr, expr2);
}
} catch (Exception e) {
throw new NucleusUserException(Localiser.msg("060011", "operation=" + name), e);
}
}
use of org.datanucleus.exceptions.NucleusException in project datanucleus-rdbms by datanucleus.
the class ArrayIsEmptyMethod 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", "isEmpty", "ArrayExpression"));
}
SQLExpressionFactory exprFactory = stmt.getSQLExpressionFactory();
if (expr instanceof ArrayLiteral) {
Object arr = ((ArrayLiteral) expr).getValue();
boolean isEmpty = (arr == null || Array.getLength(arr) == 0);
JavaTypeMapping m = exprFactory.getMappingForType(boolean.class, false);
return new BooleanLiteral(stmt, m, isEmpty ? Boolean.TRUE : Boolean.FALSE);
}
SQLExpression sizeExpr = exprFactory.invokeMethod(stmt, "ARRAY", "size", expr, args);
JavaTypeMapping mapping = exprFactory.getMappingForType(Integer.class, true);
SQLExpression zeroExpr = exprFactory.newLiteral(stmt, mapping, 0);
return sizeExpr.eq(zeroExpr);
}
Aggregations