For any query q, q.select(...)
builds a query whose values are extracted or computed from the values that
q would have produced. Roughly speaking, expressions
passed as arguments to select(...)
are to quince what expressions in a “select-list” are to SQL.
For any query q, you can call q.select(exprn), provided that:
exprn is an abstract_mapper<T>, for some mapped type T
(this is checked at compile time).
q's value mapper will be visible
to exprn.
q.select(exprn) returns a query
with the following characteristics:
exprn's
result type.
exprn.
exprn does not contain an aggregate
function, then q.select(exprn)'s output consists of successive
results of exprn, evaluated using each
successive record of q's output.
exprn contains an aggregate function,
then q.select(exprn) produces exactly one record, evaluated
based on the totality of q's output.
(This treatment of aggregate functions is SQL behaviour; quince just “passes it through” to the application.)
extern table<point> points; const query<point> some_points = points.where(points->y > 1.9f); extern const query<float> interesting_numbers; // Most typical cases. Each of these queries produces one float per point in points: // const query<float> xs = points.select(points->x); const query<float> products = points.select(points->x * points->y); // The exprn uses an aggregate function, so the query produces one output only: // const query<double> total = points.select(sum(points->x)); // Okay, because points's value mapper is identical to some_points's value mapper. // (Stylistically questionable though.) // const query<float> some_xs = some_points.select(points->x); // Also okay, because equivalent to the preceding example: // const query<float> some_xs_again = points .where(points->y > 1.9f) .select(points->x); // Invalid: the exprn is not an abstract_mapper: // const query<float> threes = points.select(3.0f); // wrong // Okay, although the exprn doesn't mention points's value mapper: // const query<float> threes = points.select(exprn_mapper<float>(3)); // Invalid: exprn refers to a value mapper that is not visible to it: // const query<bool> nonsense = points .select(points->x == *interesting_numbers); // wrong const query<int64_t> more_nonsense = points .select(count(points->x == *interesting_numbers)); // wrong // Okay: scalar() makes *interesting_numbers (aka the value mapper for interesting_numbers) // visible to any expression inside its subquery. // const query<int64_t> point_counts = interesting_numbers .select(scalar( points .select(count(points->x == *interesting_numbers)) ));