pub struct ScalarPkProbeFastPath {
pub outer_pos: usize,
pub inner_table_name: String,
pub inner_pos: usize,
pub table_idx: usize,
}Expand description
v7.32 (R30 memory) — cheap static correlation pre-check.
subquery_replacement distinguishes a correlated subquery from an
uncorrelated one by optimistically executing it and catching the
resulting ColumnNotFound / UnknownQualifier. For a join-bodied
correlated subquery that catch fires only AFTER the inner FROM is
materialised — and the deferred-join pipeline clones the whole
driving table to do it (the inbox … JOIN messages m2 … body
clones 960k × 10 KB ≈ 10 GB at prod scale, once per outer query,
purely to be thrown away). A correlated subquery is always handled
downstream by the per-row / post-LIMIT correlated path, so spotting
it up front lets us skip the wasted materialisation entirely.
Sound for the true answer: returns true only when a qualified
column at the statement’s own level names a qualifier that is not
one of its own FROM aliases — exactly the reference the inner exec
would fail to resolve. Everything it can’t reason about cleanly
(lateral / derived FROM entries) returns false and falls through to
the existing execute-and-catch path, so behaviour is unchanged.
v7.37.x (docker-fair SCALARSQ attack) — pre-analysed plan for the
(SELECT COUNT(*) FROM T WHERE T.pk = outer.col) correlated
scalar subquery shape. Computing the table + index + position
lookups once per query (instead of once per outer row) drops the
per-row work to a single column read + index probe.
Fields§
§outer_pos: usizePosition in the OUTER scan schema for the column that drives
the equality. Per row we read row.values[outer_pos] directly.
inner_table_name: StringCatalog-qualified name of the inner table (looked up per probe).
inner_pos: usizeColumn position of the inner-side PK on which we probe.
table_idx: usizev7.37.42 (docker-fair SCALARSQ attack 1) — cached insertion-order
index of inner_table_name in the active catalog at PREPARE time.
The executor and prepare share a single engine RwLock read guard
per query (see pgwire.rs simple-query path), so the catalog
can’t mutate mid-query — the cached index stays in sync with the
string name. The per-row probe therefore skips the
BTreeMap<String, usize> descent that Catalog::get(&str) would
otherwise perform, saving ~300 ns × N outer rows.
Implementations§
Trait Implementations§
Source§impl Clone for ScalarPkProbeFastPath
impl Clone for ScalarPkProbeFastPath
Source§fn clone(&self) -> ScalarPkProbeFastPath
fn clone(&self) -> ScalarPkProbeFastPath
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read more