Branch data Line data Source code
1 : : /*
2 : : * contrib/pg_trgm/trgm_gin.c
3 : : */
4 : : #include "postgres.h"
5 : :
6 : : #include "trgm.h"
7 : :
8 : : #include "access/gin.h"
9 : : #include "access/skey.h"
10 : :
11 : :
12 : 0 : PG_FUNCTION_INFO_V1(gin_extract_trgm);
13 : : Datum gin_extract_trgm(PG_FUNCTION_ARGS);
14 : :
15 : 3 : PG_FUNCTION_INFO_V1(gin_extract_value_trgm);
16 : : Datum gin_extract_value_trgm(PG_FUNCTION_ARGS);
17 : :
18 : 3 : PG_FUNCTION_INFO_V1(gin_extract_query_trgm);
19 : : Datum gin_extract_query_trgm(PG_FUNCTION_ARGS);
20 : :
21 : 3 : PG_FUNCTION_INFO_V1(gin_trgm_consistent);
22 : : Datum gin_trgm_consistent(PG_FUNCTION_ARGS);
23 : :
24 : : /*
25 : : * This function can only be called if a pre-9.1 version of the GIN operator
26 : : * class definition is present in the catalogs (probably as a consequence
27 : : * of upgrade-in-place). Cope.
28 : : */
29 : : Datum
30 : 0 : gin_extract_trgm(PG_FUNCTION_ARGS)
31 : : {
32 [ # # ]: 0 : if (PG_NARGS() == 3)
33 : 0 : return gin_extract_value_trgm(fcinfo);
34 [ # # ]: 0 : if (PG_NARGS() == 7)
35 : 0 : return gin_extract_query_trgm(fcinfo);
36 : 0 : elog(ERROR, "unexpected number of arguments to gin_extract_trgm");
37 : : PG_RETURN_NULL();
38 : : }
39 : :
40 : : Datum
41 : 1002 : gin_extract_value_trgm(PG_FUNCTION_ARGS)
42 : : {
43 : 1002 : text *val = (text *) PG_GETARG_TEXT_P(0);
44 : 1002 : int32 *nentries = (int32 *) PG_GETARG_POINTER(1);
45 : 1002 : Datum *entries = NULL;
46 : : TRGM *trg;
47 : : int32 trglen;
48 : :
49 : 1002 : *nentries = 0;
50 : :
51 : 1002 : trg = generate_trgm(VARDATA(val), VARSIZE(val) - VARHDRSZ);
52 : 1002 : trglen = ARRNELEM(trg);
53 : :
54 [ + - ]: 1002 : if (trglen > 0)
55 : : {
56 : : trgm *ptr;
57 : : int32 i;
58 : :
59 : 1002 : *nentries = trglen;
60 : 1002 : entries = (Datum *) palloc(sizeof(Datum) * trglen);
61 : :
62 : 1002 : ptr = GETARR(trg);
63 [ + + ]: 13015 : for (i = 0; i < trglen; i++)
64 : : {
65 : 12013 : int32 item = trgm2int(ptr);
66 : :
67 : 12013 : entries[i] = Int32GetDatum(item);
68 : 12013 : ptr++;
69 : : }
70 : : }
71 : :
72 : 1002 : PG_RETURN_POINTER(entries);
73 : : }
74 : :
75 : : Datum
76 : 32 : gin_extract_query_trgm(PG_FUNCTION_ARGS)
77 : : {
78 : 32 : text *val = (text *) PG_GETARG_TEXT_P(0);
79 : 32 : int32 *nentries = (int32 *) PG_GETARG_POINTER(1);
80 : 32 : StrategyNumber strategy = PG_GETARG_UINT16(2);
81 : :
82 : : /* bool **pmatch = (bool **) PG_GETARG_POINTER(3); */
83 : 32 : Pointer **extra_data = (Pointer **) PG_GETARG_POINTER(4);
84 : : /* bool **nullFlags = (bool **) PG_GETARG_POINTER(5); */
85 : 32 : int32 *searchMode = (int32 *) PG_GETARG_POINTER(6);
86 : 32 : Datum *entries = NULL;
87 : : TRGM *trg;
88 : : int32 trglen;
89 : : trgm *ptr;
90 : : int32 i;
91 : : PackedGraph *graph;
92 : :
93 [ + + + - ]: 32 : switch (strategy)
94 : : {
95 : : case SimilarityStrategyNumber:
96 : 6 : trg = generate_trgm(VARDATA(val), VARSIZE(val) - VARHDRSZ);
97 : 6 : break;
98 : : case ILikeStrategyNumber:
99 : : #ifndef IGNORECASE
100 : : elog(ERROR, "cannot handle ~~* with case-sensitive trigrams");
101 : : #endif
102 : : /* FALL THRU */
103 : : case LikeStrategyNumber:
104 : :
105 : : /*
106 : : * For wildcard search we extract all the trigrams that every
107 : : * potentially-matching string must include.
108 : : */
109 : 12 : trg = generate_wildcard_trgm(VARDATA(val), VARSIZE(val) - VARHDRSZ);
110 : 12 : break;
111 : : case RegExpStrategyNumberICase:
112 : : #ifndef IGNORECASE
113 : : elog(ERROR, "cannot handle ~* with case-sensitive trigrams");
114 : : #endif
115 : : /* FALL THRU */
116 : : case RegExpStrategyNumber:
117 : 14 : trg = createTrgmCNFA(val, fcinfo->flinfo->fn_mcxt, &graph);
118 [ + - ][ + - ]: 14 : if (trg && ARRNELEM(trg) > 0)
119 : : {
120 : : /*
121 : : * Successful regex processing: store CNFA-like graph as an
122 : : * extra_data.
123 : : */
124 : 14 : *extra_data = (Pointer *) palloc0(sizeof(Pointer) *
125 : : ARRNELEM(trg));
126 [ + + ]: 328 : for (i = 0; i < ARRNELEM(trg); i++)
127 : 314 : (*extra_data)[i] = (Pointer) graph;
128 : : }
129 : : else
130 : : {
131 : : /* No result: have to do full index scan. */
132 : 0 : *nentries = 0;
133 : 0 : *searchMode = GIN_SEARCH_MODE_ALL;
134 : : PG_RETURN_POINTER(entries);
135 : : }
136 : : break;
137 : : default:
138 : 0 : elog(ERROR, "unrecognized strategy number: %d", strategy);
139 : : trg = NULL; /* keep compiler quiet */
140 : : break;
141 : : }
142 : :
143 : 32 : trglen = ARRNELEM(trg);
144 : 32 : *nentries = trglen;
145 : :
146 [ + - ]: 32 : if (trglen > 0)
147 : : {
148 : 32 : entries = (Datum *) palloc(sizeof(Datum) * trglen);
149 : 32 : ptr = GETARR(trg);
150 [ + + ]: 434 : for (i = 0; i < trglen; i++)
151 : : {
152 : 402 : int32 item = trgm2int(ptr);
153 : :
154 : 402 : entries[i] = Int32GetDatum(item);
155 : 402 : ptr++;
156 : : }
157 : : }
158 : :
159 : : /*
160 : : * If no trigram was extracted then we have to scan all the index.
161 : : */
162 [ - + ]: 32 : if (trglen == 0)
163 : 0 : *searchMode = GIN_SEARCH_MODE_ALL;
164 : :
165 : 32 : PG_RETURN_POINTER(entries);
166 : : }
167 : :
168 : : Datum
169 : 3012 : gin_trgm_consistent(PG_FUNCTION_ARGS)
170 : : {
171 : 3012 : bool *check = (bool *) PG_GETARG_POINTER(0);
172 : 3012 : StrategyNumber strategy = PG_GETARG_UINT16(1);
173 : :
174 : : /* text *query = PG_GETARG_TEXT_P(2); */
175 : 3012 : int32 nkeys = PG_GETARG_INT32(3);
176 : :
177 : 3012 : Pointer *extra_data = (Pointer *) PG_GETARG_POINTER(4);
178 : 3012 : bool *recheck = (bool *) PG_GETARG_POINTER(5);
179 : : bool res;
180 : : int32 i,
181 : : ntrue;
182 : :
183 : : /* All cases served by this function are inexact */
184 : 3012 : *recheck = true;
185 : :
186 [ + + + - ]: 3012 : switch (strategy)
187 : : {
188 : : case SimilarityStrategyNumber:
189 : : /* Count the matches */
190 : : ntrue = 0;
191 [ + + ]: 39000 : for (i = 0; i < nkeys; i++)
192 : : {
193 [ + + ]: 36000 : if (check[i])
194 : 17255 : ntrue++;
195 : : }
196 : : #ifdef DIVUNION
197 [ + + ][ - + ]: 3000 : res = (nkeys == ntrue) ? true : ((((((float4) ntrue) / ((float4) (nkeys - ntrue)))) >= trgm_limit) ? true : false);
198 : : #else
199 : : res = (nkeys == 0) ? false : ((((((float4) ntrue) / ((float4) nkeys))) >= trgm_limit) ? true : false);
200 : : #endif
201 : 3000 : break;
202 : : case ILikeStrategyNumber:
203 : : #ifndef IGNORECASE
204 : : elog(ERROR, "cannot handle ~~* with case-sensitive trigrams");
205 : : #endif
206 : : /* FALL THRU */
207 : : case LikeStrategyNumber:
208 : : /* Check if all extracted trigrams are presented. */
209 : : res = true;
210 [ + + ]: 12 : for (i = 0; i < nkeys; i++)
211 : : {
212 [ + - ]: 7 : if (!check[i])
213 : : {
214 : : res = false;
215 : : break;
216 : : }
217 : : }
218 : : break;
219 : : case RegExpStrategyNumber:
220 : : case RegExpStrategyNumberICase:
221 [ + - ]: 7 : if (nkeys < 1)
222 : : {
223 : : /* Regex processing gave no result: do full index scan */
224 : : res = true;
225 : : break;
226 : : }
227 : 7 : res = trigramsMatchGraph((PackedGraph *) extra_data[0], check);
228 : :
229 : 7 : break;
230 : : default:
231 : 0 : elog(ERROR, "unrecognized strategy number: %d", strategy);
232 : : res = false; /* keep compiler quiet */
233 : : break;
234 : : }
235 : :
236 [ - + ]: 3012 : PG_RETURN_BOOL(res);
237 : : }
|