public Select evaluate(ExpContext ctx,
Select parent,
String alias,
QueryExpressions exps,
QueryExpressionsState state) {
// already know that this query is equivalent to an extent?
Select sel;
if (_extent) {
sel = ctx.store.getSQLFactory().newSelect();
sel.setAutoDistinct((exps.distinct & exps.DISTINCT_AUTO) != 0);
return sel;
}
// create a new select and initialize it with the joins needed for
// the criteria of this query
sel = newSelect(ctx, parent, alias, exps, state);
// create where clause; if there are no where conditions and
// no ordering or projections, we return null to signify that this
// query should be treated like an extent
Select inner = sel.getFromSelect();
SQLBuffer where = buildWhere((inner != null) ? inner : sel, ctx,
state.filter, exps.filter);
if (where == null && exps.projections.length == 0
&& exps.ordering.length == 0
&& (sel.getJoins() == null || sel.getJoins().isEmpty())) {
_extent = true;
sel.setAutoDistinct((exps.distinct & exps.DISTINCT_AUTO) != 0);
return sel;
}
// now set sql criteria; it goes on the inner select if present
if (inner != null)
inner.where(where);
else
sel.where(where);
// apply grouping and having. this does not select the grouping
// columns, just builds the GROUP BY clauses. we don't build the
// ORDER BY clauses yet because if we decide to add this select
// to a union, the ORDER BY values get aliased differently
if (exps.having != null) {
Exp havingExp = (Exp) exps.having;
SQLBuffer buf = new SQLBuffer(ctx.store.getDBDictionary());
havingExp.appendTo(sel, ctx, state.having, buf);
sel.having(buf);
}
for (int i = 0; i < exps.grouping.length; i++)
((Val) exps.grouping[i]).groupBy(sel, ctx, state.grouping[i]);
return sel;
}
Evaluate the expression, returning a new select and filling in any
associated expression state. Use #select to then select the data. |
public void select(Select sel,
ExpContext ctx,
ClassMapping mapping,
boolean subclasses,
QueryExpressions exps,
QueryExpressionsState state,
int eager) {
Select inner = sel.getFromSelect();
Val val;
Joins joins = null;
if (sel.getSubselectPath() != null)
joins = sel.newJoins().setSubselect(sel.getSubselectPath());
// build ordering clauses before select so that any eager join
// ordering gets applied after query ordering
for (int i = 0; i < exps.ordering.length; i++)
((Val) exps.ordering[i]).orderBy(sel, ctx, state.ordering[i],
exps.ascending[i]);
// if no result string set, select matching objects like normal
if (exps.projections.length == 0 && sel.getParent() == null) {
int subs = (subclasses) ? Select.SUBS_JOINABLE : Select.SUBS_NONE;
sel.selectIdentifier(mapping, subs, ctx.store, ctx.fetch, eager);
} else if (exps.projections.length == 0) {
// subselect for objects; we really just need the primary key values
sel.select(mapping.getPrimaryKeyColumns(), joins);
} else {
// if we have an inner select, we need to select the candidate
// class' pk columns to guarantee unique instances
if (inner != null)
inner.select(mapping.getPrimaryKeyColumns(), joins);
// select each result value; no need to pass on the eager mode since
// under projections we always use EAGER_NONE
boolean pks = sel.getParent() != null;
for (int i = 0; i < exps.projections.length; i++) {
val = (Val) exps.projections[i];
if (inner != null)
val.selectColumns(inner, ctx, state.projections[i], pks);
val.select(sel, ctx, state.projections[i], pks);
}
// make sure having columns are selected since it is required by
// some DBs. put them last so they don't affect result processing
if (exps.having != null && inner != null)
((Exp) exps.having).selectColumns(inner, ctx, state.having,
true);
}
// select ordering columns, since it is required by some DBs. put them
// last so they don't affect result processing
for (int i = 0; i < exps.ordering.length; i++) {
val = (Val) exps.ordering[i];
if (inner != null)
val.selectColumns(inner, ctx, state.ordering[i], true);
val.select(sel, ctx, state.ordering[i], true);
}
// add conditions limiting the projections to the proper classes; if
// this isn't a projection or a subq then they will already be added
if (exps.projections.length > 0 || sel.getParent() != null) {
ctx.store.loadSubclasses(mapping);
mapping.getDiscriminator().addClassConditions((inner != null)
? inner : sel, subclasses, joins);
}
}
Select the data for this query. |