Go to the documentation of this file.00001
00002
00003
00004 #include "postgres.h"
00005
00006 #include "trgm.h"
00007
00008 #include "access/gin.h"
00009 #include "access/skey.h"
00010
00011
00012 PG_FUNCTION_INFO_V1(gin_extract_trgm);
00013 Datum gin_extract_trgm(PG_FUNCTION_ARGS);
00014
00015 PG_FUNCTION_INFO_V1(gin_extract_value_trgm);
00016 Datum gin_extract_value_trgm(PG_FUNCTION_ARGS);
00017
00018 PG_FUNCTION_INFO_V1(gin_extract_query_trgm);
00019 Datum gin_extract_query_trgm(PG_FUNCTION_ARGS);
00020
00021 PG_FUNCTION_INFO_V1(gin_trgm_consistent);
00022 Datum gin_trgm_consistent(PG_FUNCTION_ARGS);
00023
00024
00025
00026
00027
00028
00029 Datum
00030 gin_extract_trgm(PG_FUNCTION_ARGS)
00031 {
00032 if (PG_NARGS() == 3)
00033 return gin_extract_value_trgm(fcinfo);
00034 if (PG_NARGS() == 7)
00035 return gin_extract_query_trgm(fcinfo);
00036 elog(ERROR, "unexpected number of arguments to gin_extract_trgm");
00037 PG_RETURN_NULL();
00038 }
00039
00040 Datum
00041 gin_extract_value_trgm(PG_FUNCTION_ARGS)
00042 {
00043 text *val = (text *) PG_GETARG_TEXT_P(0);
00044 int32 *nentries = (int32 *) PG_GETARG_POINTER(1);
00045 Datum *entries = NULL;
00046 TRGM *trg;
00047 int32 trglen;
00048
00049 *nentries = 0;
00050
00051 trg = generate_trgm(VARDATA(val), VARSIZE(val) - VARHDRSZ);
00052 trglen = ARRNELEM(trg);
00053
00054 if (trglen > 0)
00055 {
00056 trgm *ptr;
00057 int32 i;
00058
00059 *nentries = trglen;
00060 entries = (Datum *) palloc(sizeof(Datum) * trglen);
00061
00062 ptr = GETARR(trg);
00063 for (i = 0; i < trglen; i++)
00064 {
00065 int32 item = trgm2int(ptr);
00066
00067 entries[i] = Int32GetDatum(item);
00068 ptr++;
00069 }
00070 }
00071
00072 PG_RETURN_POINTER(entries);
00073 }
00074
00075 Datum
00076 gin_extract_query_trgm(PG_FUNCTION_ARGS)
00077 {
00078 text *val = (text *) PG_GETARG_TEXT_P(0);
00079 int32 *nentries = (int32 *) PG_GETARG_POINTER(1);
00080 StrategyNumber strategy = PG_GETARG_UINT16(2);
00081
00082
00083 Pointer **extra_data = (Pointer **) PG_GETARG_POINTER(4);
00084
00085
00086 int32 *searchMode = (int32 *) PG_GETARG_POINTER(6);
00087 Datum *entries = NULL;
00088 TRGM *trg;
00089 int32 trglen;
00090 trgm *ptr;
00091 TrgmPackedGraph *graph;
00092 int32 i;
00093
00094 switch (strategy)
00095 {
00096 case SimilarityStrategyNumber:
00097 trg = generate_trgm(VARDATA(val), VARSIZE(val) - VARHDRSZ);
00098 break;
00099 case ILikeStrategyNumber:
00100 #ifndef IGNORECASE
00101 elog(ERROR, "cannot handle ~~* with case-sensitive trigrams");
00102 #endif
00103
00104 case LikeStrategyNumber:
00105
00106
00107
00108
00109
00110 trg = generate_wildcard_trgm(VARDATA(val), VARSIZE(val) - VARHDRSZ);
00111 break;
00112 case RegExpICaseStrategyNumber:
00113 #ifndef IGNORECASE
00114 elog(ERROR, "cannot handle ~* with case-sensitive trigrams");
00115 #endif
00116
00117 case RegExpStrategyNumber:
00118 trg = createTrgmNFA(val, PG_GET_COLLATION(),
00119 &graph, CurrentMemoryContext);
00120 if (trg && ARRNELEM(trg) > 0)
00121 {
00122
00123
00124
00125
00126
00127 trglen = ARRNELEM(trg);
00128 *extra_data = (Pointer *) palloc(sizeof(Pointer) * trglen);
00129 for (i = 0; i < trglen; i++)
00130 (*extra_data)[i] = (Pointer) graph;
00131 }
00132 else
00133 {
00134
00135 *nentries = 0;
00136 *searchMode = GIN_SEARCH_MODE_ALL;
00137 PG_RETURN_POINTER(entries);
00138 }
00139 break;
00140 default:
00141 elog(ERROR, "unrecognized strategy number: %d", strategy);
00142 trg = NULL;
00143 break;
00144 }
00145
00146 trglen = ARRNELEM(trg);
00147 *nentries = trglen;
00148
00149 if (trglen > 0)
00150 {
00151 entries = (Datum *) palloc(sizeof(Datum) * trglen);
00152 ptr = GETARR(trg);
00153 for (i = 0; i < trglen; i++)
00154 {
00155 int32 item = trgm2int(ptr);
00156
00157 entries[i] = Int32GetDatum(item);
00158 ptr++;
00159 }
00160 }
00161
00162
00163
00164
00165 if (trglen == 0)
00166 *searchMode = GIN_SEARCH_MODE_ALL;
00167
00168 PG_RETURN_POINTER(entries);
00169 }
00170
00171 Datum
00172 gin_trgm_consistent(PG_FUNCTION_ARGS)
00173 {
00174 bool *check = (bool *) PG_GETARG_POINTER(0);
00175 StrategyNumber strategy = PG_GETARG_UINT16(1);
00176
00177
00178 int32 nkeys = PG_GETARG_INT32(3);
00179 Pointer *extra_data = (Pointer *) PG_GETARG_POINTER(4);
00180 bool *recheck = (bool *) PG_GETARG_POINTER(5);
00181 bool res;
00182 int32 i,
00183 ntrue;
00184
00185
00186 *recheck = true;
00187
00188 switch (strategy)
00189 {
00190 case SimilarityStrategyNumber:
00191
00192 ntrue = 0;
00193 for (i = 0; i < nkeys; i++)
00194 {
00195 if (check[i])
00196 ntrue++;
00197 }
00198 #ifdef DIVUNION
00199 res = (nkeys == ntrue) ? true : ((((((float4) ntrue) / ((float4) (nkeys - ntrue)))) >= trgm_limit) ? true : false);
00200 #else
00201 res = (nkeys == 0) ? false : ((((((float4) ntrue) / ((float4) nkeys))) >= trgm_limit) ? true : false);
00202 #endif
00203 break;
00204 case ILikeStrategyNumber:
00205 #ifndef IGNORECASE
00206 elog(ERROR, "cannot handle ~~* with case-sensitive trigrams");
00207 #endif
00208
00209 case LikeStrategyNumber:
00210
00211 res = true;
00212 for (i = 0; i < nkeys; i++)
00213 {
00214 if (!check[i])
00215 {
00216 res = false;
00217 break;
00218 }
00219 }
00220 break;
00221 case RegExpICaseStrategyNumber:
00222 #ifndef IGNORECASE
00223 elog(ERROR, "cannot handle ~* with case-sensitive trigrams");
00224 #endif
00225
00226 case RegExpStrategyNumber:
00227 if (nkeys < 1)
00228 {
00229
00230 res = true;
00231 }
00232 else
00233 res = trigramsMatchGraph((TrgmPackedGraph *) extra_data[0],
00234 check);
00235 break;
00236 default:
00237 elog(ERROR, "unrecognized strategy number: %d", strategy);
00238 res = false;
00239 break;
00240 }
00241
00242 PG_RETURN_BOOL(res);
00243 }