pub struct BoundSource {
pub id: usize,
pub rows: SourceRows,
pub table: Rc<TableInfo>,
pub alias: Vec<u8>,
pub join: JoinKind,
pub constraint: Option<BoundExpr>,
pub suppressed: Vec<u16>,
pub index_exprs: Vec<BoundIndexExprs>,
pub index_hint: IndexChoice,
}Expand description
One FROM term, bound to a table.
Fields§
§id: usizeThe statement-wide number every bound expression refers to it by.
A block’s own position in its FROM clause is not enough: a correlated subquery reads a column of a term belonging to an enclosing block, and the two numbering schemes would collide. One number per FROM term in the whole statement means a column reference is unambiguous wherever it is evaluated, and the compiler can map it to the cursor that is already open.
rows: SourceRowsWhere the rows come from.
table: Rc<TableInfo>The table, view or virtual table. The table this source reads, shared with the catalog rather than copied.
It used to be a TableInfo by value. Every table reference
in every statement therefore deep-cloned the catalog’s entry - two name
vectors, a ColumnInfo per column each with its own heap fields, the
full CREATE text, and an IndexInfo per index with its own column
vector - which measured at 2,938 ns of prepare.point’s 6,093 ns
compile, 48% of it. Every read of it still goes through Deref, so
nothing above this line had to change.
alias: Vec<u8>The name the query refers to it by.
join: JoinKindThe join that attaches it to the term before it.
constraint: Option<BoundExpr>The join constraint, already desugared from NATURAL and USING.
suppressed: Vec<u16>Columns suppressed from * by a NATURAL or USING join.
index_exprs: Vec<BoundIndexExprs>The expressions this table’s partial and expression indexes are built from, bound against this term alone.
The planner cannot bind, and the binder is the only thing that can.
An index’s predicate and its expression keys are schema text; deciding
whether a query’s WHERE implies the predicate, or whether a WHERE
names the key an index computes, is a comparison between bound
expressions. So they are bound here and carried, in a list that is empty
for every table with neither - which is every table the gate measures,
and the reason this costs a compile nothing.
They are bound against a scope holding only this term, never against the
statement’s whole FROM clause: a predicate reading b must mean this
table’s b even when another term in the query has one too. An index
whose expressions do not bind is simply left out, which leaves the
planner unable to choose it - the conservative answer, and the one that
was in force while these forms were refused outright.
index_hint: IndexChoiceINDEXED BY name or NOT INDEXED, as the FROM term wrote it.
The planner could not see this until task-2066 section 4.4.14. The
parser built it, check_index_hint checked that an INDEXED BY named a
real index, and then nothing carried it any further - so both hints were
accepted and ignored. Measured against the pinned 3.53.4 shell on a
2,000 row table with an index on each of two columns:
SELECT count(*) FROM h NOT INDEXED WHERE a = 3 AND b = 100 planned as
SCAN h there and as SEARCH h USING INDEX h_b (b=?) here.
Both are honoured now. INDEXED BY was the second half, in task-2078:
the same statement with INDEXED BY h_a planned as
SEARCH h USING INDEX h_a (a=?) there and as h_b here, and it is
held as the index’s folded name rather than as the parser’s name id
because the planner has no syntax tree to look the id up in.