* @return The BooleanExpression resulting from the contains() method.
*/
public BooleanExpression containsMethod(ScalarExpression expr)
{
IdentifierFactory idFactory = qs.getStoreManager().getIdentifierFactory();
ClassLoaderResolver clr = qs.getClassLoaderResolver();
if (expr instanceof NullLiteral)
{
// JPOX doesn't currently support querying for nulls in Collections so just return "1 = 0"
// TODO Add support for querying for nulls in collections
return new BooleanLiteral(qs, mapping, false).eq(new BooleanLiteral(qs, mapping, true));
}
else if (expr instanceof UnboundVariable)
{
UnboundVariable var = (UnboundVariable)expr;
if (var.getVariableType() == null)
{
// Set the variable type to be the element type for this collection
// implicit variable type. We now set the type to the collection type
var.setVariableType(clr.classForName(collStore.getElementType()));
}
// Get the exists query of the collection table
String existsTableId = idFactory.newIdentifier(
idFactory.newIdentifier(te.getAlias(), fieldName), var.getVariableName()).getIdentifier();
DatastoreIdentifier existsTableAlias = idFactory.newIdentifier(IdentifierFactory.TABLE, existsTableId);
QueryExpression qexpr = getBackingStoreQueryable().getExistsSubquery(qs, mapping, te, existsTableAlias);
// Join from the collection table to the element table
DatastoreIdentifier elementTableAlias = null;
if (expr.te == null)
{
String elementTableId = "UNBOUND" + '.' + var.getVariableName();
elementTableAlias = idFactory.newIdentifier(IdentifierFactory.TABLE, elementTableId);
}
else
{
elementTableAlias = expr.te.getAlias();
}
ScalarExpression joinExpr = getBackingStoreQueryable().joinElementsTo(qexpr, qs, mapping, te,
existsTableAlias, var.getVariableType(), expr, elementTableAlias, true);
var.bindTo(joinExpr);
//START see JDOQLContainerTest.testContainsResultVariable
LogicSetExpression elementTblExpr = qs.getTableExpression(elementTableAlias);
if (qs.hasCrossJoin(elementTblExpr))
{
// Perhaps some description about what this is supposed to be doing and WHY ????
qexpr.andCondition(joinExpr.eq(expr.mapping.newScalarExpression(qs, elementTblExpr)));
}
//END see JDOQLContainerTest.
return new ExistsExpression(qs, qexpr, true);
}
else
{
// "contains(Literal)", "contains(Expression)"
String existsTableId = idFactory.newIdentifier(te.getAlias(), fieldName).getIdentifier();
DatastoreIdentifier existsTableAlias = idFactory.newIdentifier(IdentifierFactory.TABLE, existsTableId);
DatastoreIdentifier elementTableAlias;
if (expr.te == null) // literals
{
int n = 0;
do
{
String elementTableId = existsTableId + '.' + (++n);
elementTableAlias = idFactory.newIdentifier(IdentifierFactory.TABLE, elementTableId);
} while (qs.getTableExpression(elementTableAlias) != null);
}
else // expressions
{
elementTableAlias = expr.te.getAlias();
}
if (expr instanceof Literal)
{
// EXISTS (SELECT 1 FROM COLLECTION_TBL WHERE ...)
QueryExpression qexpr = getBackingStoreQueryable().getExistsSubquery(qs, mapping, te, existsTableAlias);
ScalarExpression joinExpr = getBackingStoreQueryable().joinElementsTo(qexpr, qs, mapping, te,
existsTableAlias, clr.classForName(expr.getMapping().getType()), expr, elementTableAlias, true);
// TODO This sometimes adds TBL1.COL1 = TBL1.COL1 - check that the equals() removes such things
if (!expr.equals(joinExpr))
{
// Join to literal value (?)
qexpr.andCondition(expr.eq(joinExpr));
}
return new ExistsExpression(qs, qexpr, true);
}
else
{
boolean existsAlways = false;
Object ext = expr.qs.getValueForExtension("org.jpox.rdbms.query.containsUsesExistsAlways");
if (ext != null && ((String)ext).equals("true"))
{
existsAlways = true;
}
if (existsAlways)
{
// EXISTS (SELECT 1 FROM COLLECTION_TBL WHERE ...)
QueryExpression qexpr = getBackingStoreQueryable().getExistsSubquery(qs, mapping, te, existsTableAlias);
ScalarExpression joinExpr = getBackingStoreQueryable().joinElementsTo(qexpr, qs, mapping, te,
existsTableAlias, clr.classForName(expr.getMapping().getType()), expr, elementTableAlias, true);
// TODO This sometimes adds TBL1.COL1 = TBL1.COL1 - check that the equals() removes such things
if (!expr.equals(joinExpr))
{
// Join to literal value (?)
qexpr.andCondition(expr.eq(joinExpr));
}
return new ExistsExpression(qs, qexpr, true);
}
else
{
// Join to element
// TODO This is WRONG - see RDBMS-94. All contains() should do "EXISTS (SELECT ... FROM ...)"
// The problem is that when using UnboundVariables that are referenced in other legs of SQL
// we need to do cross joins up at the parent query, and no mechanism is readily available yet
ScalarExpression joinExpr = getBackingStoreQueryable().joinElementsTo(
expr.getQueryExpression(), qs, mapping, te,
existsTableAlias, clr.classForName(collStore.getElementType()), expr, elementTableAlias, false);
return joinExpr.eq(expr);
}
}
}