aboutsummaryrefslogtreecommitdiff
path: root/src/include/utils/skipsupport.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/include/utils/skipsupport.h')
-rw-r--r--src/include/utils/skipsupport.h98
1 files changed, 98 insertions, 0 deletions
diff --git a/src/include/utils/skipsupport.h b/src/include/utils/skipsupport.h
new file mode 100644
index 00000000000..bc51847cf61
--- /dev/null
+++ b/src/include/utils/skipsupport.h
@@ -0,0 +1,98 @@
+/*-------------------------------------------------------------------------
+ *
+ * skipsupport.h
+ * Support routines for B-Tree skip scan.
+ *
+ * B-Tree operator classes for discrete types can optionally provide a support
+ * function for skipping. This is used during skip scans.
+ *
+ * A B-tree operator class that implements skip support provides B-tree index
+ * scans with a way of enumerating and iterating through every possible value
+ * from the domain of indexable values. This gives scans a way to determine
+ * the next value in line for a given skip array/scan key/skipped attribute.
+ * Scans request the next (or previous) value whenever they run out of tuples
+ * matching the skip array's current element value. The next (or previous)
+ * value can be used to relocate the scan; it is applied in combination with
+ * at least one additional lower-order non-skip key, taken from the query.
+ *
+ * Skip support is used by discrete type (e.g., integer and date) opclasses.
+ * Indexes with an attribute whose input opclass is of one of these types tend
+ * to store adjacent values in adjoining groups of index tuples. Each time a
+ * skip scan with skip support successfully guesses that the next value in the
+ * index (for a given skipped column) is indeed the value that skip support
+ * just incremented its skip array to, it will have saved the scan some work.
+ * The scan will have avoided an index probe that directly finds the next
+ * value that appears in the index. (When skip support guesses wrong, then it
+ * won't have saved any work, but it also won't have added any useless work.
+ * The failed attempt to locate exactly-matching index tuples acts just like
+ * an explicit probe would; it'll still find the index's true next value.)
+ *
+ * It usually isn't feasible to implement skip support for an opclass whose
+ * input type is continuous. The B-Tree code falls back on next-key sentinel
+ * values for any opclass that doesn't provide its own skip support function.
+ * This isn't really an implementation restriction; there is no benefit to
+ * providing skip support for an opclass where guessing that the next indexed
+ * value is the next possible indexable value never (or hardly ever) works out.
+ *
+ *
+ * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/utils/skipsupport.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef SKIPSUPPORT_H
+#define SKIPSUPPORT_H
+
+#include "utils/relcache.h"
+
+typedef struct SkipSupportData *SkipSupport;
+typedef Datum (*SkipSupportIncDec) (Relation rel,
+ Datum existing,
+ bool *overflow);
+
+/*
+ * State/callbacks used by skip arrays to procedurally generate elements.
+ *
+ * A BTSKIPSUPPORT_PROC function must set each and every field when called
+ * (there are no optional fields).
+ */
+typedef struct SkipSupportData
+{
+ /*
+ * low_elem and high_elem must be set with the lowest and highest possible
+ * values from the domain of indexable values (assuming ascending order)
+ */
+ Datum low_elem; /* lowest sorting/leftmost non-NULL value */
+ Datum high_elem; /* highest sorting/rightmost non-NULL value */
+
+ /*
+ * Decrement/increment functions.
+ *
+ * Returns a decremented/incremented copy of caller's existing datum,
+ * allocated in caller's memory context (for pass-by-reference types).
+ * It's not okay for these functions to leak any memory.
+ *
+ * When the decrement function (or increment function) is called with a
+ * value that already matches low_elem (or high_elem), function must set
+ * the *overflow argument. The return value is treated as undefined by
+ * the B-Tree code; it shouldn't need to be (and won't be) pfree'd.
+ *
+ * The B-Tree code's "existing" datum argument is often just a straight
+ * copy of a value from an index tuple. Operator classes must accept
+ * every possible representational variation within the underlying type.
+ * On the other hand, opclasses are _not_ required to preserve information
+ * that doesn't affect how datums are sorted (e.g., skip support for a
+ * fixed precision numeric type needn't preserve datum display scale).
+ * Operator class decrement/increment functions will never be called with
+ * a NULL "existing" argument, either.
+ */
+ SkipSupportIncDec decrement;
+ SkipSupportIncDec increment;
+} SkipSupportData;
+
+extern SkipSupport PrepareSkipSupportFromOpclass(Oid opfamily, Oid opcintype,
+ bool reverse);
+
+#endif /* SKIPSUPPORT_H */