fn collapse_unused_generate_series(
func: &mut TableFunc,
exprs: &mut Vec<MirScalarExpr>,
)Expand description
If func is an integer generate_series whose output values are unused,
rewrites it in place into a RepeatRowNonNegative that emits the same number
of rows. The caller must have established that the generated column is not
demanded.
generate_series(start, stop, step) is inclusive of stop, so its
cardinality is max(0, floor((stop - start) / step) + 1). We only rewrite
when step is a known non-zero literal, which lets us specialize on its
sign: truncating integer division (what DivInt64 does) coincides with
floor division exactly when the dividend and divisor share a sign, which the
emptiness guard guarantees. The guard also collapses the empty series to a
count of zero, so the result is always non-negative.
When start and stop are also literals, the cardinality is computed here,
exactly, in i128 (where no i64 inputs can overflow). If it does not fit
in an i64 we decline to rewrite: the original FlatMap enumerates such a
series without error (its iteration only ever visits in-range values), so
its replacement must not error either.
When the bounds are not literals we synthesize the arithmetic, and the width
we synthesize it in depends on step:
-
|step| == 1:i64, and the division (the identity or a negation) is elided, so the count is just(a - b) + 1. A literal subtracted bound is folded intoa + (1 - b)—aitself forgenerate_series(1, n). Herea - boverflowsi64only once the span reaches2^63, which means the series has more thani64::MAXrows — infeasible, exactly what the literal path declines. Soi64arithmetic is exact for every feasible series, and an overflow only ever stands in for an effectively non-terminating enumeration. -
|step| >= 2:numeric. A coarse step over near-oppositei64extremes yields a feasible series (few rows) whose span nonetheless overflowsi64, soi64arithmetic would error where the original does not.numericholds the full~2^64span comfortably and represents the quotient exactly (it needs at most ~20 significant digits, well undernumeric’s 39), so the only place this can error is the final cast back toi64— which happens exactly when the count itself exceedsi64, the same infeasible case the literal path declines.
Null inputs are handled by RepeatRowNonNegative itself: like
generate_series, it is empty_on_null_input, so a null count yields no
rows.