00001 /* 00002 * contrib/intarray/_int_gin.c 00003 */ 00004 #include "postgres.h" 00005 00006 #include "access/gin.h" 00007 #include "access/gist.h" 00008 #include "access/skey.h" 00009 00010 #include "_int.h" 00011 00012 PG_FUNCTION_INFO_V1(ginint4_queryextract); 00013 Datum ginint4_queryextract(PG_FUNCTION_ARGS); 00014 00015 Datum 00016 ginint4_queryextract(PG_FUNCTION_ARGS) 00017 { 00018 int32 *nentries = (int32 *) PG_GETARG_POINTER(1); 00019 StrategyNumber strategy = PG_GETARG_UINT16(2); 00020 int32 *searchMode = (int32 *) PG_GETARG_POINTER(6); 00021 Datum *res = NULL; 00022 00023 *nentries = 0; 00024 00025 if (strategy == BooleanSearchStrategy) 00026 { 00027 QUERYTYPE *query = PG_GETARG_QUERYTYPE_P(0); 00028 ITEM *items = GETQUERY(query); 00029 int i; 00030 00031 /* empty query must fail */ 00032 if (query->size <= 0) 00033 PG_RETURN_POINTER(NULL); 00034 00035 /* 00036 * If the query doesn't have any required primitive values (for 00037 * instance, it's something like '! 42'), we have to do a full index 00038 * scan. 00039 */ 00040 if (query_has_required_values(query)) 00041 *searchMode = GIN_SEARCH_MODE_DEFAULT; 00042 else 00043 *searchMode = GIN_SEARCH_MODE_ALL; 00044 00045 /* 00046 * Extract all the VAL items as things we want GIN to check for. 00047 */ 00048 res = (Datum *) palloc(sizeof(Datum) * query->size); 00049 *nentries = 0; 00050 00051 for (i = 0; i < query->size; i++) 00052 { 00053 if (items[i].type == VAL) 00054 { 00055 res[*nentries] = Int32GetDatum(items[i].val); 00056 (*nentries)++; 00057 } 00058 } 00059 } 00060 else 00061 { 00062 ArrayType *query = PG_GETARG_ARRAYTYPE_P(0); 00063 00064 CHECKARRVALID(query); 00065 *nentries = ARRNELEMS(query); 00066 if (*nentries > 0) 00067 { 00068 int32 *arr; 00069 int32 i; 00070 00071 res = (Datum *) palloc(sizeof(Datum) * (*nentries)); 00072 00073 arr = ARRPTR(query); 00074 for (i = 0; i < *nentries; i++) 00075 res[i] = Int32GetDatum(arr[i]); 00076 } 00077 00078 switch (strategy) 00079 { 00080 case RTOverlapStrategyNumber: 00081 *searchMode = GIN_SEARCH_MODE_DEFAULT; 00082 break; 00083 case RTContainedByStrategyNumber: 00084 case RTOldContainedByStrategyNumber: 00085 /* empty set is contained in everything */ 00086 *searchMode = GIN_SEARCH_MODE_INCLUDE_EMPTY; 00087 break; 00088 case RTSameStrategyNumber: 00089 if (*nentries > 0) 00090 *searchMode = GIN_SEARCH_MODE_DEFAULT; 00091 else 00092 *searchMode = GIN_SEARCH_MODE_INCLUDE_EMPTY; 00093 break; 00094 case RTContainsStrategyNumber: 00095 case RTOldContainsStrategyNumber: 00096 if (*nentries > 0) 00097 *searchMode = GIN_SEARCH_MODE_DEFAULT; 00098 else /* everything contains the empty set */ 00099 *searchMode = GIN_SEARCH_MODE_ALL; 00100 break; 00101 default: 00102 elog(ERROR, "ginint4_queryextract: unknown strategy number: %d", 00103 strategy); 00104 } 00105 } 00106 00107 PG_RETURN_POINTER(res); 00108 } 00109 00110 PG_FUNCTION_INFO_V1(ginint4_consistent); 00111 Datum ginint4_consistent(PG_FUNCTION_ARGS); 00112 00113 Datum 00114 ginint4_consistent(PG_FUNCTION_ARGS) 00115 { 00116 bool *check = (bool *) PG_GETARG_POINTER(0); 00117 StrategyNumber strategy = PG_GETARG_UINT16(1); 00118 int32 nkeys = PG_GETARG_INT32(3); 00119 00120 /* Pointer *extra_data = (Pointer *) PG_GETARG_POINTER(4); */ 00121 bool *recheck = (bool *) PG_GETARG_POINTER(5); 00122 bool res = FALSE; 00123 int32 i; 00124 00125 switch (strategy) 00126 { 00127 case RTOverlapStrategyNumber: 00128 /* result is not lossy */ 00129 *recheck = false; 00130 /* at least one element in check[] is true, so result = true */ 00131 res = TRUE; 00132 break; 00133 case RTContainedByStrategyNumber: 00134 case RTOldContainedByStrategyNumber: 00135 /* we will need recheck */ 00136 *recheck = true; 00137 /* at least one element in check[] is true, so result = true */ 00138 res = TRUE; 00139 break; 00140 case RTSameStrategyNumber: 00141 /* we will need recheck */ 00142 *recheck = true; 00143 /* Must have all elements in check[] true */ 00144 res = TRUE; 00145 for (i = 0; i < nkeys; i++) 00146 { 00147 if (!check[i]) 00148 { 00149 res = FALSE; 00150 break; 00151 } 00152 } 00153 break; 00154 case RTContainsStrategyNumber: 00155 case RTOldContainsStrategyNumber: 00156 /* result is not lossy */ 00157 *recheck = false; 00158 /* Must have all elements in check[] true */ 00159 res = TRUE; 00160 for (i = 0; i < nkeys; i++) 00161 { 00162 if (!check[i]) 00163 { 00164 res = FALSE; 00165 break; 00166 } 00167 } 00168 break; 00169 case BooleanSearchStrategy: 00170 { 00171 QUERYTYPE *query = PG_GETARG_QUERYTYPE_P(2); 00172 00173 /* result is not lossy */ 00174 *recheck = false; 00175 res = gin_bool_consistent(query, check); 00176 } 00177 break; 00178 default: 00179 elog(ERROR, "ginint4_consistent: unknown strategy number: %d", 00180 strategy); 00181 } 00182 00183 PG_RETURN_BOOL(res); 00184 }