5050#include "utils/builtins.h"
5151#include "utils/rel.h"
5252
53+ #include "access/nbtree.h"
54+ #include "nodes/nodeFuncs.h"
55+
5356#include "optimizer/plancat.h"
5457#include "utils/inval.h"
5558#include "access/visibilitymap.h"
@@ -79,7 +82,10 @@ uint32
7982vertex_hash_init (Relation rel , double num_tuples , ForkNumber forkNum );
8083void
8184vertex_hash_doinsert (Relation rel , HeapTuple itup , Relation heapRel );
82-
85+ void
86+ vertex_exec_index_build_ScanKeys (PlanState * planstate , Relation index ,
87+ List * quals ,
88+ ScanKey scanKeys , int * numScanKeys );
8389typedef struct vertex_hash_struct
8490{
8591 graphid id ; // hash key
@@ -2784,7 +2790,12 @@ static exec_seq_scan_scan_key_hook_type prev_exec_seq_scan_scan_key_hook = NULL;
27842790void postgraph_seq_scan_key_hook (SeqScanState * node ,
27852791 int * numScanKeys , ScanKey scanKeys ) {
27862792
2787- ereport (WARNING , errmsg ("In hook" ));
2793+ ereport (WARNING , errmsg ("In hook" ));
2794+
2795+ vertex_exec_index_build_ScanKeys (node , node -> ss .ss_currentRelation ,
2796+ node -> ss .ps .plan -> qual ,
2797+ scanKeys , numScanKeys );
2798+
27882799 return ;
27892800}
27902801
@@ -2796,4 +2807,201 @@ void register_seq_scan_hook(void){
27962807void unregister_seq_scan_hook (void ){
27972808 exec_seq_scan_scan_key_hook = prev_exec_seq_scan_scan_key_hook ;
27982809}
2799-
2810+
2811+
2812+
2813+
2814+ /*
2815+ * ExecIndexBuildScanKeys
2816+ * Build the index scan keys from the index qualification expressions
2817+ *
2818+ * The index quals are passed to the index AM in the form of a ScanKey array.
2819+ * This routine sets up the ScanKeys, fills in all constant fields of the
2820+ * ScanKeys, and prepares information about the keys that have non-constant
2821+ * comparison values. We divide index qual expressions into five types:
2822+ *
2823+ * 1. Simple operator with constant comparison value ("indexkey op constant").
2824+ * For these, we just fill in a ScanKey containing the constant value.
2825+ *
2826+ * 2. Simple operator with non-constant value ("indexkey op expression").
2827+ * For these, we create a ScanKey with everything filled in except the
2828+ * expression value, and set up an IndexRuntimeKeyInfo struct to drive
2829+ * evaluation of the expression at the right times.
2830+ *
2831+ * 3. RowCompareExpr ("(indexkey, indexkey, ...) op (expr, expr, ...)").
2832+ * For these, we create a header ScanKey plus a subsidiary ScanKey array,
2833+ * as specified in access/skey.h. The elements of the row comparison
2834+ * can have either constant or non-constant comparison values.
2835+ *
2836+ * 4. ScalarArrayOpExpr ("indexkey op ANY (array-expression)"). If the index
2837+ * supports amsearcharray, we handle these the same as simple operators,
2838+ * setting the SK_SEARCHARRAY flag to tell the AM to handle them. Otherwise,
2839+ * we create a ScanKey with everything filled in except the comparison value,
2840+ * and set up an IndexArrayKeyInfo struct to drive processing of the qual.
2841+ * (Note that if we use an IndexArrayKeyInfo struct, the array expression is
2842+ * always treated as requiring runtime evaluation, even if it's a constant.)
2843+ *
2844+ * 5. NullTest ("indexkey IS NULL/IS NOT NULL"). We just fill in the
2845+ * ScanKey properly.
2846+ *
2847+ * This code is also used to prepare ORDER BY expressions for amcanorderbyop
2848+ * indexes. The behavior is exactly the same, except that we have to look up
2849+ * the operator differently. Note that only cases 1 and 2 are currently
2850+ * possible for ORDER BY.
2851+ *
2852+ * Input params are:
2853+ *
2854+ * planstate: executor state node we are working for
2855+ * index: the index we are building scan keys for
2856+ * quals: indexquals (or indexorderbys) expressions
2857+ * isorderby: true if processing ORDER BY exprs, false if processing quals
2858+ * *runtimeKeys: ptr to pre-existing IndexRuntimeKeyInfos, or NULL if none
2859+ * *numRuntimeKeys: number of pre-existing runtime keys
2860+ *
2861+ * Output params are:
2862+ *
2863+ * *scanKeys: receives ptr to array of ScanKeys
2864+ * *numScanKeys: receives number of scankeys
2865+ * *runtimeKeys: receives ptr to array of IndexRuntimeKeyInfos, or NULL if none
2866+ * *numRuntimeKeys: receives number of runtime keys
2867+ * *arrayKeys: receives ptr to array of IndexArrayKeyInfos, or NULL if none
2868+ * *numArrayKeys: receives number of array keys
2869+ *
2870+ * Caller may pass NULL for arrayKeys and numArrayKeys to indicate that
2871+ * IndexArrayKeyInfos are not supported.
2872+ */
2873+ void
2874+ vertex_exec_index_build_ScanKeys (PlanState * planstate , Relation index ,
2875+ List * quals ,
2876+ ScanKey scanKeys , int * numScanKeys )
2877+ {
2878+ ListCell * qual_cell ;
2879+
2880+ IndexRuntimeKeyInfo * runtime_keys ;
2881+ int n_runtime_keys ;
2882+ int max_runtime_keys ;
2883+ int j ;
2884+
2885+ /* Allocate array for ScanKey */
2886+ scanKeys = palloc (sizeof (IndexRuntimeKeyInfo ));
2887+
2888+ /*
2889+ * runtime_keys array is dynamically resized as needed. We handle it this
2890+ * way so that the same runtime keys array can be shared between
2891+ * indexquals and indexorderbys, which will be processed in separate calls
2892+ * of this function. Caller must be sure to pass in NULL/0 for first
2893+ * call.
2894+ */
2895+ numScanKeys = 0 ;
2896+
2897+
2898+
2899+ /*
2900+ * for each opclause in the given qual, convert the opclause into a single
2901+ * scan key
2902+ */
2903+
2904+ j = 0 ;
2905+ foreach (qual_cell , quals )
2906+ {
2907+ Expr * clause = (Expr * ) lfirst (qual_cell );
2908+
2909+ Oid opno ; /* operator's OID */
2910+ RegProcedure opfuncid ; /* operator proc id used in scan */
2911+ Oid opfamily ; /* opfamily of index column */
2912+ int op_strategy ; /* operator's strategy number */
2913+ Oid op_lefttype ; /* operator's declared input types */
2914+ Oid op_righttype ;
2915+ Expr * leftop ; /* expr on lhs of operator */
2916+ Expr * rightop ; /* expr on rhs ... */
2917+ AttrNumber varattno ; /* att number used in scan */
2918+ int indnkeyatts ;
2919+
2920+ indnkeyatts = 4 ;// id, startid, endid, properties
2921+ if (IsA (clause , OpExpr ))
2922+ {
2923+ ScanKey this_scan_key = palloc (sizeof (ScanKey ));
2924+
2925+
2926+ IndexRuntimeKeyInfo * runtimeKey = (IndexRuntimeKeyInfo * )scanKeys ;
2927+ /* indexkey op const or indexkey op expression */
2928+ int flags = 0 ;
2929+ Datum scanvalue ;
2930+
2931+ opno = ((OpExpr * ) clause )-> opno ;
2932+ opfuncid = ((OpExpr * ) clause )-> opfuncid ;
2933+
2934+ /*
2935+ * leftop should be the index key Var, possibly relabeled
2936+ */
2937+ leftop = (Expr * ) get_leftop (clause );
2938+
2939+ if (leftop && IsA (leftop , RelabelType ))
2940+ leftop = ((RelabelType * ) leftop )-> arg ;
2941+
2942+ Assert (leftop != NULL );
2943+
2944+ if (!(IsA (leftop , Var ) &&
2945+ ((Var * ) leftop )-> varno == INDEX_VAR ))
2946+ elog (ERROR , "indexqual doesn't have key on left side" );
2947+
2948+ varattno = ((Var * ) leftop )-> varattno ;
2949+ if (varattno < 1 || varattno > indnkeyatts )
2950+ elog (ERROR , "bogus index qualification" );
2951+
2952+ if (varattno != 1 )
2953+ continue ;
2954+ /*
2955+ * We have to look up the operator's strategy number. This
2956+ * provides a cross-check that the operator does match the index.
2957+ */
2958+ opfamily = index -> rd_opfamily [varattno - 1 ];
2959+
2960+ bool * isorderby ;
2961+ get_op_opfamily_properties (opno , opfamily , isorderby ,
2962+ & op_strategy ,
2963+ & op_lefttype ,
2964+ & op_righttype );
2965+
2966+ if (isorderby )
2967+ flags |= SK_ORDER_BY ;
2968+
2969+ /*
2970+ * rightop is the constant or variable comparison value
2971+ */
2972+ rightop = (Expr * ) get_rightop (clause );
2973+
2974+ if (rightop && IsA (rightop , RelabelType ))
2975+ rightop = ((RelabelType * ) rightop )-> arg ;
2976+
2977+ Assert (rightop != NULL );
2978+
2979+
2980+
2981+
2982+
2983+ /*
2984+ * initialize the scan key's fields appropriately
2985+ */
2986+ ScanKeyEntryInitialize (this_scan_key ,
2987+ flags ,
2988+ varattno , /* attribute number to scan */
2989+ op_strategy , /* op's strategy */
2990+ op_righttype , /* strategy subtype */
2991+ ((OpExpr * ) clause )-> inputcollid , /* collation */
2992+ opfuncid , /* reg proc to use */
2993+ scanvalue ); /* constant */
2994+
2995+
2996+ runtimeKey -> scan_key = this_scan_key ;
2997+ runtimeKey -> key_expr = ExecInitExpr (rightop , planstate );
2998+ runtimeKey -> key_toastable = TypeIsToastable (op_righttype );
2999+
3000+ scanvalue = (Datum ) 0 ;
3001+ numScanKeys ++ ;
3002+
3003+ break ;
3004+ }
3005+ }
3006+
3007+ }
0 commit comments