MCPcopy Create free account
hub / github.com/ClickHouse/ClickHouse / makePipe

Method makePipe

src/Processors/QueryPlan/ReadFromSystemPrimesStep.cpp:174–369  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

172}
173
174Pipe ReadFromSystemPrimesStep::makePipe()
175{
176 auto & primes_storage = storage->as<StorageSystemPrimes &>();
177 chassert(primes_storage.step != 0);
178
179 Pipe pipe;
180 const auto header = PrimesSource::createHeader(primes_storage.column_name);
181
182 auto add_null_source = [&] { NumbersLikeUtils::addNullSource(pipe, header); };
183
184 /// Pushdown rationale:
185 /// - Filter pushdown:
186 /// - Bounded sources (`primes(N)` / `primes(offset, length[, step])`) define a prime-index domain.
187 /// Value-space filtering is a later step; applying it during generation would change that domain and alter results.
188 /// Example: `SELECT prime FROM primes(100) WHERE prime > 1000`.
189 /// Correct behavior is to generate `primes(100)` first (the first 100 primes) and then filter, which is empty.
190 /// If we pushed `prime > 1000` into generation, we would switch to a value-domain scan and lose index-domain semantics.
191 /// - Unbounded sources (`primes()` / `system.primes`) have no bounded prime-index domain to preserve.
192 /// Therefore extracted value ranges/bounds can be applied during generation; if none are extractable, we scan normally.
193 /// Example: `SELECT prime FROM primes() WHERE prime BETWEEN 100 AND 130`.
194 /// This is equivalent to post-filtering because the source is unbounded in index space.
195 /// - LIMIT/OFFSET pushdown:
196 /// - Safe only when generated rows already satisfy WHERE (no filter, or exact extracted ranges).
197 /// Otherwise pre-filter LIMIT can cut off rows that would match later.
198 /// Example: `SELECT prime FROM system.primes WHERE prime % 10 = 1 LIMIT 5`.
199 /// If LIMIT were pushed first, we would take `[2, 3, 5, 7, 11]`, filter to `[11]`, and return too few rows.
200 /// Correct output is `[11, 31, 41, 61, 71]`.
201 /// With conservative ranges (e.g. `prime % 3 = 1 AND prime < 100`), bounds only restrict generation domain;
202 /// they do not guarantee all generated rows satisfy WHERE, so LIMIT still cannot be pushed down.
203 ///
204 /// This is the row-limit we pass down to the source.
205 /// It starts as the storage/table-function limit (`primes(N)`), and may be additionally capped
206 /// by the query LIMIT/OFFSET when it is safe to push that down.
207 std::optional<UInt64> effective_limit = primes_storage.limit;
208
209 /// Calculate how many primes the sieve must generate for `primes(offset, limit, step)`.
210 /// Total primes generated is: `offset + (limit - 1) * step + 1`
211 auto estimate_rows_to_read = [&](UInt64 num_output_rows) -> UInt64
212 {
213 if (num_output_rows == 0)
214 return 0;
215 UInt128 last_prime_index
216 = static_cast<UInt128>(primes_storage.offset) + static_cast<UInt128>(num_output_rows - 1) * primes_storage.step;
217 UInt128 total_primes_to_generate = last_prime_index + 1;
218 return static_cast<UInt64>(std::min<UInt128>(total_primes_to_generate, std::numeric_limits<UInt64>::max()));
219 };
220
221 /// Storage-level LIMIT 0 (e.g. `primes(0)`) is an empty table regardless of the WHERE clause.
222 if (effective_limit && *effective_limit == 0)
223 {
224 add_null_source();
225 return pipe;
226 }
227
228 /// Cap `effective_limit` by the query LIMIT/OFFSET, but only in paths where doing so is correct.
229 /// (The query LIMIT is applied after WHERE; pushing it into the source makes it effectively pre-filter,
230 /// so it is only safe when this source already generates only rows that satisfy the filter.)
231 auto apply_query_limit = [&] { NumbersLikeUtils::applyQueryLimit(effective_limit, limit); };

Callers

nothing calls this directly

Calls 14

addNullSourceFunction · 0.85
applyQueryLimitFunction · 0.85
rangesToIntervalsFunction · 0.85
mergeIntervalsFunction · 0.85
checkLimitsFunction · 0.85
extractRangesFunction · 0.85
isAlwaysFalseFunction · 0.85
isUniverseFunction · 0.85
maxFunction · 0.50
emptyMethod · 0.45
addTotalRowsApproxMethod · 0.45

Tested by

no test coverage detected