Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
spgist-extensibility.html621 linesDownload Raw Back to html
1<?xml version="1.0" encoding="UTF-8" standalone="no"?>2<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>69.3. Extensibility</title><link rel="stylesheet" type="text/css" href="stylesheet.css" /><link rev="made" href="pgsql-docs@lists.postgresql.org" /><meta name="generator" content="DocBook XSL Stylesheets Vsnapshot" /><link rel="prev" href="spgist-builtin-opclasses.html" title="69.2. Built-in Operator Classes" /><link rel="next" href="spgist-implementation.html" title="69.4. Implementation" /></head><body id="docContent" class="container-fluid col-10"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="5" align="center">69.3. Extensibility</th></tr><tr><td width="10%" align="left"><a accesskey="p" href="spgist-builtin-opclasses.html" title="69.2. Built-in Operator Classes">Prev</a> </td><td width="10%" align="left"><a accesskey="u" href="spgist.html" title="Chapter 69. SP-GiST Indexes">Up</a></td><th width="60%" align="center">Chapter 69. SP-GiST Indexes</th><td width="10%" align="right"><a accesskey="h" href="index.html" title="PostgreSQL 16.3 Documentation">Home</a></td><td width="10%" align="right"> <a accesskey="n" href="spgist-implementation.html" title="69.4. Implementation">Next</a></td></tr></table><hr /></div><div class="sect1" id="SPGIST-EXTENSIBILITY"><div class="titlepage"><div><div><h2 class="title" style="clear: both">69.3. Extensibility <a href="#SPGIST-EXTENSIBILITY" class="id_link">#</a></h2></div></div></div><p>3  <acronym class="acronym">SP-GiST</acronym> offers an interface with a high level of4  abstraction, requiring the access method developer to implement only5  methods specific to a given data type. The <acronym class="acronym">SP-GiST</acronym> core6  is responsible for efficient disk mapping and searching the tree structure.7  It also takes care of concurrency and logging considerations.8 </p><p>9  Leaf tuples of an <acronym class="acronym">SP-GiST</acronym> tree usually contain values10  of the same data type as the indexed column, although it is also possible11  for them to contain lossy representations of the indexed column.12  Leaf tuples stored at the root level will directly represent13  the original indexed data value, but leaf tuples at lower14  levels might contain only a partial value, such as a suffix.15  In that case the operator class support functions must be able to16  reconstruct the original value using information accumulated from the17  inner tuples that are passed through to reach the leaf level.18 </p><p>19  When an <acronym class="acronym">SP-GiST</acronym> index is created with20  <code class="literal">INCLUDE</code> columns, the values of those columns are also21  stored in leaf tuples.  The <code class="literal">INCLUDE</code> columns are of no22  concern to the <acronym class="acronym">SP-GiST</acronym> operator class, so they are23  not discussed further here.24 </p><p>25  Inner tuples are more complex, since they are branching points in the26  search tree.  Each inner tuple contains a set of one or more27  <em class="firstterm">nodes</em>, which represent groups of similar leaf values.28  A node contains a downlink that leads either to another, lower-level inner29  tuple, or to a short list of leaf tuples that all lie on the same index page.30  Each node normally has a <em class="firstterm">label</em> that describes it; for example,31  in a radix tree the node label could be the next character of the string32  value.  (Alternatively, an operator class can omit the node labels, if it33  works with a fixed set of nodes for all inner tuples;34  see <a class="xref" href="spgist-implementation.html#SPGIST-NULL-LABELS" title="69.4.2. SP-GiST Without Node Labels">Section 69.4.2</a>.)35  Optionally, an inner tuple can have a <em class="firstterm">prefix</em> value36  that describes all its members.  In a radix tree this could be the common37  prefix of the represented strings.  The prefix value is not necessarily38  really a prefix, but can be any data needed by the operator class;39  for example, in a quad-tree it can store the central point that the four40  quadrants are measured with respect to.  A quad-tree inner tuple would41  then also contain four nodes corresponding to the quadrants around this42  central point.43 </p><p>44  Some tree algorithms require knowledge of level (or depth) of the current45  tuple, so the <acronym class="acronym">SP-GiST</acronym> core provides the possibility for46  operator classes to manage level counting while descending the tree.47  There is also support for incrementally reconstructing the represented48  value when that is needed, and for passing down additional data (called49  <em class="firstterm">traverse values</em>) during a tree descent.50 </p><div class="note"><h3 class="title">Note</h3><p>51   The <acronym class="acronym">SP-GiST</acronym> core code takes care of null entries.52   Although <acronym class="acronym">SP-GiST</acronym> indexes do store entries for nulls53   in indexed columns, this is hidden from the index operator class code:54   no null index entries or search conditions will ever be passed to the55   operator class methods.  (It is assumed that <acronym class="acronym">SP-GiST</acronym>56   operators are strict and so cannot succeed for null values.)  Null values57   are therefore not discussed further here.58  </p></div><p>59  There are five user-defined methods that an index operator class for60  <acronym class="acronym">SP-GiST</acronym> must provide, and two are optional.  All five61  mandatory methods follow the convention of accepting two <code class="type">internal</code>62  arguments, the first of which is a pointer to a C struct containing input63  values for the support method, while the second argument is a pointer to a64  C struct where output values must be placed.  Four of the mandatory methods just65  return <code class="type">void</code>, since all their results appear in the output struct; but66  <code class="function">leaf_consistent</code> returns a <code class="type">boolean</code> result.67  The methods must not modify any fields of their input structs.  In all68  cases, the output struct is initialized to zeroes before calling the69  user-defined method.  The optional sixth method <code class="function">compress</code>70  accepts a <code class="type">datum</code> to be indexed as the only argument and returns a value suitable71  for physical storage in a leaf tuple.  The optional seventh method72  <code class="function">options</code> accepts an <code class="type">internal</code> pointer to a C struct, where73  opclass-specific parameters should be placed, and returns <code class="type">void</code>.74 </p><p>75  The five mandatory user-defined methods are:76 </p><div class="variablelist"><dl class="variablelist"><dt><span class="term"><code class="function">config</code></span></dt><dd><p>77       Returns static information about the index implementation, including78       the data type OIDs of the prefix and node label data types.79      </p><p>80      The <acronym class="acronym">SQL</acronym> declaration of the function must look like this:81</p><pre class="programlisting">82CREATE FUNCTION my_config(internal, internal) RETURNS void ...83</pre><p>84      The first argument is a pointer to a <code class="structname">spgConfigIn</code>85      C struct, containing input data for the function.86      The second argument is a pointer to a <code class="structname">spgConfigOut</code>87      C struct, which the function must fill with result data.88</p><pre class="programlisting">89typedef struct spgConfigIn90{91    Oid         attType;        /* Data type to be indexed */92} spgConfigIn;93 94typedef struct spgConfigOut95{96    Oid         prefixType;     /* Data type of inner-tuple prefixes */97    Oid         labelType;      /* Data type of inner-tuple node labels */98    Oid         leafType;       /* Data type of leaf-tuple values */99    bool        canReturnData;  /* Opclass can reconstruct original data */100    bool        longValuesOK;   /* Opclass can cope with values &gt; 1 page */101} spgConfigOut;102</pre><p>103 104      <code class="structfield">attType</code> is passed in order to support polymorphic105      index operator classes; for ordinary fixed-data-type operator classes, it106      will always have the same value and so can be ignored.107     </p><p>108      For operator classes that do not use prefixes,109      <code class="structfield">prefixType</code> can be set to <code class="literal">VOIDOID</code>.110      Likewise, for operator classes that do not use node labels,111      <code class="structfield">labelType</code> can be set to <code class="literal">VOIDOID</code>.112      <code class="structfield">canReturnData</code> should be set true if the operator class113      is capable of reconstructing the originally-supplied index value.114      <code class="structfield">longValuesOK</code> should be set true only when the115      <code class="structfield">attType</code> is of variable length and the operator116      class is capable of segmenting long values by repeated suffixing117      (see <a class="xref" href="spgist-implementation.html#SPGIST-LIMITS" title="69.4.1. SP-GiST Limits">Section 69.4.1</a>).118     </p><p>119      <code class="structfield">leafType</code> should match the index storage type120      defined by the operator class's <code class="structfield">opckeytype</code>121      catalog entry.122      (Note that <code class="structfield">opckeytype</code> can be zero,123      implying the storage type is the same as the operator class's input124      type, which is the most common situation.)125      For reasons of backward compatibility, the <code class="function">config</code>126      method can set <code class="structfield">leafType</code> to some other value,127      and that value will be used; but this is deprecated since the index128      contents are then incorrectly identified in the catalogs.129      Also, it's permissible to130      leave <code class="structfield">leafType</code> uninitialized (zero);131      that is interpreted as meaning the index storage type derived from132      <code class="structfield">opckeytype</code>.133     </p><p>134      When <code class="structfield">attType</code>135      and <code class="structfield">leafType</code> are different, the optional136      method <code class="function">compress</code> must be provided.137      Method <code class="function">compress</code> is responsible138      for transformation of datums to be indexed from <code class="structfield">attType</code>139      to <code class="structfield">leafType</code>.140     </p></dd><dt><span class="term"><code class="function">choose</code></span></dt><dd><p>141        Chooses a method for inserting a new value into an inner tuple.142      </p><p>143      The <acronym class="acronym">SQL</acronym> declaration of the function must look like this:144</p><pre class="programlisting">145CREATE FUNCTION my_choose(internal, internal) RETURNS void ...146</pre><p>147      The first argument is a pointer to a <code class="structname">spgChooseIn</code>148      C struct, containing input data for the function.149      The second argument is a pointer to a <code class="structname">spgChooseOut</code>150      C struct, which the function must fill with result data.151</p><pre class="programlisting">152typedef struct spgChooseIn153{154    Datum       datum;          /* original datum to be indexed */155    Datum       leafDatum;      /* current datum to be stored at leaf */156    int         level;          /* current level (counting from zero) */157 158    /* Data from current inner tuple */159    bool        allTheSame;     /* tuple is marked all-the-same? */160    bool        hasPrefix;      /* tuple has a prefix? */161    Datum       prefixDatum;    /* if so, the prefix value */162    int         nNodes;         /* number of nodes in the inner tuple */163    Datum      *nodeLabels;     /* node label values (NULL if none) */164} spgChooseIn;165 166typedef enum spgChooseResultType167{168    spgMatchNode = 1,           /* descend into existing node */169    spgAddNode,                 /* add a node to the inner tuple */170    spgSplitTuple               /* split inner tuple (change its prefix) */171} spgChooseResultType;172 173typedef struct spgChooseOut174{175    spgChooseResultType resultType;     /* action code, see above */176    union177    {178        struct                  /* results for spgMatchNode */179        {180            int         nodeN;      /* descend to this node (index from 0) */181            int         levelAdd;   /* increment level by this much */182            Datum       restDatum;  /* new leaf datum */183        }           matchNode;184        struct                  /* results for spgAddNode */185        {186            Datum       nodeLabel;  /* new node's label */187            int         nodeN;      /* where to insert it (index from 0) */188        }           addNode;189        struct                  /* results for spgSplitTuple */190        {191            /* Info to form new upper-level inner tuple with one child tuple */192            bool        prefixHasPrefix;    /* tuple should have a prefix? */193            Datum       prefixPrefixDatum;  /* if so, its value */194            int         prefixNNodes;       /* number of nodes */195            Datum      *prefixNodeLabels;   /* their labels (or NULL for196                                             * no labels) */197            int         childNodeN;         /* which node gets child tuple */198 199            /* Info to form new lower-level inner tuple with all old nodes */200            bool        postfixHasPrefix;   /* tuple should have a prefix? */201            Datum       postfixPrefixDatum; /* if so, its value */202        }           splitTuple;203    }           result;204} spgChooseOut;205</pre><p>206 207       <code class="structfield">datum</code> is the original datum of208       <code class="structname">spgConfigIn</code>.<code class="structfield">attType</code>209       type that was to be inserted into the index.210       <code class="structfield">leafDatum</code> is a value of211       <code class="structname">spgConfigOut</code>.<code class="structfield">leafType</code>212       type, which is initially a result of method213       <code class="function">compress</code> applied to <code class="structfield">datum</code>214       when method <code class="function">compress</code> is provided, or the same value as215       <code class="structfield">datum</code> otherwise.216       <code class="structfield">leafDatum</code> can change at lower levels of the tree217       if the <code class="function">choose</code> or <code class="function">picksplit</code>218       methods change it.  When the insertion search reaches a leaf page,219       the current value of <code class="structfield">leafDatum</code> is what will be stored220       in the newly created leaf tuple.221       <code class="structfield">level</code> is the current inner tuple's level, starting at222       zero for the root level.223       <code class="structfield">allTheSame</code> is true if the current inner tuple is224       marked as containing multiple equivalent nodes225       (see <a class="xref" href="spgist-implementation.html#SPGIST-ALL-THE-SAME" title="69.4.3. “All-the-Same” Inner Tuples">Section 69.4.3</a>).226       <code class="structfield">hasPrefix</code> is true if the current inner tuple contains227       a prefix; if so,228       <code class="structfield">prefixDatum</code> is its value.229       <code class="structfield">nNodes</code> is the number of child nodes contained in the230       inner tuple, and231       <code class="structfield">nodeLabels</code> is an array of their label values, or232       NULL if there are no labels.233      </p><p>234       The <code class="function">choose</code> function can determine either that235       the new value matches one of the existing child nodes, or that a new236       child node must be added, or that the new value is inconsistent with237       the tuple prefix and so the inner tuple must be split to create a238       less restrictive prefix.239      </p><p>240       If the new value matches one of the existing child nodes,241       set <code class="structfield">resultType</code> to <code class="literal">spgMatchNode</code>.242       Set <code class="structfield">nodeN</code> to the index (from zero) of that node in243       the node array.244       Set <code class="structfield">levelAdd</code> to the increment in245       <code class="structfield">level</code> caused by descending through that node,246       or leave it as zero if the operator class does not use levels.247       Set <code class="structfield">restDatum</code> to equal <code class="structfield">leafDatum</code>248       if the operator class does not modify datums from one level to the249       next, or otherwise set it to the modified value to be used as250       <code class="structfield">leafDatum</code> at the next level.251      </p><p>252       If a new child node must be added,253       set <code class="structfield">resultType</code> to <code class="literal">spgAddNode</code>.254       Set <code class="structfield">nodeLabel</code> to the label to be used for the new255       node, and set <code class="structfield">nodeN</code> to the index (from zero) at which256       to insert the node in the node array.257       After the node has been added, the <code class="function">choose</code>258       function will be called again with the modified inner tuple;259       that call should result in an <code class="literal">spgMatchNode</code> result.260      </p><p>261       If the new value is inconsistent with the tuple prefix,262       set <code class="structfield">resultType</code> to <code class="literal">spgSplitTuple</code>.263       This action moves all the existing nodes into a new lower-level264       inner tuple, and replaces the existing inner tuple with a tuple265       having a single downlink pointing to the new lower-level inner tuple.266       Set <code class="structfield">prefixHasPrefix</code> to indicate whether the new267       upper tuple should have a prefix, and if so set268       <code class="structfield">prefixPrefixDatum</code> to the prefix value.  This new269       prefix value must be sufficiently less restrictive than the original270       to accept the new value to be indexed.271       Set <code class="structfield">prefixNNodes</code> to the number of nodes needed in the272       new tuple, and set <code class="structfield">prefixNodeLabels</code> to a palloc'd array273       holding their labels, or to NULL if node labels are not required.274       Note that the total size of the new upper tuple must be no more275       than the total size of the tuple it is replacing; this constrains276       the lengths of the new prefix and new labels.277       Set <code class="structfield">childNodeN</code> to the index (from zero) of the node278       that will downlink to the new lower-level inner tuple.279       Set <code class="structfield">postfixHasPrefix</code> to indicate whether the new280       lower-level inner tuple should have a prefix, and if so set281       <code class="structfield">postfixPrefixDatum</code> to the prefix value.  The282       combination of these two prefixes and the downlink node's label283       (if any) must have the same meaning as the original prefix, because284       there is no opportunity to alter the node labels that are moved to285       the new lower-level tuple, nor to change any child index entries.286       After the node has been split, the <code class="function">choose</code>287       function will be called again with the replacement inner tuple.288       That call may return an <code class="literal">spgAddNode</code> result, if no suitable289       node was created by the <code class="literal">spgSplitTuple</code> action.  Eventually290       <code class="function">choose</code> must return <code class="literal">spgMatchNode</code> to291       allow the insertion to descend to the next level.292      </p></dd><dt><span class="term"><code class="function">picksplit</code></span></dt><dd><p>293       Decides how to create a new inner tuple over a set of leaf tuples.294      </p><p>295        The <acronym class="acronym">SQL</acronym> declaration of the function must look like this:296</p><pre class="programlisting">297CREATE FUNCTION my_picksplit(internal, internal) RETURNS void ...298</pre><p>299      The first argument is a pointer to a <code class="structname">spgPickSplitIn</code>300      C struct, containing input data for the function.301      The second argument is a pointer to a <code class="structname">spgPickSplitOut</code>302      C struct, which the function must fill with result data.303</p><pre class="programlisting">304typedef struct spgPickSplitIn305{306    int         nTuples;        /* number of leaf tuples */307    Datum      *datums;         /* their datums (array of length nTuples) */308    int         level;          /* current level (counting from zero) */309} spgPickSplitIn;310 311typedef struct spgPickSplitOut312{313    bool        hasPrefix;      /* new inner tuple should have a prefix? */314    Datum       prefixDatum;    /* if so, its value */315 316    int         nNodes;         /* number of nodes for new inner tuple */317    Datum      *nodeLabels;     /* their labels (or NULL for no labels) */318 319    int        *mapTuplesToNodes;   /* node index for each leaf tuple */320    Datum      *leafTupleDatums;    /* datum to store in each new leaf tuple */321} spgPickSplitOut;322</pre><p>323 324       <code class="structfield">nTuples</code> is the number of leaf tuples provided.325       <code class="structfield">datums</code> is an array of their datum values of326       <code class="structname">spgConfigOut</code>.<code class="structfield">leafType</code>327       type.328       <code class="structfield">level</code> is the current level that all the leaf tuples329       share, which will become the level of the new inner tuple.330      </p><p>331       Set <code class="structfield">hasPrefix</code> to indicate whether the new inner332       tuple should have a prefix, and if so set333       <code class="structfield">prefixDatum</code> to the prefix value.334       Set <code class="structfield">nNodes</code> to indicate the number of nodes that335       the new inner tuple will contain, and336       set <code class="structfield">nodeLabels</code> to an array of their label values,337       or to NULL if node labels are not required.338       Set <code class="structfield">mapTuplesToNodes</code> to an array that gives the index339       (from zero) of the node that each leaf tuple should be assigned to.340       Set <code class="structfield">leafTupleDatums</code> to an array of the values to341       be stored in the new leaf tuples (these will be the same as the342       input <code class="structfield">datums</code> if the operator class does not modify343       datums from one level to the next).344       Note that the <code class="function">picksplit</code> function is345       responsible for palloc'ing the346       <code class="structfield">nodeLabels</code>, <code class="structfield">mapTuplesToNodes</code> and347       <code class="structfield">leafTupleDatums</code> arrays.348      </p><p>349       If more than one leaf tuple is supplied, it is expected that the350       <code class="function">picksplit</code> function will classify them into more than351       one node; otherwise it is not possible to split the leaf tuples352       across multiple pages, which is the ultimate purpose of this353       operation.  Therefore, if the <code class="function">picksplit</code> function354       ends up placing all the leaf tuples in the same node, the core355       SP-GiST code will override that decision and generate an inner356       tuple in which the leaf tuples are assigned at random to several357       identically-labeled nodes.  Such a tuple is marked358       <code class="literal">allTheSame</code> to signify that this has happened.  The359       <code class="function">choose</code> and <code class="function">inner_consistent</code> functions360       must take suitable care with such inner tuples.361       See <a class="xref" href="spgist-implementation.html#SPGIST-ALL-THE-SAME" title="69.4.3. “All-the-Same” Inner Tuples">Section 69.4.3</a> for more information.362      </p><p>363       <code class="function">picksplit</code> can be applied to a single leaf tuple only364       in the case that the <code class="function">config</code> function set365       <code class="structfield">longValuesOK</code> to true and a larger-than-a-page input366       value has been supplied.  In this case the point of the operation is367       to strip off a prefix and produce a new, shorter leaf datum value.368       The call will be repeated until a leaf datum short enough to fit on369       a page has been produced.  See <a class="xref" href="spgist-implementation.html#SPGIST-LIMITS" title="69.4.1. SP-GiST Limits">Section 69.4.1</a> for370       more information.371      </p></dd><dt><span class="term"><code class="function">inner_consistent</code></span></dt><dd><p>372       Returns set of nodes (branches) to follow during tree search.373      </p><p>374       The <acronym class="acronym">SQL</acronym> declaration of the function must look like this:375</p><pre class="programlisting">376CREATE FUNCTION my_inner_consistent(internal, internal) RETURNS void ...377</pre><p>378      The first argument is a pointer to a <code class="structname">spgInnerConsistentIn</code>379      C struct, containing input data for the function.380      The second argument is a pointer to a <code class="structname">spgInnerConsistentOut</code>381      C struct, which the function must fill with result data.382 383</p><pre class="programlisting">384typedef struct spgInnerConsistentIn385{386    ScanKey     scankeys;       /* array of operators and comparison values */387    ScanKey     orderbys;       /* array of ordering operators and comparison388                                 * values */389    int         nkeys;          /* length of scankeys array */390    int         norderbys;      /* length of orderbys array */391 392    Datum       reconstructedValue;     /* value reconstructed at parent */393    void       *traversalValue; /* opclass-specific traverse value */394    MemoryContext traversalMemoryContext;   /* put new traverse values here */395    int         level;          /* current level (counting from zero) */396    bool        returnData;     /* original data must be returned? */397 398    /* Data from current inner tuple */399    bool        allTheSame;     /* tuple is marked all-the-same? */400    bool        hasPrefix;      /* tuple has a prefix? */401    Datum       prefixDatum;    /* if so, the prefix value */402    int         nNodes;         /* number of nodes in the inner tuple */403    Datum      *nodeLabels;     /* node label values (NULL if none) */404} spgInnerConsistentIn;405 406typedef struct spgInnerConsistentOut407{408    int         nNodes;         /* number of child nodes to be visited */409    int        *nodeNumbers;    /* their indexes in the node array */410    int        *levelAdds;      /* increment level by this much for each */411    Datum      *reconstructedValues;    /* associated reconstructed values */412    void      **traversalValues;        /* opclass-specific traverse values */413    double    **distances;              /* associated distances */414} spgInnerConsistentOut;415</pre><p>416 417       The array <code class="structfield">scankeys</code>, of length <code class="structfield">nkeys</code>,418       describes the index search condition(s).  These conditions are419       combined with AND — only index entries that satisfy all of420       them are interesting.  (Note that <code class="structfield">nkeys</code> = 0 implies421       that all index entries satisfy the query.)  Usually the consistent422       function only cares about the <code class="structfield">sk_strategy</code> and423       <code class="structfield">sk_argument</code> fields of each array entry, which424       respectively give the indexable operator and comparison value.425       In particular it is not necessary to check <code class="structfield">sk_flags</code> to426       see if the comparison value is NULL, because the SP-GiST core code427       will filter out such conditions.428       The array <code class="structfield">orderbys</code>, of length <code class="structfield">norderbys</code>,429       describes ordering operators (if any) in the same manner.430       <code class="structfield">reconstructedValue</code> is the value reconstructed for the431       parent tuple; it is <code class="literal">(Datum) 0</code> at the root level or if the432       <code class="function">inner_consistent</code> function did not provide a value at the433       parent level.434       <code class="structfield">traversalValue</code> is a pointer to any traverse data435       passed down from the previous call of <code class="function">inner_consistent</code>436       on the parent index tuple, or NULL at the root level.437       <code class="structfield">traversalMemoryContext</code> is the memory context in which438       to store output traverse values (see below).439       <code class="structfield">level</code> is the current inner tuple's level, starting at440       zero for the root level.441       <code class="structfield">returnData</code> is <code class="literal">true</code> if reconstructed data is442       required for this query; this will only be so if the443       <code class="function">config</code> function asserted <code class="structfield">canReturnData</code>.444       <code class="structfield">allTheSame</code> is true if the current inner tuple is445       marked <span class="quote">“<span class="quote">all-the-same</span>”</span>; in this case all the nodes have the446       same label (if any) and so either all or none of them match the query447       (see <a class="xref" href="spgist-implementation.html#SPGIST-ALL-THE-SAME" title="69.4.3. “All-the-Same” Inner Tuples">Section 69.4.3</a>).448       <code class="structfield">hasPrefix</code> is true if the current inner tuple contains449       a prefix; if so,450       <code class="structfield">prefixDatum</code> is its value.451       <code class="structfield">nNodes</code> is the number of child nodes contained in the452       inner tuple, and453       <code class="structfield">nodeLabels</code> is an array of their label values, or454       NULL if the nodes do not have labels.455      </p><p>456       <code class="structfield">nNodes</code> must be set to the number of child nodes that457       need to be visited by the search, and458       <code class="structfield">nodeNumbers</code> must be set to an array of their indexes.459       If the operator class keeps track of levels, set460       <code class="structfield">levelAdds</code> to an array of the level increments461       required when descending to each node to be visited.  (Often these462       increments will be the same for all the nodes, but that's not463       necessarily so, so an array is used.)464       If value reconstruction is needed, set465       <code class="structfield">reconstructedValues</code> to an array of the values466       reconstructed for each child node to be visited; otherwise, leave467       <code class="structfield">reconstructedValues</code> as NULL.468       The reconstructed values are assumed to be of type469       <code class="structname">spgConfigOut</code>.<code class="structfield">leafType</code>.470       (However, since the core system will do nothing with them except471       possibly copy them, it is sufficient for them to have the472       same <code class="literal">typlen</code> and <code class="literal">typbyval</code>473       properties as <code class="structfield">leafType</code>.)474       If ordered search is performed, set <code class="structfield">distances</code>475       to an array of distance values according to <code class="structfield">orderbys</code>476       array (nodes with lowest distances will be processed first).  Leave it477       NULL otherwise.478       If it is desired to pass down additional out-of-band information479       (<span class="quote">“<span class="quote">traverse values</span>”</span>) to lower levels of the tree search,480       set <code class="structfield">traversalValues</code> to an array of the appropriate481       traverse values, one for each child node to be visited; otherwise,482       leave <code class="structfield">traversalValues</code> as NULL.483       Note that the <code class="function">inner_consistent</code> function is484       responsible for palloc'ing the485       <code class="structfield">nodeNumbers</code>, <code class="structfield">levelAdds</code>,486       <code class="structfield">distances</code>,487       <code class="structfield">reconstructedValues</code>, and488       <code class="structfield">traversalValues</code> arrays in the current memory context.489       However, any output traverse values pointed to by490       the <code class="structfield">traversalValues</code> array should be allocated491       in <code class="structfield">traversalMemoryContext</code>.492       Each traverse value must be a single palloc'd chunk.493      </p></dd><dt><span class="term"><code class="function">leaf_consistent</code></span></dt><dd><p>494       Returns true if a leaf tuple satisfies a query.495      </p><p>496       The <acronym class="acronym">SQL</acronym> declaration of the function must look like this:497</p><pre class="programlisting">498CREATE FUNCTION my_leaf_consistent(internal, internal) RETURNS bool ...499</pre><p>500      The first argument is a pointer to a <code class="structname">spgLeafConsistentIn</code>501      C struct, containing input data for the function.502      The second argument is a pointer to a <code class="structname">spgLeafConsistentOut</code>503      C struct, which the function must fill with result data.504</p><pre class="programlisting">505typedef struct spgLeafConsistentIn506{507    ScanKey     scankeys;       /* array of operators and comparison values */508    ScanKey     orderbys;       /* array of ordering operators and comparison509                                 * values */510    int         nkeys;          /* length of scankeys array */511    int         norderbys;      /* length of orderbys array */512 513    Datum       reconstructedValue;     /* value reconstructed at parent */514    void       *traversalValue; /* opclass-specific traverse value */515    int         level;          /* current level (counting from zero) */516    bool        returnData;     /* original data must be returned? */517 518    Datum       leafDatum;      /* datum in leaf tuple */519} spgLeafConsistentIn;520 521typedef struct spgLeafConsistentOut522{523    Datum       leafValue;        /* reconstructed original data, if any */524    bool        recheck;          /* set true if operator must be rechecked */525    bool        recheckDistances; /* set true if distances must be rechecked */526    double     *distances;        /* associated distances */527} spgLeafConsistentOut;528</pre><p>529 530       The array <code class="structfield">scankeys</code>, of length <code class="structfield">nkeys</code>,531       describes the index search condition(s).  These conditions are532       combined with AND — only index entries that satisfy all of533       them satisfy the query.  (Note that <code class="structfield">nkeys</code> = 0 implies534       that all index entries satisfy the query.)  Usually the consistent535       function only cares about the <code class="structfield">sk_strategy</code> and536       <code class="structfield">sk_argument</code> fields of each array entry, which537       respectively give the indexable operator and comparison value.538       In particular it is not necessary to check <code class="structfield">sk_flags</code> to539       see if the comparison value is NULL, because the SP-GiST core code540       will filter out such conditions.541       The array <code class="structfield">orderbys</code>, of length <code class="structfield">norderbys</code>,542       describes the ordering operators in the same manner.543       <code class="structfield">reconstructedValue</code> is the value reconstructed for the544       parent tuple; it is <code class="literal">(Datum) 0</code> at the root level or if the545       <code class="function">inner_consistent</code> function did not provide a value at the546       parent level.547       <code class="structfield">traversalValue</code> is a pointer to any traverse data548       passed down from the previous call of <code class="function">inner_consistent</code>549       on the parent index tuple, or NULL at the root level.550       <code class="structfield">level</code> is the current leaf tuple's level, starting at551       zero for the root level.552       <code class="structfield">returnData</code> is <code class="literal">true</code> if reconstructed data is553       required for this query; this will only be so if the554       <code class="function">config</code> function asserted <code class="structfield">canReturnData</code>.555       <code class="structfield">leafDatum</code> is the key value of556       <code class="structname">spgConfigOut</code>.<code class="structfield">leafType</code>557       stored in the current leaf tuple.558      </p><p>559       The function must return <code class="literal">true</code> if the leaf tuple matches the560       query, or <code class="literal">false</code> if not.  In the <code class="literal">true</code> case,561       if <code class="structfield">returnData</code> is <code class="literal">true</code> then562       <code class="structfield">leafValue</code> must be set to the value (of type563       <code class="structname">spgConfigIn</code>.<code class="structfield">attType</code>)564       originally supplied to be indexed for this leaf tuple.  Also,565       <code class="structfield">recheck</code> may be set to <code class="literal">true</code> if the match566       is uncertain and so the operator(s) must be re-applied to the actual567       heap tuple to verify the match.568       If ordered search is performed, set <code class="structfield">distances</code>569       to an array of distance values according to <code class="structfield">orderbys</code>570       array.  Leave it NULL otherwise.  If at least one of returned distances571       is not exact, set <code class="structfield">recheckDistances</code> to true.572       In this case, the executor will calculate the exact distances after573       fetching the tuple from the heap, and will reorder the tuples if needed.574      </p></dd></dl></div><p>575  The optional user-defined methods are:576 </p><div class="variablelist"><dl class="variablelist"><dt><span class="term"><code class="function">Datum compress(Datum in)</code></span></dt><dd><p>577       Converts a data item into a format suitable for physical storage in578       a leaf tuple of the index.  It accepts a value of type579       <code class="structname">spgConfigIn</code>.<code class="structfield">attType</code>580       and returns a value of type581       <code class="structname">spgConfigOut</code>.<code class="structfield">leafType</code>.582       The output value must not contain an out-of-line TOAST pointer.583      </p><p>584       Note: the <code class="function">compress</code> method is only applied to585       values to be stored.  The consistent methods receive query586       <code class="structfield">scankeys</code> unchanged, without transformation587       using <code class="function">compress</code>.588      </p></dd><dt><span class="term"><code class="function">options</code></span></dt><dd><p>589       Defines a set of user-visible parameters that control operator class590       behavior.591      </p><p>592        The <acronym class="acronym">SQL</acronym> declaration of the function must look like this:593 594</p><pre class="programlisting">595CREATE OR REPLACE FUNCTION my_options(internal)596RETURNS void597AS 'MODULE_PATHNAME'598LANGUAGE C STRICT;599</pre><p>600      </p><p>601       The function is passed a pointer to a <code class="structname">local_relopts</code>602       struct, which needs to be filled with a set of operator class603       specific options.  The options can be accessed from other support604       functions using the <code class="literal">PG_HAS_OPCLASS_OPTIONS()</code> and605       <code class="literal">PG_GET_OPCLASS_OPTIONS()</code> macros.606      </p><p>607       Since the representation of the key in <acronym class="acronym">SP-GiST</acronym> is608       flexible, it may depend on user-specified parameters.609      </p></dd></dl></div><p>610   All the SP-GiST support methods are normally called in a short-lived611   memory context; that is, <code class="varname">CurrentMemoryContext</code> will be reset612   after processing of each tuple.  It is therefore not very important to613   worry about pfree'ing everything you palloc.  (The <code class="function">config</code>614   method is an exception: it should try to avoid leaking memory.  But615   usually the <code class="function">config</code> method need do nothing but assign616   constants into the passed parameter struct.)617  </p><p>618   If the indexed column is of a collatable data type, the index collation619   will be passed to all the support methods, using the standard620   <code class="function">PG_GET_COLLATION()</code> mechanism.621  </p></div><div class="navfooter"><hr /><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="spgist-builtin-opclasses.html" title="69.2. Built-in Operator Classes">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="spgist.html" title="Chapter 69. SP-GiST Indexes">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="spgist-implementation.html" title="69.4. Implementation">Next</a></td></tr><tr><td width="40%" align="left" valign="top">69.2. Built-in Operator Classes </td><td width="20%" align="center"><a accesskey="h" href="index.html" title="PostgreSQL 16.3 Documentation">Home</a></td><td width="40%" align="right" valign="top"> 69.4. Implementation</td></tr></table></div></body></html>
codekingpro/portable-devtools · Team Ai