/* (non-Javadoc)
* @see org.datanucleus.query.evaluator.AbstractExpressionEvaluator#processPrimaryExpression(org.datanucleus.query.expression.PrimaryExpression)
*/
protected Object processPrimaryExpression(PrimaryExpression expr)
{
SQLExpression sqlExpr = null;
if (expr.getLeft() != null)
{
if (expr.getLeft() instanceof DyadicExpression && expr.getLeft().getOperator() == Expression.OP_CAST)
{
// Evaluate the cast
expr.getLeft().evaluate(this);
sqlExpr = stack.pop();
// Add the cast expression to the table mapping
Literal castLitExpr = (Literal)expr.getLeft().getRight();
AbstractClassMetaData castCmd =
ec.getMetaDataManager().getMetaDataForClass(resolveClass((String)castLitExpr.getLiteral()), clr);
String exprCastName = null;
if (expr.getLeft().getLeft() instanceof PrimaryExpression)
{
exprCastName = "CAST_" + ((PrimaryExpression)expr.getLeft().getLeft()).getId();
}
else if (expr.getLeft().getLeft() instanceof VariableExpression)
{
exprCastName = "CAST_" + ((VariableExpression)expr.getLeft().getLeft()).getId();
}
else if (expr.getLeft().getLeft() instanceof InvokeExpression)
{
exprCastName = "CAST_" + expr.getLeft().getLeft();
}
else
{
throw new NucleusException("Don't currently support cast of " + expr.getLeft().getLeft());
}
SQLTableMapping tblMapping = new SQLTableMapping(sqlExpr.getSQLTable(), castCmd, sqlExpr.getJavaTypeMapping());
setSQLTableMappingForAlias(exprCastName, tblMapping);
SQLTableMapping sqlMapping =
getSQLTableMappingForPrimaryExpression(stmt, exprCastName, expr, Boolean.FALSE);
if (sqlMapping == null)
{
throw new NucleusException("PrimaryExpression " + expr + " is not yet supported");
}
sqlExpr = exprFactory.newExpression(stmt, sqlMapping.table, sqlMapping.mapping);
stack.push(sqlExpr);
return sqlExpr;
}
else if (expr.getLeft() instanceof ParameterExpression)
{
// "{paramExpr}.field[.field[.field]]"
setNotPrecompilable(); // Need parameter values to process this
ParameterExpression paramExpr = (ParameterExpression)expr.getLeft();
Symbol paramSym = compilation.getSymbolTable().getSymbol(paramExpr.getId());
if (paramSym.getValueType() != null && paramSym.getValueType().isArray())
{
// Special case : array "methods" (particularly "length")
String first = expr.getTuples().get(0);
processParameterExpression(paramExpr, true);
SQLExpression paramSqlExpr = stack.pop();
sqlExpr = exprFactory.invokeMethod(stmt, "ARRAY", first, paramSqlExpr, null);
stack.push(sqlExpr);
return sqlExpr;
}
else
{
// Create Literal for the parameter (since we need to perform operations on it)
processParameterExpression(paramExpr, true);
SQLExpression paramSqlExpr = stack.pop();
SQLLiteral lit = (SQLLiteral)paramSqlExpr;
Object paramValue = lit.getValue();
List<String> tuples = expr.getTuples();
Iterator<String> tuplesIter = tuples.iterator();
Object objValue = paramValue;
while (tuplesIter.hasNext())
{
String fieldName = tuplesIter.next();
objValue = getValueForObjectField(objValue, fieldName);
setNotPrecompilable(); // Using literal value of parameter, so cannot precompile it
if (objValue == null)
{
break;
}
}
if (objValue == null)
{
sqlExpr = exprFactory.newLiteral(stmt, null, null);
stack.push(sqlExpr);
return sqlExpr;
}
else
{
JavaTypeMapping m = exprFactory.getMappingForType(objValue.getClass(), false);
sqlExpr = exprFactory.newLiteral(stmt, m, objValue);
stack.push(sqlExpr);
return sqlExpr;
}
}
}
else if (expr.getLeft() instanceof VariableExpression)
{
// "{varExpr}.field[.field[.field]]"
VariableExpression varExpr = (VariableExpression)expr.getLeft();
processVariableExpression(varExpr);
SQLExpression varSqlExpr = stack.pop();
if (varSqlExpr instanceof UnboundExpression)
{
// Bind as CROSS JOIN for now
processUnboundExpression((UnboundExpression)varSqlExpr);
varSqlExpr = stack.pop();
}
Class varType = clr.classForName(varSqlExpr.getJavaTypeMapping().getType());
if (varSqlExpr.getSQLStatement() == stmt.getParentStatement())
{
// Use parent mapper to get the mapping for this field since it has the table
SQLTableMapping sqlMapping =
parentMapper.getSQLTableMappingForPrimaryExpression(stmt, null, expr, Boolean.FALSE);
if (sqlMapping == null)
{
throw new NucleusException("PrimaryExpression " + expr.getId() + " is not yet supported");
}
// TODO Cater for the table required to join to not being the primary table of the outer query
// This should check on
// getDatastoreAdapter().supportsOption(RDBMSAdapter.ACCESS_PARENTQUERY_IN_SUBQUERY))
sqlExpr = exprFactory.newExpression(varSqlExpr.getSQLStatement(),
sqlMapping.table, sqlMapping.mapping);
stack.push(sqlExpr);
return sqlExpr;
}
SQLTableMapping varTblMapping = getSQLTableMappingForAlias(varExpr.getId());
if (varTblMapping == null)
{
throw new NucleusUserException("Variable " + varExpr.getId() + " is not yet bound, so cannot get field " + expr.getId());
}
if (varTblMapping.cmd == null)
{
throw new NucleusUserException("Variable " + varExpr.getId() + " of type " + varType.getName() + " cannot evaluate " + expr.getId());
}
SQLTableMapping sqlMapping =
getSQLTableMappingForPrimaryExpression(varSqlExpr.getSQLStatement(), varExpr.getId(),
expr, Boolean.FALSE);
sqlExpr = exprFactory.newExpression(sqlMapping.table.getSQLStatement(), sqlMapping.table,
sqlMapping.mapping);
stack.push(sqlExpr);
return sqlExpr;
}
else if (expr.getLeft() instanceof InvokeExpression)
{
processInvokeExpression((InvokeExpression)expr.getLeft());
SQLExpression invokeSqlExpr = stack.pop();
DatastoreContainerObject tbl = invokeSqlExpr.getSQLTable().getTable();
if (tbl instanceof DatastoreClass)
{
// Table of a class, so assume to have field in the table of the class
// TODO Allow joins to superclasses if required
if (expr.getTuples().size() > 1)
{
throw new NucleusUserException("Dont currently support evaluating " + expr.getId() +
" on " + invokeSqlExpr);
}
JavaTypeMapping mapping = ((DatastoreClass)tbl).getMemberMapping(expr.getId());
if (mapping == null)
{
throw new NucleusUserException("Dont currently support evaluating " + expr.getId() +
" on " + invokeSqlExpr +
". The field " + expr.getId() + " doesnt exist in table " + tbl);
}
sqlExpr = exprFactory.newExpression(stmt, invokeSqlExpr.getSQLTable(), mapping);
stack.push(sqlExpr);
return sqlExpr;
}
else
{