Line data Source code
1 : /* 2 : * contrib/intarray/_int_gin.c 3 : */ 4 : #include "postgres.h" 5 : 6 : #include "_int.h" 7 : #include "access/gin.h" 8 : #include "access/stratnum.h" 9 : 10 4 : PG_FUNCTION_INFO_V1(ginint4_queryextract); 11 : 12 : Datum 13 52 : ginint4_queryextract(PG_FUNCTION_ARGS) 14 : { 15 52 : int32 *nentries = (int32 *) PG_GETARG_POINTER(1); 16 52 : StrategyNumber strategy = PG_GETARG_UINT16(2); 17 52 : int32 *searchMode = (int32 *) PG_GETARG_POINTER(6); 18 52 : Datum *res = NULL; 19 : 20 52 : *nentries = 0; 21 : 22 52 : if (strategy == BooleanSearchStrategy) 23 : { 24 24 : QUERYTYPE *query = PG_GETARG_QUERYTYPE_P(0); 25 24 : ITEM *items = GETQUERY(query); 26 : int i; 27 : 28 : /* empty query must fail */ 29 24 : if (query->size <= 0) 30 0 : PG_RETURN_POINTER(NULL); 31 : 32 : /* 33 : * If the query doesn't have any required primitive values (for 34 : * instance, it's something like '! 42'), we have to do a full index 35 : * scan. 36 : */ 37 24 : if (query_has_required_values(query)) 38 16 : *searchMode = GIN_SEARCH_MODE_DEFAULT; 39 : else 40 8 : *searchMode = GIN_SEARCH_MODE_ALL; 41 : 42 : /* 43 : * Extract all the VAL items as things we want GIN to check for. 44 : */ 45 24 : res = (Datum *) palloc(sizeof(Datum) * query->size); 46 24 : *nentries = 0; 47 : 48 124 : for (i = 0; i < query->size; i++) 49 : { 50 100 : if (items[i].type == VAL) 51 : { 52 56 : res[*nentries] = Int32GetDatum(items[i].val); 53 56 : (*nentries)++; 54 : } 55 : } 56 : } 57 : else 58 : { 59 28 : ArrayType *query = PG_GETARG_ARRAYTYPE_P(0); 60 : 61 28 : CHECKARRVALID(query); 62 28 : *nentries = ARRNELEMS(query); 63 28 : if (*nentries > 0) 64 : { 65 : int32 *arr; 66 : int32 i; 67 : 68 28 : res = (Datum *) palloc(sizeof(Datum) * (*nentries)); 69 : 70 28 : arr = ARRPTR(query); 71 92 : for (i = 0; i < *nentries; i++) 72 64 : res[i] = Int32GetDatum(arr[i]); 73 : } 74 : 75 28 : switch (strategy) 76 : { 77 4 : case RTOverlapStrategyNumber: 78 4 : *searchMode = GIN_SEARCH_MODE_DEFAULT; 79 4 : break; 80 4 : case RTContainedByStrategyNumber: 81 : case RTOldContainedByStrategyNumber: 82 : /* empty set is contained in everything */ 83 4 : *searchMode = GIN_SEARCH_MODE_INCLUDE_EMPTY; 84 4 : break; 85 4 : case RTSameStrategyNumber: 86 4 : if (*nentries > 0) 87 4 : *searchMode = GIN_SEARCH_MODE_DEFAULT; 88 : else 89 0 : *searchMode = GIN_SEARCH_MODE_INCLUDE_EMPTY; 90 4 : break; 91 16 : case RTContainsStrategyNumber: 92 : case RTOldContainsStrategyNumber: 93 16 : if (*nentries > 0) 94 16 : *searchMode = GIN_SEARCH_MODE_DEFAULT; 95 : else /* everything contains the empty set */ 96 0 : *searchMode = GIN_SEARCH_MODE_ALL; 97 16 : break; 98 0 : default: 99 0 : elog(ERROR, "ginint4_queryextract: unknown strategy number: %d", 100 : strategy); 101 : } 102 : } 103 : 104 52 : PG_RETURN_POINTER(res); 105 : } 106 : 107 4 : PG_FUNCTION_INFO_V1(ginint4_consistent); 108 : 109 : Datum 110 33920 : ginint4_consistent(PG_FUNCTION_ARGS) 111 : { 112 33920 : bool *check = (bool *) PG_GETARG_POINTER(0); 113 33920 : StrategyNumber strategy = PG_GETARG_UINT16(1); 114 33920 : int32 nkeys = PG_GETARG_INT32(3); 115 : 116 : /* Pointer *extra_data = (Pointer *) PG_GETARG_POINTER(4); */ 117 33920 : bool *recheck = (bool *) PG_GETARG_POINTER(5); 118 33920 : bool res = false; 119 : int32 i; 120 : 121 33920 : switch (strategy) 122 : { 123 810 : case RTOverlapStrategyNumber: 124 : /* result is not lossy */ 125 810 : *recheck = false; 126 : /* at least one element in check[] is true, so result = true */ 127 810 : res = true; 128 810 : break; 129 1264 : case RTContainedByStrategyNumber: 130 : case RTOldContainedByStrategyNumber: 131 : /* we will need recheck */ 132 1264 : *recheck = true; 133 : /* at least one element in check[] is true, so result = true */ 134 1264 : res = true; 135 1264 : break; 136 410 : case RTSameStrategyNumber: 137 : /* we will need recheck */ 138 410 : *recheck = true; 139 : /* Must have all elements in check[] true */ 140 410 : res = true; 141 826 : for (i = 0; i < nkeys; i++) 142 : { 143 824 : if (!check[i]) 144 : { 145 408 : res = false; 146 408 : break; 147 : } 148 : } 149 410 : break; 150 1630 : case RTContainsStrategyNumber: 151 : case RTOldContainsStrategyNumber: 152 : /* result is not lossy */ 153 1630 : *recheck = false; 154 : /* Must have all elements in check[] true */ 155 1630 : res = true; 156 1818 : for (i = 0; i < nkeys; i++) 157 : { 158 1728 : if (!check[i]) 159 : { 160 1540 : res = false; 161 1540 : break; 162 : } 163 : } 164 1630 : break; 165 29806 : case BooleanSearchStrategy: 166 : { 167 29806 : QUERYTYPE *query = PG_GETARG_QUERYTYPE_P(2); 168 : 169 : /* result is not lossy */ 170 29806 : *recheck = false; 171 29806 : res = gin_bool_consistent(query, check); 172 : } 173 29806 : break; 174 0 : default: 175 0 : elog(ERROR, "ginint4_consistent: unknown strategy number: %d", 176 : strategy); 177 : } 178 : 179 33920 : PG_RETURN_BOOL(res); 180 : }