Skip to main content

Index

Struct Index 

Source
pub struct Index {
    pub name: String,
    pub column_position: usize,
    pub kind: IndexKind,
    pub included_columns: Vec<usize>,
    pub partial_predicate: Option<String>,
    pub expression: Option<String>,
    pub nulls_not_distinct: bool,
    pub descending: bool,
    pub nulls_first: Option<bool>,
    pub collation: Option<String>,
    pub is_unique: bool,
    pub extra_column_positions: Vec<usize>,
}
Expand description

A single-column secondary index. v2.0 carries either a B-tree map (the default — used for equality / range lookups on scalar columns) or a navigable-small-world graph (used for kNN over vector columns).

Fields§

§name: String§column_position: usize§kind: IndexKind§included_columns: Vec<usize>

v6.8.0 — column positions of INCLUDE (col1, col2, …) non-key columns. Carries the planner’s “this query is covered by the index” signal; lookup paths still resolve via the RowLocator to fetch the row body, but EXPLAIN surfaces the covered-scan annotation so operators can confirm the planner sees the coverage.

Empty Vec = no INCLUDE clause (the legacy shape). v12 catalog snapshots deserialise with an empty vec.

§partial_predicate: Option<String>

v6.8.1 — partial-index predicate stored as its canonical Display form (the engine re-parses it on the maintenance path). None = unconditional index (the legacy shape). Persisted as [u8 has_pred][u16 LE len][bytes] on the catalog snapshot (FILE_VERSION 12, appended after included_columns).

§expression: Option<String>

v6.8.2 — expression-index key, stored as the expression’s canonical Display form. None = bare column-reference index (the legacy shape). Persisted alongside partial_predicate on the v12 catalog snapshot.

§nulls_not_distinct: bool

v7.39 (read01 round 52) — CREATE UNIQUE INDEX … NULLS NOT DISTINCT (PG 15+): a NULL in the key no longer exempts the row, so two all-NULL keys collide. Default false = SQL-standard NULLS DISTINCT. Persisted in the index appendix (FILE_VERSION 62+); older catalogs deserialise with false.

§descending: bool

v7.39 (round 537) — the key column’s ordering clause, as written.

SPG’s index does not scan in a direction, so this changes no lookup; pg_indexes.indexdef is a reproduction of the DDL and dropping the clause made CREATE INDEX i ON t (a DESC NULLS LAST) read back as (a) — a dump lost it and a schema diff saw drift every run. nulls_first is None when the statement did not say, in which case PG’s default applies and neither word is rendered.

§nulls_first: Option<bool>§collation: Option<String>

v7.39 (round 538) — an explicit COLLATE on the key, as written. SPG orders text by bytes, so it changes no comparison; PG prints it because a named collation and an inherited one are different objects even where they sort identically.

§is_unique: bool

v7.9.29 — CREATE UNIQUE INDEX …. When true the engine rejects INSERTs whose key already appears in this index (combined with partial_predicate when present — only rows matching the predicate enter the uniqueness check). Catalog FILE_VERSION 16+; older snapshots deserialise with false. mailrs K1.

§extra_column_positions: Vec<usize>

v7.9.29 — extra (non-leading) column positions for multi-column indexes (CREATE INDEX … (a, b, c)). The planner today still only uses the leading column_position for index seeks, but UNIQUE INDEX enforcement walks the full tuple so partial-unique invariants like CalDAV (calendar_id, uid, recurrence_id) are enforced correctly. Catalog FILE_VERSION 16+; older snapshots deserialise empty.

Implementations§

Source§

impl Index

Source

pub fn iter_desc( &self, ) -> Box<dyn Iterator<Item = (&IndexKey, &Vec<RowLocator>)> + '_>

v7.34.4 — descending-order iterator over (IndexKey, locators) pairs for a BTree index, with O(log N) descent to the rightmost leaf and lazy emission thereafter. Returns an empty iterator for non-BTree index kinds — callers handle both uniformly. Used by the ORDER BY <indexed col> DESC + LIMIT N executor path: walking only the first N matches off the rightmost leaf avoids the per-row materialisation + partial-sort cost on large tables (mailrs content_worker at 250 k rows).

Source

pub fn iter_asc( &self, ) -> Box<dyn Iterator<Item = (&IndexKey, &Vec<RowLocator>)> + '_>

v7.34.4 — ascending-order iterator over (IndexKey, locators) pairs. Mirror of iter_desc for ORDER BY … ASC + LIMIT N.

Source

pub fn lookup_eq(&self, key: &IndexKey) -> &[RowLocator]

Look up the locators stored under key (B-tree only). Returns an empty slice when the key is absent or the index isn’t a BTree — callers can treat both cases uniformly.

v5.1: return type widened from &[usize] to &[RowLocator]. Pre-v5.2 callers can read the slice and .as_hot().unwrap() each entry (no Cold variants exist until the freezer lands); post-v5.2 callers dispatch hot vs. cold per locator.

Source

pub fn lookup_eq_i64(&self, n: i64) -> &[RowLocator]

v7.37.43 (INSUBQ B-2) — specialised lookup for integer-PK probes. try_count_star_pk_in_subquery_fast already holds an i64 (the inner survivor key); skip the IndexKey::from_value enum-dispatch trip and build the key inline. ~20 ns × N_survivors saved on the INSUBQ hot loop.

Source

pub fn lookup_range_capped( &self, lo: Bound<&IndexKey>, hi: Bound<&IndexKey>, cap: usize, ) -> Option<Vec<RowLocator>>

v7.38 (perf, index range scan) — flatten the row locators for every key in [lo, hi] (bounds per core::ops::Bound) via the BTree’s O(log N + k) range walk. Returns None once more than cap locators accumulate — a “this range isn’t selective enough, seq-scan instead” signal that stops a wide range from materialising a near-full table’s worth of rows through the index. BTree only (other kinds → None).

Source

pub fn lookup_range_capped_by( &self, lo: Bound<&IndexKey>, hi: Bound<&IndexKey>, cap: usize, keep: impl Fn(RowLocator) -> bool, ) -> Option<Vec<RowLocator>>

v7.39 (round 490) — the same range walk, but the caller decides which locators are worth carrying, and the cap counts only those.

A BTree index holds one locator per row VERSION. On a churned table the dead versions are still in there: round 490 measured a 1000-row range handing back 61 000 locators after 60 delete-and-reinsert cycles with the background vacuum switched off. Every caller then dropped the dead ones — the mutation paths and the SELECT range path all test is_row_visible and continue — but only after they had been collected into a Vec, sorted, and walked.

Handing the predicate down means the walk keeps ~1000, and the cap (which exists so an index walk never costs more than the scan it replaces) is once again measured in rows a caller will actually look at. Round 461 had to add the dead count to the budget to stop the seek being refused outright; with the filter here that compensation is no longer needed.

Source

pub fn range_keyed( &self, lo: Bound<&IndexKey>, hi: Bound<&IndexKey>, ) -> Option<impl Iterator<Item = (&IndexKey, RowLocator)> + '_>

v7.39 (round 560) — the index range as (key, locator) pairs.

lookup_range_capped_by throws the KEY away and returns only locators, so a query whose projection is exactly the indexed column still goes to the row store for a value the walk already had in hand — paying per row for something the index knows.

Uncapped on purpose: an index-only walk touches no row, so the selectivity ceiling that keeps a seek from being worse than the scan it replaces does not apply to it.

v7.39 (round 562) — and it does not collect, either. This returned a Vec<(IndexKey, RowLocator)>: for a 100k-row range, 100k key clones into a Vec::new() that doubles its way up to several MB, all to be walked once and dropped. A profile of the server serving that query put 20% of the connection thread’s CPU on the collect alone, with another 18% in the allocator beside it. The caller consumes the pairs in order and needs the key only by reference, so it can have the walk itself.

Source

pub fn gin_lookup_word(&self, word: &str) -> &[RowLocator]

v7.12.3 — GIN posting-list lookup. Returns the row locators whose tsvector cell contains word. Empty when the word is absent from the index or this isn’t a GIN index.

Source

pub fn gin_trgm_lookup(&self, tri: &str) -> &[RowLocator]

v7.15.0 — trigram-GIN posting-list lookup. Returns the row locators whose indexed TEXT cell contains the trigram tri. Empty when the trigram is absent or this isn’t a trigram-GIN index.

Source

pub fn gin_jsonb_lookup(&self, token: &str) -> &[RowLocator]

v7.37.8(sentori Epic 5 P2)— JSONB-GIN posting-list lookup. Returns the row locators whose indexed JSONB cell carries the canonical token(see crate::jsonb_gin::extract_tokens). Empty when the token is absent or this isn’t a JSONB-GIN index. Planners drive <col> @> <jsonb_literal> through here.

Source

pub const fn nsw(&self) -> Option<&NswGraph>

Borrow the NSW graph (if this is an NSW index). Callers that need the graph for a kNN search go through here.

Source

pub const fn is_brin(&self) -> bool

v6.7.1 — true when this index is a BRIN (block range) index. Used by the segment encoder to opt into BRIN sidecar emission at freeze time, and by the planner to opt into page-skipping on range predicates.

Source

pub const fn is_gin_trgm(&self) -> bool

v7.15.0 — true when this index is a trigram GIN (gin_trgm_ops-flavoured). Used by the LIKE planner to opt into trigram acceleration.

Source

pub const fn is_gin(&self) -> bool

v7.12.3 — true when this index is a GIN inverted index. Used by the planner to opt into posting-list acceleration on WHERE col @@ tsquery predicates.

Source

pub const fn is_gin_fulltext(&self) -> bool

v7.17.0 Phase 2.2 — true when this index is a fulltext GIN over a TEXT / VARCHAR column (MySQL FULLTEXT KEY surface). Used by the planner to opt the FULLTEXT-indexed column into MATCH AGAINST acceleration.

Source

pub const fn is_gin_jsonb(&self) -> bool

v7.37.8(sentori Epic 5 P2)— true when this index is a real JSONB-GIN(posting-list backed). Used by the planner to opt <col> @> <jsonb_literal> into posting-list seek.

Trait Implementations§

Source§

impl Clone for Index

Source§

fn clone(&self) -> Index

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for Index

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl Freeze for Index

§

impl RefUnwindSafe for Index

§

impl Send for Index

§

impl Sync for Index

§

impl Unpin for Index

§

impl UnsafeUnpin for Index

§

impl UnwindSafe for Index

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.