PrevUpHomeNext

select()

With One Argument
With Multiple Arguments
With Multiple Arguments and a Collector Class
With group(...)
Performance Tip: Avoid Repeated Subexpressions

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:

  • Its value type is the same as exprn's result type.
  • Its value mapper is identical to exprn.
  • If 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.
  • If 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.)

Examples
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))
    ));

PrevUpHomeNext