Branch data Line data Source code
1 : : /*-------------------------------------------------------------------------
2 : : *
3 : : * like_support.c
4 : : * Planner support functions for LIKE, regex, and related operators.
5 : : *
6 : : * These routines handle special optimization of operators that can be
7 : : * used with index scans even though they are not known to the executor's
8 : : * indexscan machinery. The key idea is that these operators allow us
9 : : * to derive approximate indexscan qual clauses, such that any tuples
10 : : * that pass the operator clause itself must also satisfy the simpler
11 : : * indexscan condition(s). Then we can use the indexscan machinery
12 : : * to avoid scanning as much of the table as we'd otherwise have to,
13 : : * while applying the original operator as a qpqual condition to ensure
14 : : * we deliver only the tuples we want. (In essence, we're using a regular
15 : : * index as if it were a lossy index.)
16 : : *
17 : : * An example of what we're doing is
18 : : * textfield LIKE 'abc%def'
19 : : * from which we can generate the indexscanable conditions
20 : : * textfield >= 'abc' AND textfield < 'abd'
21 : : * which allow efficient scanning of an index on textfield.
22 : : * (In reality, character set and collation issues make the transformation
23 : : * from LIKE to indexscan limits rather harder than one might think ...
24 : : * but that's the basic idea.)
25 : : *
26 : : * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
27 : : * Portions Copyright (c) 1994, Regents of the University of California
28 : : *
29 : : *
30 : : * IDENTIFICATION
31 : : * src/backend/utils/adt/like_support.c
32 : : *
33 : : *-------------------------------------------------------------------------
34 : : */
35 : : #include "postgres.h"
36 : :
37 : : #include <math.h>
38 : :
39 : : #include "access/htup_details.h"
40 : : #include "catalog/pg_collation.h"
41 : : #include "catalog/pg_operator.h"
42 : : #include "catalog/pg_opfamily.h"
43 : : #include "catalog/pg_statistic.h"
44 : : #include "catalog/pg_type.h"
45 : : #include "mb/pg_wchar.h"
46 : : #include "miscadmin.h"
47 : : #include "nodes/makefuncs.h"
48 : : #include "nodes/nodeFuncs.h"
49 : : #include "nodes/supportnodes.h"
50 : : #include "utils/builtins.h"
51 : : #include "utils/datum.h"
52 : : #include "utils/lsyscache.h"
53 : : #include "utils/pg_locale.h"
54 : : #include "utils/selfuncs.h"
55 : : #include "utils/varlena.h"
56 : :
57 : :
58 : : typedef enum
59 : : {
60 : : Pattern_Type_Like,
61 : : Pattern_Type_Like_IC,
62 : : Pattern_Type_Regex,
63 : : Pattern_Type_Regex_IC,
64 : : Pattern_Type_Prefix,
65 : : } Pattern_Type;
66 : :
67 : : typedef enum
68 : : {
69 : : Pattern_Prefix_None, Pattern_Prefix_Partial, Pattern_Prefix_Exact,
70 : : } Pattern_Prefix_Status;
71 : :
72 : : /* non-collatable comparisons, eg for bytea, are always deterministic */
73 : : #define NONDETERMINISTIC(coll) \
74 : : (OidIsValid(coll) && !get_collation_isdeterministic(coll))
75 : :
76 : : static Node *like_regex_support(Node *rawreq, Pattern_Type ptype);
77 : : static List *match_pattern_prefix(Node *leftop,
78 : : Node *rightop,
79 : : Pattern_Type ptype,
80 : : Oid expr_coll,
81 : : Oid opfamily,
82 : : Oid indexcollation);
83 : : static double patternsel_common(PlannerInfo *root,
84 : : Oid oprid,
85 : : Oid opfuncid,
86 : : List *args,
87 : : int varRelid,
88 : : Oid collation,
89 : : Pattern_Type ptype,
90 : : bool negate);
91 : : static Pattern_Prefix_Status pattern_fixed_prefix(Const *patt,
92 : : Pattern_Type ptype,
93 : : Oid collation,
94 : : Const **prefix,
95 : : Selectivity *rest_selec);
96 : : static Selectivity prefix_selectivity(PlannerInfo *root,
97 : : VariableStatData *vardata,
98 : : Oid eqopr, Oid ltopr, Oid geopr,
99 : : Oid collation,
100 : : Const *prefixcon);
101 : : static Selectivity like_selectivity(const char *patt, int pattlen,
102 : : bool case_insensitive);
103 : : static Selectivity regex_selectivity(const char *patt, int pattlen,
104 : : bool case_insensitive,
105 : : int fixed_prefix_len);
106 : : static Const *make_greater_string(const Const *str_const, FmgrInfo *ltproc,
107 : : Oid collation);
108 : : static Datum string_to_datum(const char *str, Oid datatype);
109 : : static Const *string_to_const(const char *str, Oid datatype);
110 : : static Const *string_to_bytea_const(const char *str, size_t str_len);
111 : :
112 : :
113 : : /*
114 : : * Planner support functions for LIKE, regex, and related operators
115 : : */
116 : : Datum
117 : 4147 : textlike_support(PG_FUNCTION_ARGS)
118 : : {
119 : 4147 : Node *rawreq = (Node *) PG_GETARG_POINTER(0);
120 : :
121 : 4147 : PG_RETURN_POINTER(like_regex_support(rawreq, Pattern_Type_Like));
122 : : }
123 : :
124 : : Datum
125 : 282 : texticlike_support(PG_FUNCTION_ARGS)
126 : : {
127 : 282 : Node *rawreq = (Node *) PG_GETARG_POINTER(0);
128 : :
129 : 282 : PG_RETURN_POINTER(like_regex_support(rawreq, Pattern_Type_Like_IC));
130 : : }
131 : :
132 : : Datum
133 : 19222 : textregexeq_support(PG_FUNCTION_ARGS)
134 : : {
135 : 19222 : Node *rawreq = (Node *) PG_GETARG_POINTER(0);
136 : :
137 : 19222 : PG_RETURN_POINTER(like_regex_support(rawreq, Pattern_Type_Regex));
138 : : }
139 : :
140 : : Datum
141 : 97 : texticregexeq_support(PG_FUNCTION_ARGS)
142 : : {
143 : 97 : Node *rawreq = (Node *) PG_GETARG_POINTER(0);
144 : :
145 : 97 : PG_RETURN_POINTER(like_regex_support(rawreq, Pattern_Type_Regex_IC));
146 : : }
147 : :
148 : : Datum
149 : 130 : text_starts_with_support(PG_FUNCTION_ARGS)
150 : : {
151 : 130 : Node *rawreq = (Node *) PG_GETARG_POINTER(0);
152 : :
153 : 130 : PG_RETURN_POINTER(like_regex_support(rawreq, Pattern_Type_Prefix));
154 : : }
155 : :
156 : : /* Common code for the above */
157 : : static Node *
158 : 23878 : like_regex_support(Node *rawreq, Pattern_Type ptype)
159 : : {
160 : 23878 : Node *ret = NULL;
161 : :
162 [ + + ]: 23878 : if (IsA(rawreq, SupportRequestSelectivity))
163 : : {
164 : : /*
165 : : * Make a selectivity estimate for a function call, just as we'd do if
166 : : * the call was via the corresponding operator.
167 : : */
168 : 20 : SupportRequestSelectivity *req = (SupportRequestSelectivity *) rawreq;
169 : : Selectivity s1;
170 : :
171 [ - + ]: 20 : if (req->is_join)
172 : : {
173 : : /*
174 : : * For the moment we just punt. If patternjoinsel is ever
175 : : * improved to do better, this should be made to call it.
176 : : */
177 : 0 : s1 = DEFAULT_MATCH_SEL;
178 : : }
179 : : else
180 : : {
181 : : /* Share code with operator restriction selectivity functions */
182 : 20 : s1 = patternsel_common(req->root,
183 : : InvalidOid,
184 : : req->funcid,
185 : : req->args,
186 : : req->varRelid,
187 : : req->inputcollid,
188 : : ptype,
189 : : false);
190 : : }
191 : 20 : req->selectivity = s1;
192 : 20 : ret = (Node *) req;
193 : : }
194 [ + + ]: 23858 : else if (IsA(rawreq, SupportRequestIndexCondition))
195 : : {
196 : : /* Try to convert operator/function call to index conditions */
197 : 6917 : SupportRequestIndexCondition *req = (SupportRequestIndexCondition *) rawreq;
198 : :
199 : : /*
200 : : * Currently we have no "reverse" match operators with the pattern on
201 : : * the left, so we only need consider cases with the indexkey on the
202 : : * left.
203 : : */
204 [ - + ]: 6917 : if (req->indexarg != 0)
205 : 0 : return NULL;
206 : :
207 [ + + ]: 6917 : if (is_opclause(req->node))
208 : : {
209 : 6897 : OpExpr *clause = (OpExpr *) req->node;
210 : :
211 : : Assert(list_length(clause->args) == 2);
212 : : ret = (Node *)
213 : 6897 : match_pattern_prefix((Node *) linitial(clause->args),
214 : 6897 : (Node *) lsecond(clause->args),
215 : : ptype,
216 : : clause->inputcollid,
217 : : req->opfamily,
218 : : req->indexcollation);
219 : : }
220 [ + - ]: 20 : else if (is_funcclause(req->node)) /* be paranoid */
221 : : {
222 : 20 : FuncExpr *clause = (FuncExpr *) req->node;
223 : :
224 : : Assert(list_length(clause->args) == 2);
225 : : ret = (Node *)
226 : 20 : match_pattern_prefix((Node *) linitial(clause->args),
227 : 20 : (Node *) lsecond(clause->args),
228 : : ptype,
229 : : clause->inputcollid,
230 : : req->opfamily,
231 : : req->indexcollation);
232 : : }
233 : : }
234 : :
235 : 23878 : return ret;
236 : : }
237 : :
238 : : /*
239 : : * match_pattern_prefix
240 : : * Try to generate an indexqual for a LIKE or regex operator.
241 : : */
242 : : static List *
243 : 6917 : match_pattern_prefix(Node *leftop,
244 : : Node *rightop,
245 : : Pattern_Type ptype,
246 : : Oid expr_coll,
247 : : Oid opfamily,
248 : : Oid indexcollation)
249 : : {
250 : : List *result;
251 : : Const *patt;
252 : : Const *prefix;
253 : : Pattern_Prefix_Status pstatus;
254 : : Oid ldatatype;
255 : : Oid rdatatype;
256 : : Oid eqopr;
257 : : Oid ltopr;
258 : : Oid geopr;
259 : 6917 : Oid preopr = InvalidOid;
260 : : bool collation_aware;
261 : : Expr *expr;
262 : : FmgrInfo ltproc;
263 : : Const *greaterstr;
264 : :
265 : : /*
266 : : * Can't do anything with a non-constant or NULL pattern argument.
267 : : *
268 : : * Note that since we restrict ourselves to cases with a hard constant on
269 : : * the RHS, it's a-fortiori a pseudoconstant, and we don't need to worry
270 : : * about verifying that.
271 : : */
272 [ + + ]: 6917 : if (!IsA(rightop, Const) ||
273 [ - + ]: 6893 : ((Const *) rightop)->constisnull)
274 : 24 : return NIL;
275 : 6893 : patt = (Const *) rightop;
276 : :
277 : : /*
278 : : * Try to extract a fixed prefix from the pattern.
279 : : */
280 : 6893 : pstatus = pattern_fixed_prefix(patt, ptype, expr_coll,
281 : : &prefix, NULL);
282 : :
283 : : /* fail if no fixed prefix */
284 [ + + ]: 6893 : if (pstatus == Pattern_Prefix_None)
285 : 241 : return NIL;
286 : :
287 : : /*
288 : : * Identify the operators we want to use, based on the type of the
289 : : * left-hand argument. Usually these are just the type's regular
290 : : * comparison operators, but if we are considering one of the semi-legacy
291 : : * "pattern" opclasses, use the "pattern" operators instead. Those are
292 : : * not collation-sensitive but always use C collation, as we want. The
293 : : * selected operators also determine the needed type of the prefix
294 : : * constant.
295 : : */
296 : 6652 : ldatatype = exprType(leftop);
297 [ + + + - : 6652 : switch (ldatatype)
- ]
298 : : {
299 : 74 : case TEXTOID:
300 [ - + ]: 74 : if (opfamily == TEXT_PATTERN_BTREE_FAM_OID)
301 : : {
302 : 0 : eqopr = TextEqualOperator;
303 : 0 : ltopr = TextPatternLessOperator;
304 : 0 : geopr = TextPatternGreaterEqualOperator;
305 : 0 : collation_aware = false;
306 : : }
307 [ + + ]: 74 : else if (opfamily == TEXT_SPGIST_FAM_OID)
308 : : {
309 : 20 : eqopr = TextEqualOperator;
310 : 20 : ltopr = TextPatternLessOperator;
311 : 20 : geopr = TextPatternGreaterEqualOperator;
312 : : /* This opfamily has direct support for prefixing */
313 : 20 : preopr = TextPrefixOperator;
314 : 20 : collation_aware = false;
315 : : }
316 : : else
317 : : {
318 : 54 : eqopr = TextEqualOperator;
319 : 54 : ltopr = TextLessOperator;
320 : 54 : geopr = TextGreaterEqualOperator;
321 : 54 : collation_aware = true;
322 : : }
323 : 74 : rdatatype = TEXTOID;
324 : 74 : break;
325 : 6558 : case NAMEOID:
326 : :
327 : : /*
328 : : * Note that here, we need the RHS type to be text, so that the
329 : : * comparison value isn't improperly truncated to NAMEDATALEN.
330 : : */
331 : 6558 : eqopr = NameEqualTextOperator;
332 : 6558 : ltopr = NameLessTextOperator;
333 : 6558 : geopr = NameGreaterEqualTextOperator;
334 : 6558 : collation_aware = true;
335 : 6558 : rdatatype = TEXTOID;
336 : 6558 : break;
337 : 20 : case BPCHAROID:
338 [ - + ]: 20 : if (opfamily == BPCHAR_PATTERN_BTREE_FAM_OID)
339 : : {
340 : 0 : eqopr = BpcharEqualOperator;
341 : 0 : ltopr = BpcharPatternLessOperator;
342 : 0 : geopr = BpcharPatternGreaterEqualOperator;
343 : 0 : collation_aware = false;
344 : : }
345 : : else
346 : : {
347 : 20 : eqopr = BpcharEqualOperator;
348 : 20 : ltopr = BpcharLessOperator;
349 : 20 : geopr = BpcharGreaterEqualOperator;
350 : 20 : collation_aware = true;
351 : : }
352 : 20 : rdatatype = BPCHAROID;
353 : 20 : break;
354 : 0 : case BYTEAOID:
355 : 0 : eqopr = ByteaEqualOperator;
356 : 0 : ltopr = ByteaLessOperator;
357 : 0 : geopr = ByteaGreaterEqualOperator;
358 : 0 : collation_aware = false;
359 : 0 : rdatatype = BYTEAOID;
360 : 0 : break;
361 : 0 : default:
362 : : /* Can't get here unless we're attached to the wrong operator */
363 : 0 : return NIL;
364 : : }
365 : :
366 : : /*
367 : : * If necessary, coerce the prefix constant to the right type. The given
368 : : * prefix constant is either text or bytea type, therefore the only case
369 : : * where we need to do anything is when converting text to bpchar. Those
370 : : * two types are binary-compatible, so relabeling the Const node is
371 : : * sufficient.
372 : : */
373 [ + + ]: 6652 : if (prefix->consttype != rdatatype)
374 : : {
375 : : Assert(prefix->consttype == TEXTOID &&
376 : : rdatatype == BPCHAROID);
377 : 20 : prefix->consttype = rdatatype;
378 : : }
379 : :
380 : : /*
381 : : * If we found an exact-match pattern, generate an "=" indexqual.
382 : : *
383 : : * Here and below, check to see whether the desired operator is actually
384 : : * supported by the index opclass, and fail quietly if not. This allows
385 : : * us to not be concerned with specific opclasses (except for the legacy
386 : : * "pattern" cases); any index that correctly implements the operators
387 : : * will work.
388 : : *
389 : : * This case will work for LIKE/regex expressions with nondeterministic
390 : : * collation, so long as the index's collation is the same. If the
391 : : * expression's collation is deterministic, we can even use an index whose
392 : : * collation differs from the expression's. All deterministic collations
393 : : * agree on equality (it's bitwise), while we assume that an index with
394 : : * nondeterministic collation will return a superset of the bitwise-equal
395 : : * entries. Since the "=" indexqual is marked as lossy by default, we'll
396 : : * apply the LIKE/regex operator as a recheck, and that will filter out
397 : : * any non-matching entries.
398 : : */
399 [ + + ]: 6652 : if (pstatus == Pattern_Prefix_Exact)
400 : : {
401 [ + + ]: 5539 : if (!op_in_opfamily(eqopr, opfamily))
402 : 10 : return NIL;
403 [ + + + - : 5529 : if (indexcollation != expr_coll && NONDETERMINISTIC(expr_coll))
- + ]
404 : 0 : return NIL;
405 : 5529 : expr = make_opclause(eqopr, BOOLOID, false,
406 : : (Expr *) leftop, (Expr *) prefix,
407 : : InvalidOid, indexcollation);
408 : 5529 : result = list_make1(expr);
409 : 5529 : return result;
410 : : }
411 : :
412 : : /*
413 : : * Anything other than Pattern_Prefix_Exact is not supported if the
414 : : * expression collation is nondeterministic. The optimized equality or
415 : : * prefix tests use bytewise comparisons, which is not consistent with
416 : : * nondeterministic collations.
417 : : */
418 [ + - + + ]: 1113 : if (NONDETERMINISTIC(expr_coll))
419 : 5 : return NIL;
420 : :
421 : : /*
422 : : * Otherwise, we have a nonempty required prefix of the values. Some
423 : : * opclasses support prefix checks directly, otherwise we'll try to
424 : : * generate a range constraint.
425 : : */
426 [ + + + - ]: 1108 : if (OidIsValid(preopr) && op_in_opfamily(preopr, opfamily))
427 : : {
428 : 20 : expr = make_opclause(preopr, BOOLOID, false,
429 : : (Expr *) leftop, (Expr *) prefix,
430 : : InvalidOid, indexcollation);
431 : 20 : result = list_make1(expr);
432 : 20 : return result;
433 : : }
434 : :
435 : : /*
436 : : * Since we need a range constraint, it's only going to work reliably if
437 : : * the index is collation-insensitive or has "C" collation. Note that
438 : : * here we are looking at the index's collation, not the expression's
439 : : * collation -- this test is *not* dependent on the LIKE/regex operator's
440 : : * collation.
441 : : */
442 [ + - ]: 1088 : if (collation_aware &&
443 [ + + ]: 1088 : !pg_newlocale_from_collation(indexcollation)->collate_is_c)
444 : 9 : return NIL;
445 : :
446 : : /*
447 : : * We can always say "x >= prefix".
448 : : */
449 [ + + ]: 1079 : if (!op_in_opfamily(geopr, opfamily))
450 : 10 : return NIL;
451 : 1069 : expr = make_opclause(geopr, BOOLOID, false,
452 : : (Expr *) leftop, (Expr *) prefix,
453 : : InvalidOid, indexcollation);
454 : 1069 : result = list_make1(expr);
455 : :
456 : : /*-------
457 : : * If we can create a string larger than the prefix, we can say
458 : : * "x < greaterstr". NB: we rely on make_greater_string() to generate
459 : : * a guaranteed-greater string, not just a probably-greater string.
460 : : * In general this is only guaranteed in C locale, so we'd better be
461 : : * using a C-locale index collation.
462 : : *-------
463 : : */
464 [ - + ]: 1069 : if (!op_in_opfamily(ltopr, opfamily))
465 : 0 : return result;
466 : 1069 : fmgr_info(get_opcode(ltopr), <proc);
467 : 1069 : greaterstr = make_greater_string(prefix, <proc, indexcollation);
468 [ + - ]: 1069 : if (greaterstr)
469 : : {
470 : 1069 : expr = make_opclause(ltopr, BOOLOID, false,
471 : : (Expr *) leftop, (Expr *) greaterstr,
472 : : InvalidOid, indexcollation);
473 : 1069 : result = lappend(result, expr);
474 : : }
475 : :
476 : 1069 : return result;
477 : : }
478 : :
479 : :
480 : : /*
481 : : * patternsel_common - generic code for pattern-match restriction selectivity.
482 : : *
483 : : * To support using this from either the operator or function paths, caller
484 : : * may pass either operator OID or underlying function OID; we look up the
485 : : * latter from the former if needed. (We could just have patternsel() call
486 : : * get_opcode(), but the work would be wasted if we don't have a need to
487 : : * compare a fixed prefix to the pg_statistic data.)
488 : : *
489 : : * Note that oprid and/or opfuncid should be for the positive-match operator
490 : : * even when negate is true.
491 : : */
492 : : static double
493 : 9506 : patternsel_common(PlannerInfo *root,
494 : : Oid oprid,
495 : : Oid opfuncid,
496 : : List *args,
497 : : int varRelid,
498 : : Oid collation,
499 : : Pattern_Type ptype,
500 : : bool negate)
501 : : {
502 : : VariableStatData vardata;
503 : : Node *other;
504 : : bool varonleft;
505 : : Datum constval;
506 : : Oid consttype;
507 : : Oid vartype;
508 : : Oid rdatatype;
509 : : Oid eqopr;
510 : : Oid ltopr;
511 : : Oid geopr;
512 : : Pattern_Prefix_Status pstatus;
513 : : Const *patt;
514 : 9506 : Const *prefix = NULL;
515 : 9506 : Selectivity rest_selec = 0;
516 : 9506 : double nullfrac = 0.0;
517 : : double result;
518 : :
519 : : /*
520 : : * Initialize result to the appropriate default estimate depending on
521 : : * whether it's a match or not-match operator.
522 : : */
523 [ + + ]: 9506 : if (negate)
524 : 1589 : result = 1.0 - DEFAULT_MATCH_SEL;
525 : : else
526 : 7917 : result = DEFAULT_MATCH_SEL;
527 : :
528 : : /*
529 : : * If expression is not variable op constant, then punt and return the
530 : : * default estimate.
531 : : */
532 [ + + ]: 9506 : if (!get_restriction_variable(root, args, varRelid,
533 : : &vardata, &other, &varonleft))
534 : 238 : return result;
535 [ + + - + ]: 9268 : if (!varonleft || !IsA(other, Const))
536 : : {
537 [ - + ]: 25 : ReleaseVariableStats(vardata);
538 : 25 : return result;
539 : : }
540 : :
541 : : /*
542 : : * If the constant is NULL, assume operator is strict and return zero, ie,
543 : : * operator will never return TRUE. (It's zero even for a negator op.)
544 : : */
545 [ - + ]: 9243 : if (((Const *) other)->constisnull)
546 : : {
547 [ # # ]: 0 : ReleaseVariableStats(vardata);
548 : 0 : return 0.0;
549 : : }
550 : 9243 : constval = ((Const *) other)->constvalue;
551 : 9243 : consttype = ((Const *) other)->consttype;
552 : :
553 : : /*
554 : : * The right-hand const is type text or bytea for all supported operators.
555 : : * We do not expect to see binary-compatible types here, since
556 : : * const-folding should have relabeled the const to exactly match the
557 : : * operator's declared type.
558 : : */
559 [ + + + + ]: 9243 : if (consttype != TEXTOID && consttype != BYTEAOID)
560 : : {
561 [ - + ]: 12 : ReleaseVariableStats(vardata);
562 : 12 : return result;
563 : : }
564 : :
565 : : /*
566 : : * Similarly, the exposed type of the left-hand side should be one of
567 : : * those we know. (Do not look at vardata.atttype, which might be
568 : : * something binary-compatible but different.) We can use it to identify
569 : : * the comparison operators and the required type of the comparison
570 : : * constant, much as in match_pattern_prefix().
571 : : */
572 : 9231 : vartype = vardata.vartype;
573 : :
574 [ + + + + : 9231 : switch (vartype)
+ ]
575 : : {
576 : 1183 : case TEXTOID:
577 : 1183 : eqopr = TextEqualOperator;
578 : 1183 : ltopr = TextLessOperator;
579 : 1183 : geopr = TextGreaterEqualOperator;
580 : 1183 : rdatatype = TEXTOID;
581 : 1183 : break;
582 : 7973 : case NAMEOID:
583 : :
584 : : /*
585 : : * Note that here, we need the RHS type to be text, so that the
586 : : * comparison value isn't improperly truncated to NAMEDATALEN.
587 : : */
588 : 7973 : eqopr = NameEqualTextOperator;
589 : 7973 : ltopr = NameLessTextOperator;
590 : 7973 : geopr = NameGreaterEqualTextOperator;
591 : 7973 : rdatatype = TEXTOID;
592 : 7973 : break;
593 : 68 : case BPCHAROID:
594 : 68 : eqopr = BpcharEqualOperator;
595 : 68 : ltopr = BpcharLessOperator;
596 : 68 : geopr = BpcharGreaterEqualOperator;
597 : 68 : rdatatype = BPCHAROID;
598 : 68 : break;
599 : 5 : case BYTEAOID:
600 : 5 : eqopr = ByteaEqualOperator;
601 : 5 : ltopr = ByteaLessOperator;
602 : 5 : geopr = ByteaGreaterEqualOperator;
603 : 5 : rdatatype = BYTEAOID;
604 : 5 : break;
605 : 2 : default:
606 : : /* Can't get here unless we're attached to the wrong operator */
607 [ - + ]: 2 : ReleaseVariableStats(vardata);
608 : 2 : return result;
609 : : }
610 : :
611 : : /*
612 : : * Grab the nullfrac for use below.
613 : : */
614 [ + + ]: 9229 : if (HeapTupleIsValid(vardata.statsTuple))
615 : : {
616 : : Form_pg_statistic stats;
617 : :
618 : 7570 : stats = (Form_pg_statistic) GETSTRUCT(vardata.statsTuple);
619 : 7570 : nullfrac = stats->stanullfrac;
620 : : }
621 : :
622 : : /*
623 : : * Pull out any fixed prefix implied by the pattern, and estimate the
624 : : * fractional selectivity of the remainder of the pattern. Unlike many
625 : : * other selectivity estimators, we use the pattern operator's actual
626 : : * collation for this step. This is not because we expect the collation
627 : : * to make a big difference in the selectivity estimate (it seldom would),
628 : : * but because we want to be sure we cache compiled regexps under the
629 : : * right cache key, so that they can be re-used at runtime.
630 : : */
631 : 9229 : patt = (Const *) other;
632 : 9229 : pstatus = pattern_fixed_prefix(patt, ptype, collation,
633 : : &prefix, &rest_selec);
634 : :
635 : : /*
636 : : * If necessary, coerce the prefix constant to the right type. The only
637 : : * case where we need to do anything is when converting text to bpchar.
638 : : * Those two types are binary-compatible, so relabeling the Const node is
639 : : * sufficient.
640 : : */
641 [ + + + + ]: 9213 : if (prefix && prefix->consttype != rdatatype)
642 : : {
643 : : Assert(prefix->consttype == TEXTOID &&
644 : : rdatatype == BPCHAROID);
645 : 30 : prefix->consttype = rdatatype;
646 : : }
647 : :
648 [ + + ]: 9213 : if (pstatus == Pattern_Prefix_Exact)
649 : : {
650 : : /*
651 : : * Pattern specifies an exact match, so estimate as for '='
652 : : */
653 : 5711 : result = var_eq_const(&vardata, eqopr, collation, prefix->constvalue,
654 : : false, true, false);
655 : : }
656 : : else
657 : : {
658 : : /*
659 : : * Not exact-match pattern. If we have a sufficiently large
660 : : * histogram, estimate selectivity for the histogram part of the
661 : : * population by counting matches in the histogram. If not, estimate
662 : : * selectivity of the fixed prefix and remainder of pattern
663 : : * separately, then combine the two to get an estimate of the
664 : : * selectivity for the part of the column population represented by
665 : : * the histogram. (For small histograms, we combine these
666 : : * approaches.)
667 : : *
668 : : * We then add up data for any most-common-values values; these are
669 : : * not in the histogram population, and we can get exact answers for
670 : : * them by applying the pattern operator, so there's no reason to
671 : : * approximate. (If the MCVs cover a significant part of the total
672 : : * population, this gives us a big leg up in accuracy.)
673 : : */
674 : : Selectivity selec;
675 : : int hist_size;
676 : : FmgrInfo opproc;
677 : : double mcv_selec,
678 : : sumcommon;
679 : :
680 : : /* Try to use the histogram entries to get selectivity */
681 [ + + ]: 3502 : if (!OidIsValid(opfuncid))
682 : 3482 : opfuncid = get_opcode(oprid);
683 : 3502 : fmgr_info(opfuncid, &opproc);
684 : :
685 : 3502 : selec = histogram_selectivity(&vardata, &opproc, collation,
686 : : constval, true,
687 : : 10, 1, &hist_size);
688 : :
689 : : /* If not at least 100 entries, use the heuristic method */
690 [ + + ]: 3502 : if (hist_size < 100)
691 : : {
692 : : Selectivity heursel;
693 : : Selectivity prefixsel;
694 : :
695 [ + + ]: 2392 : if (pstatus == Pattern_Prefix_Partial)
696 : 1829 : prefixsel = prefix_selectivity(root, &vardata,
697 : : eqopr, ltopr, geopr,
698 : : collation,
699 : : prefix);
700 : : else
701 : 563 : prefixsel = 1.0;
702 : 2392 : heursel = prefixsel * rest_selec;
703 : :
704 [ + + ]: 2392 : if (selec < 0) /* fewer than 10 histogram entries? */
705 : 2156 : selec = heursel;
706 : : else
707 : : {
708 : : /*
709 : : * For histogram sizes from 10 to 100, we combine the
710 : : * histogram and heuristic selectivities, putting increasingly
711 : : * more trust in the histogram for larger sizes.
712 : : */
713 : 236 : double hist_weight = hist_size / 100.0;
714 : :
715 : 236 : selec = selec * hist_weight + heursel * (1.0 - hist_weight);
716 : : }
717 : : }
718 : :
719 : : /* In any case, don't believe extremely small or large estimates. */
720 [ + + ]: 3502 : if (selec < 0.0001)
721 : 1271 : selec = 0.0001;
722 [ + + ]: 2231 : else if (selec > 0.9999)
723 : 86 : selec = 0.9999;
724 : :
725 : : /*
726 : : * If we have most-common-values info, add up the fractions of the MCV
727 : : * entries that satisfy MCV OP PATTERN. These fractions contribute
728 : : * directly to the result selectivity. Also add up the total fraction
729 : : * represented by MCV entries.
730 : : */
731 : 3502 : mcv_selec = mcv_selectivity(&vardata, &opproc, collation,
732 : : constval, true,
733 : : &sumcommon);
734 : :
735 : : /*
736 : : * Now merge the results from the MCV and histogram calculations,
737 : : * realizing that the histogram covers only the non-null values that
738 : : * are not listed in MCV.
739 : : */
740 : 3502 : selec *= 1.0 - nullfrac - sumcommon;
741 : 3502 : selec += mcv_selec;
742 : 3502 : result = selec;
743 : : }
744 : :
745 : : /* now adjust if we wanted not-match rather than match */
746 [ + + ]: 9213 : if (negate)
747 : 1345 : result = 1.0 - result - nullfrac;
748 : :
749 : : /* result should be in range, but make sure... */
750 [ - + + + ]: 9213 : CLAMP_PROBABILITY(result);
751 : :
752 [ + + ]: 9213 : if (prefix)
753 : : {
754 : 8734 : pfree(DatumGetPointer(prefix->constvalue));
755 : 8734 : pfree(prefix);
756 : : }
757 : :
758 [ + + ]: 9213 : ReleaseVariableStats(vardata);
759 : :
760 : 9213 : return result;
761 : : }
762 : :
763 : : /*
764 : : * Fix impedance mismatch between SQL-callable functions and patternsel_common
765 : : */
766 : : static double
767 : 9486 : patternsel(PG_FUNCTION_ARGS, Pattern_Type ptype, bool negate)
768 : : {
769 : 9486 : PlannerInfo *root = (PlannerInfo *) PG_GETARG_POINTER(0);
770 : 9486 : Oid operator = PG_GETARG_OID(1);
771 : 9486 : List *args = (List *) PG_GETARG_POINTER(2);
772 : 9486 : int varRelid = PG_GETARG_INT32(3);
773 : 9486 : Oid collation = PG_GET_COLLATION();
774 : :
775 : : /*
776 : : * If this is for a NOT LIKE or similar operator, get the corresponding
777 : : * positive-match operator and work with that.
778 : : */
779 [ + + ]: 9486 : if (negate)
780 : : {
781 : 1589 : operator = get_negator(operator);
782 [ - + ]: 1589 : if (!OidIsValid(operator))
783 [ # # ]: 0 : elog(ERROR, "patternsel called for operator without a negator");
784 : : }
785 : :
786 : 9486 : return patternsel_common(root,
787 : : operator,
788 : : InvalidOid,
789 : : args,
790 : : varRelid,
791 : : collation,
792 : : ptype,
793 : : negate);
794 : : }
795 : :
796 : : /*
797 : : * regexeqsel - Selectivity of regular-expression pattern match.
798 : : */
799 : : Datum
800 : 6450 : regexeqsel(PG_FUNCTION_ARGS)
801 : : {
802 : 6450 : PG_RETURN_FLOAT8(patternsel(fcinfo, Pattern_Type_Regex, false));
803 : : }
804 : :
805 : : /*
806 : : * icregexeqsel - Selectivity of case-insensitive regex match.
807 : : */
808 : : Datum
809 : 50 : icregexeqsel(PG_FUNCTION_ARGS)
810 : : {
811 : 50 : PG_RETURN_FLOAT8(patternsel(fcinfo, Pattern_Type_Regex_IC, false));
812 : : }
813 : :
814 : : /*
815 : : * likesel - Selectivity of LIKE pattern match.
816 : : */
817 : : Datum
818 : 1255 : likesel(PG_FUNCTION_ARGS)
819 : : {
820 : 1255 : PG_RETURN_FLOAT8(patternsel(fcinfo, Pattern_Type_Like, false));
821 : : }
822 : :
823 : : /*
824 : : * prefixsel - selectivity of prefix operator
825 : : */
826 : : Datum
827 : 45 : prefixsel(PG_FUNCTION_ARGS)
828 : : {
829 : 45 : PG_RETURN_FLOAT8(patternsel(fcinfo, Pattern_Type_Prefix, false));
830 : : }
831 : :
832 : : /*
833 : : *
834 : : * iclikesel - Selectivity of ILIKE pattern match.
835 : : */
836 : : Datum
837 : 97 : iclikesel(PG_FUNCTION_ARGS)
838 : : {
839 : 97 : PG_RETURN_FLOAT8(patternsel(fcinfo, Pattern_Type_Like_IC, false));
840 : : }
841 : :
842 : : /*
843 : : * regexnesel - Selectivity of regular-expression pattern non-match.
844 : : */
845 : : Datum
846 : 1473 : regexnesel(PG_FUNCTION_ARGS)
847 : : {
848 : 1473 : PG_RETURN_FLOAT8(patternsel(fcinfo, Pattern_Type_Regex, true));
849 : : }
850 : :
851 : : /*
852 : : * icregexnesel - Selectivity of case-insensitive regex non-match.
853 : : */
854 : : Datum
855 : 12 : icregexnesel(PG_FUNCTION_ARGS)
856 : : {
857 : 12 : PG_RETURN_FLOAT8(patternsel(fcinfo, Pattern_Type_Regex_IC, true));
858 : : }
859 : :
860 : : /*
861 : : * nlikesel - Selectivity of LIKE pattern non-match.
862 : : */
863 : : Datum
864 : 100 : nlikesel(PG_FUNCTION_ARGS)
865 : : {
866 : 100 : PG_RETURN_FLOAT8(patternsel(fcinfo, Pattern_Type_Like, true));
867 : : }
868 : :
869 : : /*
870 : : * icnlikesel - Selectivity of ILIKE pattern non-match.
871 : : */
872 : : Datum
873 : 4 : icnlikesel(PG_FUNCTION_ARGS)
874 : : {
875 : 4 : PG_RETURN_FLOAT8(patternsel(fcinfo, Pattern_Type_Like_IC, true));
876 : : }
877 : :
878 : : /*
879 : : * patternjoinsel - Generic code for pattern-match join selectivity.
880 : : */
881 : : static double
882 : 118 : patternjoinsel(PG_FUNCTION_ARGS, Pattern_Type ptype, bool negate)
883 : : {
884 : : /* For the moment we just punt. */
885 [ - + ]: 118 : return negate ? (1.0 - DEFAULT_MATCH_SEL) : DEFAULT_MATCH_SEL;
886 : : }
887 : :
888 : : /*
889 : : * regexeqjoinsel - Join selectivity of regular-expression pattern match.
890 : : */
891 : : Datum
892 : 118 : regexeqjoinsel(PG_FUNCTION_ARGS)
893 : : {
894 : 118 : PG_RETURN_FLOAT8(patternjoinsel(fcinfo, Pattern_Type_Regex, false));
895 : : }
896 : :
897 : : /*
898 : : * icregexeqjoinsel - Join selectivity of case-insensitive regex match.
899 : : */
900 : : Datum
901 : 0 : icregexeqjoinsel(PG_FUNCTION_ARGS)
902 : : {
903 : 0 : PG_RETURN_FLOAT8(patternjoinsel(fcinfo, Pattern_Type_Regex_IC, false));
904 : : }
905 : :
906 : : /*
907 : : * likejoinsel - Join selectivity of LIKE pattern match.
908 : : */
909 : : Datum
910 : 0 : likejoinsel(PG_FUNCTION_ARGS)
911 : : {
912 : 0 : PG_RETURN_FLOAT8(patternjoinsel(fcinfo, Pattern_Type_Like, false));
913 : : }
914 : :
915 : : /*
916 : : * prefixjoinsel - Join selectivity of prefix operator
917 : : */
918 : : Datum
919 : 0 : prefixjoinsel(PG_FUNCTION_ARGS)
920 : : {
921 : 0 : PG_RETURN_FLOAT8(patternjoinsel(fcinfo, Pattern_Type_Prefix, false));
922 : : }
923 : :
924 : : /*
925 : : * iclikejoinsel - Join selectivity of ILIKE pattern match.
926 : : */
927 : : Datum
928 : 0 : iclikejoinsel(PG_FUNCTION_ARGS)
929 : : {
930 : 0 : PG_RETURN_FLOAT8(patternjoinsel(fcinfo, Pattern_Type_Like_IC, false));
931 : : }
932 : :
933 : : /*
934 : : * regexnejoinsel - Join selectivity of regex non-match.
935 : : */
936 : : Datum
937 : 0 : regexnejoinsel(PG_FUNCTION_ARGS)
938 : : {
939 : 0 : PG_RETURN_FLOAT8(patternjoinsel(fcinfo, Pattern_Type_Regex, true));
940 : : }
941 : :
942 : : /*
943 : : * icregexnejoinsel - Join selectivity of case-insensitive regex non-match.
944 : : */
945 : : Datum
946 : 0 : icregexnejoinsel(PG_FUNCTION_ARGS)
947 : : {
948 : 0 : PG_RETURN_FLOAT8(patternjoinsel(fcinfo, Pattern_Type_Regex_IC, true));
949 : : }
950 : :
951 : : /*
952 : : * nlikejoinsel - Join selectivity of LIKE pattern non-match.
953 : : */
954 : : Datum
955 : 0 : nlikejoinsel(PG_FUNCTION_ARGS)
956 : : {
957 : 0 : PG_RETURN_FLOAT8(patternjoinsel(fcinfo, Pattern_Type_Like, true));
958 : : }
959 : :
960 : : /*
961 : : * icnlikejoinsel - Join selectivity of ILIKE pattern non-match.
962 : : */
963 : : Datum
964 : 0 : icnlikejoinsel(PG_FUNCTION_ARGS)
965 : : {
966 : 0 : PG_RETURN_FLOAT8(patternjoinsel(fcinfo, Pattern_Type_Like_IC, true));
967 : : }
968 : :
969 : :
970 : : /*-------------------------------------------------------------------------
971 : : *
972 : : * Pattern analysis functions
973 : : *
974 : : * These routines support analysis of LIKE and regular-expression patterns
975 : : * by the planner/optimizer. It's important that they agree with the
976 : : * regular-expression code in backend/regex/ and the LIKE code in
977 : : * backend/utils/adt/like.c. Also, the computation of the fixed prefix
978 : : * must be conservative: if we report a string longer than the true fixed
979 : : * prefix, the query may produce actually wrong answers, rather than just
980 : : * getting a bad selectivity estimate!
981 : : *
982 : : *-------------------------------------------------------------------------
983 : : */
984 : :
985 : : /*
986 : : * Extract the fixed prefix, if any, for a pattern.
987 : : *
988 : : * *prefix is set to a palloc'd prefix string (in the form of a Const node),
989 : : * or to NULL if no fixed prefix exists for the pattern.
990 : : * If rest_selec is not NULL, *rest_selec is set to an estimate of the
991 : : * selectivity of the remainder of the pattern (without any fixed prefix).
992 : : * The prefix Const has the same type (TEXT or BYTEA) as the input pattern.
993 : : *
994 : : * The return value distinguishes no fixed prefix, a partial prefix,
995 : : * or an exact-match-only pattern.
996 : : */
997 : :
998 : : static Pattern_Prefix_Status
999 : 2224 : like_fixed_prefix(Const *patt_const, Const **prefix_const,
1000 : : Selectivity *rest_selec)
1001 : : {
1002 : : char *match;
1003 : : char *patt;
1004 : : int pattlen;
1005 : 2224 : Oid typeid = patt_const->consttype;
1006 : : int pos,
1007 : : match_pos;
1008 : :
1009 : : /* the right-hand const is type text or bytea */
1010 : : Assert(typeid == BYTEAOID || typeid == TEXTOID);
1011 : :
1012 [ + + ]: 2224 : if (typeid != BYTEAOID)
1013 : : {
1014 : 2214 : patt = TextDatumGetCString(patt_const->constvalue);
1015 : 2214 : pattlen = strlen(patt);
1016 : : }
1017 : : else
1018 : : {
1019 : 10 : bytea *bstr = DatumGetByteaPP(patt_const->constvalue);
1020 : :
1021 : 10 : pattlen = VARSIZE_ANY_EXHDR(bstr);
1022 : 10 : patt = (char *) palloc(pattlen);
1023 : 10 : memcpy(patt, VARDATA_ANY(bstr), pattlen);
1024 : : Assert(bstr == DatumGetPointer(patt_const->constvalue));
1025 : : }
1026 : :
1027 : 2224 : match = palloc(pattlen + 1);
1028 : 2224 : match_pos = 0;
1029 [ + + ]: 13046 : for (pos = 0; pos < pattlen; pos++)
1030 : : {
1031 : : /* % and _ are wildcard characters in LIKE */
1032 [ + + ]: 12939 : if (patt[pos] == '%' ||
1033 [ + + ]: 11736 : patt[pos] == '_')
1034 : : break;
1035 : :
1036 : : /* Backslash escapes the next character */
1037 [ + + ]: 10822 : if (patt[pos] == '\\')
1038 : : {
1039 : 227 : pos++;
1040 [ - + ]: 227 : if (pos >= pattlen)
1041 : 0 : break;
1042 : : }
1043 : :
1044 : 10822 : match[match_pos++] = patt[pos];
1045 : : }
1046 : :
1047 : 2224 : match[match_pos] = '\0';
1048 : :
1049 [ + + ]: 2224 : if (typeid != BYTEAOID)
1050 : 2214 : *prefix_const = string_to_const(match, typeid);
1051 : : else
1052 : 10 : *prefix_const = string_to_bytea_const(match, match_pos);
1053 : :
1054 [ + + ]: 2224 : if (rest_selec != NULL)
1055 : 1355 : *rest_selec = like_selectivity(&patt[pos], pattlen - pos, false);
1056 : :
1057 : 2224 : pfree(patt);
1058 : 2224 : pfree(match);
1059 : :
1060 : : /* in LIKE, an empty pattern is an exact match! */
1061 [ + + ]: 2224 : if (pos == pattlen)
1062 : 107 : return Pattern_Prefix_Exact; /* reached end of pattern, so exact */
1063 : :
1064 [ + + ]: 2117 : if (match_pos > 0)
1065 : 1881 : return Pattern_Prefix_Partial;
1066 : :
1067 : 236 : return Pattern_Prefix_None;
1068 : : }
1069 : :
1070 : : /*
1071 : : * Case-insensitive variant of like_fixed_prefix(). Multibyte and
1072 : : * locale-aware for detecting cased characters.
1073 : : */
1074 : : static Pattern_Prefix_Status
1075 : 189 : like_fixed_prefix_ci(Const *patt_const, Oid collation, Const **prefix_const,
1076 : : Selectivity *rest_selec)
1077 : : {
1078 : 189 : text *val = DatumGetTextPP(patt_const->constvalue);
1079 : 189 : Oid typeid = patt_const->consttype;
1080 : 189 : int nbytes = VARSIZE_ANY_EXHDR(val);
1081 : : int wpos;
1082 : : pg_wchar *wpatt;
1083 : : int wpattlen;
1084 : : pg_wchar *wmatch;
1085 : 189 : int wmatch_pos = 0;
1086 : : char *match;
1087 : : int match_mblen;
1088 : 189 : pg_locale_t locale = 0;
1089 : :
1090 : : /* the right-hand const is type text or bytea */
1091 : : Assert(typeid == BYTEAOID || typeid == TEXTOID);
1092 : :
1093 [ - + ]: 189 : if (typeid == BYTEAOID)
1094 [ # # ]: 0 : ereport(ERROR,
1095 : : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1096 : : errmsg("case insensitive matching not supported on type bytea")));
1097 : :
1098 [ - + ]: 189 : if (!OidIsValid(collation))
1099 : : {
1100 : : /*
1101 : : * This typically means that the parser could not resolve a conflict
1102 : : * of implicit collations, so report it that way.
1103 : : */
1104 [ # # ]: 0 : ereport(ERROR,
1105 : : (errcode(ERRCODE_INDETERMINATE_COLLATION),
1106 : : errmsg("could not determine which collation to use for ILIKE"),
1107 : : errhint("Use the COLLATE clause to set the collation explicitly.")));
1108 : : }
1109 : :
1110 : 189 : locale = pg_newlocale_from_collation(collation);
1111 : :
1112 : 189 : wpatt = palloc((nbytes + 1) * sizeof(pg_wchar));
1113 : 189 : wpattlen = pg_mb2wchar_with_len(VARDATA_ANY(val), wpatt, nbytes);
1114 : :
1115 : 189 : wmatch = palloc((nbytes + 1) * sizeof(pg_wchar));
1116 [ + - ]: 269 : for (wpos = 0; wpos < wpattlen; wpos++)
1117 : : {
1118 : : /* % and _ are wildcard characters in LIKE */
1119 [ + + ]: 269 : if (wpatt[wpos] == '%' ||
1120 [ + - ]: 219 : wpatt[wpos] == '_')
1121 : : break;
1122 : :
1123 : : /* Backslash escapes the next character */
1124 [ - + ]: 219 : if (wpatt[wpos] == '\\')
1125 : : {
1126 : 0 : wpos++;
1127 [ # # ]: 0 : if (wpos >= wpattlen)
1128 : 0 : break;
1129 : : }
1130 : :
1131 : : /*
1132 : : * For ILIKE, stop if it's a case-varying character (it's sort of a
1133 : : * wildcard).
1134 : : */
1135 [ + + ]: 219 : if (pg_iswcased(wpatt[wpos], locale))
1136 : 139 : break;
1137 : :
1138 : 80 : wmatch[wmatch_pos++] = wpatt[wpos];
1139 : : }
1140 : :
1141 : 189 : wmatch[wmatch_pos] = '\0';
1142 : :
1143 : 189 : match = palloc(pg_database_encoding_max_length() * wmatch_pos + 1);
1144 : 189 : match_mblen = pg_wchar2mb_with_len(wmatch, match, wmatch_pos);
1145 : 189 : match[match_mblen] = '\0';
1146 : 189 : pfree(wmatch);
1147 : :
1148 : 189 : *prefix_const = string_to_const(match, TEXTOID);
1149 : 189 : pfree(match);
1150 : :
1151 [ + + ]: 189 : if (rest_selec != NULL)
1152 : : {
1153 : 93 : int wrestlen = wpattlen - wmatch_pos;
1154 : : char *rest;
1155 : : int rest_mblen;
1156 : :
1157 : 93 : rest = palloc(pg_database_encoding_max_length() * wrestlen + 1);
1158 : 93 : rest_mblen = pg_wchar2mb_with_len(&wpatt[wmatch_pos], rest, wrestlen);
1159 : :
1160 : 93 : *rest_selec = like_selectivity(rest, rest_mblen, true);
1161 : 93 : pfree(rest);
1162 : : }
1163 : :
1164 : 189 : pfree(wpatt);
1165 : :
1166 : : /* in LIKE, an empty pattern is an exact match! */
1167 [ - + ]: 189 : if (wpos == wpattlen)
1168 : 0 : return Pattern_Prefix_Exact; /* reached end of pattern, so exact */
1169 : :
1170 [ + + ]: 189 : if (wmatch_pos > 0)
1171 : 40 : return Pattern_Prefix_Partial;
1172 : :
1173 : 149 : return Pattern_Prefix_None;
1174 : : }
1175 : :
1176 : : static Pattern_Prefix_Status
1177 : 13624 : regex_fixed_prefix(Const *patt_const, bool case_insensitive, Oid collation,
1178 : : Const **prefix_const, Selectivity *rest_selec)
1179 : : {
1180 : 13624 : Oid typeid = patt_const->consttype;
1181 : : char *prefix;
1182 : : bool exact;
1183 : :
1184 : : /*
1185 : : * Should be unnecessary, there are no bytea regex operators defined. As
1186 : : * such, it should be noted that the rest of this function has *not* been
1187 : : * made safe for binary (possibly NULL containing) strings.
1188 : : */
1189 [ - + ]: 13624 : if (typeid == BYTEAOID)
1190 [ # # ]: 0 : ereport(ERROR,
1191 : : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1192 : : errmsg("regular-expression matching not supported on type bytea")));
1193 : :
1194 : : /* Use the regexp machinery to extract the prefix, if any */
1195 : 13624 : prefix = regexp_fixed_prefix(DatumGetTextPP(patt_const->constvalue),
1196 : : case_insensitive, collation,
1197 : : &exact);
1198 : :
1199 [ + + ]: 13608 : if (prefix == NULL)
1200 : : {
1201 : 587 : *prefix_const = NULL;
1202 : :
1203 [ + + ]: 587 : if (rest_selec != NULL)
1204 : : {
1205 : 479 : char *patt = TextDatumGetCString(patt_const->constvalue);
1206 : :
1207 : 479 : *rest_selec = regex_selectivity(patt, strlen(patt),
1208 : : case_insensitive,
1209 : : 0);
1210 : 479 : pfree(patt);
1211 : : }
1212 : :
1213 : 587 : return Pattern_Prefix_None;
1214 : : }
1215 : :
1216 : 13021 : *prefix_const = string_to_const(prefix, typeid);
1217 : :
1218 [ + + ]: 13021 : if (rest_selec != NULL)
1219 : : {
1220 [ + + ]: 7221 : if (exact)
1221 : : {
1222 : : /* Exact match, so there's no additional selectivity */
1223 : 5649 : *rest_selec = 1.0;
1224 : : }
1225 : : else
1226 : : {
1227 : 1572 : char *patt = TextDatumGetCString(patt_const->constvalue);
1228 : :
1229 : 3144 : *rest_selec = regex_selectivity(patt, strlen(patt),
1230 : : case_insensitive,
1231 : 1572 : strlen(prefix));
1232 : 1572 : pfree(patt);
1233 : : }
1234 : : }
1235 : :
1236 : 13021 : pfree(prefix);
1237 : :
1238 [ + + ]: 13021 : if (exact)
1239 : 11143 : return Pattern_Prefix_Exact; /* pattern specifies exact match */
1240 : : else
1241 : 1878 : return Pattern_Prefix_Partial;
1242 : : }
1243 : :
1244 : : static Pattern_Prefix_Status
1245 : 16122 : pattern_fixed_prefix(Const *patt, Pattern_Type ptype, Oid collation,
1246 : : Const **prefix, Selectivity *rest_selec)
1247 : : {
1248 : : Pattern_Prefix_Status result;
1249 : :
1250 [ + + + + : 16122 : switch (ptype)
+ - ]
1251 : : {
1252 : 2224 : case Pattern_Type_Like:
1253 : 2224 : result = like_fixed_prefix(patt, prefix, rest_selec);
1254 : 2224 : break;
1255 : 189 : case Pattern_Type_Like_IC:
1256 : 189 : result = like_fixed_prefix_ci(patt, collation, prefix,
1257 : : rest_selec);
1258 : 189 : break;
1259 : 13573 : case Pattern_Type_Regex:
1260 : 13573 : result = regex_fixed_prefix(patt, false, collation,
1261 : : prefix, rest_selec);
1262 : 13557 : break;
1263 : 51 : case Pattern_Type_Regex_IC:
1264 : 51 : result = regex_fixed_prefix(patt, true, collation,
1265 : : prefix, rest_selec);
1266 : 51 : break;
1267 : 85 : case Pattern_Type_Prefix:
1268 : : /* Prefix type work is trivial. */
1269 : 85 : result = Pattern_Prefix_Partial;
1270 : 85 : *prefix = makeConst(patt->consttype,
1271 : : patt->consttypmod,
1272 : : patt->constcollid,
1273 : : patt->constlen,
1274 : : datumCopy(patt->constvalue,
1275 : 85 : patt->constbyval,
1276 : : patt->constlen),
1277 : 85 : patt->constisnull,
1278 : 85 : patt->constbyval);
1279 [ + + ]: 85 : if (rest_selec != NULL)
1280 : 65 : *rest_selec = 1.0; /* all */
1281 : 85 : break;
1282 : 0 : default:
1283 [ # # ]: 0 : elog(ERROR, "unrecognized ptype: %d", (int) ptype);
1284 : : result = Pattern_Prefix_None; /* keep compiler quiet */
1285 : : break;
1286 : : }
1287 : 16106 : return result;
1288 : : }
1289 : :
1290 : : /*
1291 : : * Estimate the selectivity of a fixed prefix for a pattern match.
1292 : : *
1293 : : * A fixed prefix "foo" is estimated as the selectivity of the expression
1294 : : * "variable >= 'foo' AND variable < 'fop'".
1295 : : *
1296 : : * The selectivity estimate is with respect to the portion of the column
1297 : : * population represented by the histogram --- the caller must fold this
1298 : : * together with info about MCVs and NULLs.
1299 : : *
1300 : : * We use the given comparison operators and collation to do the estimation.
1301 : : * The given variable and Const must be of the associated datatype(s).
1302 : : *
1303 : : * XXX Note: we make use of the upper bound to estimate operator selectivity
1304 : : * even if the locale is such that we cannot rely on the upper-bound string.
1305 : : * The selectivity only needs to be approximately right anyway, so it seems
1306 : : * more useful to use the upper-bound code than not.
1307 : : */
1308 : : static Selectivity
1309 : 1829 : prefix_selectivity(PlannerInfo *root, VariableStatData *vardata,
1310 : : Oid eqopr, Oid ltopr, Oid geopr,
1311 : : Oid collation,
1312 : : Const *prefixcon)
1313 : : {
1314 : : Selectivity prefixsel;
1315 : : FmgrInfo opproc;
1316 : : Const *greaterstrcon;
1317 : : Selectivity eq_sel;
1318 : :
1319 : : /* Estimate the selectivity of "x >= prefix" */
1320 : 1829 : fmgr_info(get_opcode(geopr), &opproc);
1321 : :
1322 : 1829 : prefixsel = ineq_histogram_selectivity(root, vardata,
1323 : : geopr, &opproc, true, true,
1324 : : collation,
1325 : : prefixcon->constvalue,
1326 : : prefixcon->consttype);
1327 : :
1328 [ + + ]: 1829 : if (prefixsel < 0.0)
1329 : : {
1330 : : /* No histogram is present ... return a suitable default estimate */
1331 : 512 : return DEFAULT_MATCH_SEL;
1332 : : }
1333 : :
1334 : : /*
1335 : : * If we can create a string larger than the prefix, say "x < greaterstr".
1336 : : */
1337 : 1317 : fmgr_info(get_opcode(ltopr), &opproc);
1338 : 1317 : greaterstrcon = make_greater_string(prefixcon, &opproc, collation);
1339 [ + - ]: 1317 : if (greaterstrcon)
1340 : : {
1341 : : Selectivity topsel;
1342 : :
1343 : 1317 : topsel = ineq_histogram_selectivity(root, vardata,
1344 : : ltopr, &opproc, false, false,
1345 : : collation,
1346 : : greaterstrcon->constvalue,
1347 : : greaterstrcon->consttype);
1348 : :
1349 : : /* ineq_histogram_selectivity worked before, it shouldn't fail now */
1350 : : Assert(topsel >= 0.0);
1351 : :
1352 : : /*
1353 : : * Merge the two selectivities in the same way as for a range query
1354 : : * (see clauselist_selectivity()). Note that we don't need to worry
1355 : : * about double-exclusion of nulls, since ineq_histogram_selectivity
1356 : : * doesn't count those anyway.
1357 : : */
1358 : 1317 : prefixsel = topsel + prefixsel - 1.0;
1359 : : }
1360 : :
1361 : : /*
1362 : : * If the prefix is long then the two bounding values might be too close
1363 : : * together for the histogram to distinguish them usefully, resulting in a
1364 : : * zero estimate (plus or minus roundoff error). To avoid returning a
1365 : : * ridiculously small estimate, compute the estimated selectivity for
1366 : : * "variable = 'foo'", and clamp to that. (Obviously, the resultant
1367 : : * estimate should be at least that.)
1368 : : *
1369 : : * We apply this even if we couldn't make a greater string. That case
1370 : : * suggests that the prefix is near the maximum possible, and thus
1371 : : * probably off the end of the histogram, and thus we probably got a very
1372 : : * small estimate from the >= condition; so we still need to clamp.
1373 : : */
1374 : 1317 : eq_sel = var_eq_const(vardata, eqopr, collation, prefixcon->constvalue,
1375 : : false, true, false);
1376 : :
1377 [ + + ]: 1317 : prefixsel = Max(prefixsel, eq_sel);
1378 : :
1379 : 1317 : return prefixsel;
1380 : : }
1381 : :
1382 : :
1383 : : /*
1384 : : * Estimate the selectivity of a pattern of the specified type.
1385 : : * Note that any fixed prefix of the pattern will have been removed already,
1386 : : * so actually we may be looking at just a fragment of the pattern.
1387 : : *
1388 : : * For now, we use a very simplistic approach: fixed characters reduce the
1389 : : * selectivity a good deal, character ranges reduce it a little,
1390 : : * wildcards (such as % for LIKE or .* for regex) increase it.
1391 : : */
1392 : :
1393 : : #define FIXED_CHAR_SEL 0.20 /* about 1/5 */
1394 : : #define CHAR_RANGE_SEL 0.25
1395 : : #define ANY_CHAR_SEL 0.9 /* not 1, since it won't match end-of-string */
1396 : : #define FULL_WILDCARD_SEL 5.0
1397 : : #define PARTIAL_WILDCARD_SEL 2.0
1398 : :
1399 : : static Selectivity
1400 : 1448 : like_selectivity(const char *patt, int pattlen, bool case_insensitive)
1401 : : {
1402 : 1448 : Selectivity sel = 1.0;
1403 : : int pos;
1404 : :
1405 : : /* Skip any leading wildcard; it's already factored into initial sel */
1406 [ + + ]: 2786 : for (pos = 0; pos < pattlen; pos++)
1407 : : {
1408 [ + + + + ]: 2044 : if (patt[pos] != '%' && patt[pos] != '_')
1409 : 706 : break;
1410 : : }
1411 : :
1412 [ + + ]: 5786 : for (; pos < pattlen; pos++)
1413 : : {
1414 : : /* % and _ are wildcard characters in LIKE */
1415 [ + + ]: 4338 : if (patt[pos] == '%')
1416 : 618 : sel *= FULL_WILDCARD_SEL;
1417 [ + + ]: 3720 : else if (patt[pos] == '_')
1418 : 145 : sel *= ANY_CHAR_SEL;
1419 [ + + ]: 3575 : else if (patt[pos] == '\\')
1420 : : {
1421 : : /* Backslash quotes the next character */
1422 : 32 : pos++;
1423 [ - + ]: 32 : if (pos >= pattlen)
1424 : 0 : break;
1425 : 32 : sel *= FIXED_CHAR_SEL;
1426 : : }
1427 : : else
1428 : 3543 : sel *= FIXED_CHAR_SEL;
1429 : : }
1430 : : /* Could get sel > 1 if multiple wildcards */
1431 [ - + ]: 1448 : if (sel > 1.0)
1432 : 0 : sel = 1.0;
1433 : 1448 : return sel;
1434 : : }
1435 : :
1436 : : static Selectivity
1437 : 2397 : regex_selectivity_sub(const char *patt, int pattlen, bool case_insensitive)
1438 : : {
1439 : 2397 : Selectivity sel = 1.0;
1440 : 2397 : int paren_depth = 0;
1441 : 2397 : int paren_pos = 0; /* dummy init to keep compiler quiet */
1442 : : int pos;
1443 : :
1444 : : /* since this function recurses, it could be driven to stack overflow */
1445 : 2397 : check_stack_depth();
1446 : :
1447 [ + + ]: 25956 : for (pos = 0; pos < pattlen; pos++)
1448 : : {
1449 [ + + ]: 23575 : if (patt[pos] == '(')
1450 : : {
1451 [ + + ]: 355 : if (paren_depth == 0)
1452 : 335 : paren_pos = pos; /* remember start of parenthesized item */
1453 : 355 : paren_depth++;
1454 : : }
1455 [ + + + - ]: 23220 : else if (patt[pos] == ')' && paren_depth > 0)
1456 : : {
1457 : 350 : paren_depth--;
1458 [ + + ]: 350 : if (paren_depth == 0)
1459 : 330 : sel *= regex_selectivity_sub(patt + (paren_pos + 1),
1460 : 330 : pos - (paren_pos + 1),
1461 : : case_insensitive);
1462 : : }
1463 [ + + + + ]: 22870 : else if (patt[pos] == '|' && paren_depth == 0)
1464 : : {
1465 : : /*
1466 : : * If unquoted | is present at paren level 0 in pattern, we have
1467 : : * multiple alternatives; sum their probabilities.
1468 : : */
1469 : 32 : sel += regex_selectivity_sub(patt + (pos + 1),
1470 : 16 : pattlen - (pos + 1),
1471 : : case_insensitive);
1472 : 16 : break; /* rest of pattern is now processed */
1473 : : }
1474 [ + + ]: 22854 : else if (patt[pos] == '[')
1475 : : {
1476 : 192 : bool negclass = false;
1477 : :
1478 [ + + ]: 192 : if (patt[++pos] == '^')
1479 : : {
1480 : 50 : negclass = true;
1481 : 50 : pos++;
1482 : : }
1483 [ + + ]: 192 : if (patt[pos] == ']') /* ']' at start of class is not special */
1484 : 20 : pos++;
1485 [ + - + + ]: 1002 : while (pos < pattlen && patt[pos] != ']')
1486 : 810 : pos++;
1487 [ + + ]: 192 : if (paren_depth == 0)
1488 [ + + ]: 117 : sel *= (negclass ? (1.0 - CHAR_RANGE_SEL) : CHAR_RANGE_SEL);
1489 : : }
1490 [ + + ]: 22662 : else if (patt[pos] == '.')
1491 : : {
1492 [ + + ]: 759 : if (paren_depth == 0)
1493 : 431 : sel *= ANY_CHAR_SEL;
1494 : : }
1495 [ + + ]: 21903 : else if (patt[pos] == '*' ||
1496 [ + + ]: 21241 : patt[pos] == '?' ||
1497 [ + + ]: 21108 : patt[pos] == '+')
1498 : : {
1499 : : /* Ought to be smarter about quantifiers... */
1500 [ + + ]: 804 : if (paren_depth == 0)
1501 : 429 : sel *= PARTIAL_WILDCARD_SEL;
1502 : : }
1503 [ + + ]: 21099 : else if (patt[pos] == '{')
1504 : : {
1505 [ + - + + ]: 132 : while (pos < pattlen && patt[pos] != '}')
1506 : 94 : pos++;
1507 [ + + ]: 38 : if (paren_depth == 0)
1508 : 32 : sel *= PARTIAL_WILDCARD_SEL;
1509 : : }
1510 [ + + ]: 21061 : else if (patt[pos] == '\\')
1511 : : {
1512 : : /* backslash quotes the next character */
1513 : 244 : pos++;
1514 [ - + ]: 244 : if (pos >= pattlen)
1515 : 0 : break;
1516 [ + + ]: 244 : if (paren_depth == 0)
1517 : 124 : sel *= FIXED_CHAR_SEL;
1518 : : }
1519 : : else
1520 : : {
1521 [ + + ]: 20817 : if (paren_depth == 0)
1522 : 18551 : sel *= FIXED_CHAR_SEL;
1523 : : }
1524 : : }
1525 : : /* Could get sel > 1 if multiple wildcards */
1526 [ + + ]: 2397 : if (sel > 1.0)
1527 : 17 : sel = 1.0;
1528 : 2397 : return sel;
1529 : : }
1530 : :
1531 : : static Selectivity
1532 : 2051 : regex_selectivity(const char *patt, int pattlen, bool case_insensitive,
1533 : : int fixed_prefix_len)
1534 : : {
1535 : : Selectivity sel;
1536 : :
1537 : : /* If patt doesn't end with $, consider it to have a trailing wildcard */
1538 [ + - + + : 2051 : if (pattlen > 0 && patt[pattlen - 1] == '$' &&
+ - ]
1539 [ + - ]: 335 : (pattlen == 1 || patt[pattlen - 2] != '\\'))
1540 : : {
1541 : : /* has trailing $ */
1542 : 335 : sel = regex_selectivity_sub(patt, pattlen - 1, case_insensitive);
1543 : : }
1544 : : else
1545 : : {
1546 : : /* no trailing $ */
1547 : 1716 : sel = regex_selectivity_sub(patt, pattlen, case_insensitive);
1548 : 1716 : sel *= FULL_WILDCARD_SEL;
1549 : : }
1550 : :
1551 : : /*
1552 : : * If there's a fixed prefix, discount its selectivity. We have to be
1553 : : * careful here since a very long prefix could result in pow's result
1554 : : * underflowing to zero (in which case "sel" probably has as well).
1555 : : */
1556 [ + + ]: 2051 : if (fixed_prefix_len > 0)
1557 : : {
1558 : 1572 : double prefixsel = pow(FIXED_CHAR_SEL, fixed_prefix_len);
1559 : :
1560 [ + - ]: 1572 : if (prefixsel > 0.0)
1561 : 1572 : sel /= prefixsel;
1562 : : }
1563 : :
1564 : : /* Make sure result stays in range */
1565 [ - + + + ]: 2051 : CLAMP_PROBABILITY(sel);
1566 : 2051 : return sel;
1567 : : }
1568 : :
1569 : :
1570 : : /*
1571 : : * For bytea, the increment function need only increment the current byte
1572 : : * (there are no multibyte characters to worry about).
1573 : : */
1574 : : static bool
1575 : 0 : byte_increment(unsigned char *ptr, int len)
1576 : : {
1577 [ # # ]: 0 : if (*ptr >= 255)
1578 : 0 : return false;
1579 : 0 : (*ptr)++;
1580 : 0 : return true;
1581 : : }
1582 : :
1583 : : /*
1584 : : * Try to generate a string greater than the given string or any
1585 : : * string it is a prefix of. If successful, return a palloc'd string
1586 : : * in the form of a Const node; else return NULL.
1587 : : *
1588 : : * The caller must provide the appropriate "less than" comparison function
1589 : : * for testing the strings, along with the collation to use.
1590 : : *
1591 : : * The key requirement here is that given a prefix string, say "foo",
1592 : : * we must be able to generate another string "fop" that is greater than
1593 : : * all strings "foobar" starting with "foo". We can test that we have
1594 : : * generated a string greater than the prefix string, but in non-C collations
1595 : : * that is not a bulletproof guarantee that an extension of the string might
1596 : : * not sort after it; an example is that "foo " is less than "foo!", but it
1597 : : * is not clear that a "dictionary" sort ordering will consider "foo!" less
1598 : : * than "foo bar". CAUTION: Therefore, this function should be used only for
1599 : : * estimation purposes when working in a non-C collation.
1600 : : *
1601 : : * To try to catch most cases where an extended string might otherwise sort
1602 : : * before the result value, we determine which of the strings "Z", "z", "y",
1603 : : * and "9" is seen as largest by the collation, and append that to the given
1604 : : * prefix before trying to find a string that compares as larger.
1605 : : *
1606 : : * To search for a greater string, we repeatedly "increment" the rightmost
1607 : : * character, using an encoding-specific character incrementer function.
1608 : : * When it's no longer possible to increment the last character, we truncate
1609 : : * off that character and start incrementing the next-to-rightmost.
1610 : : * For example, if "z" were the last character in the sort order, then we
1611 : : * could produce "foo" as a string greater than "fonz".
1612 : : *
1613 : : * This could be rather slow in the worst case, but in most cases we
1614 : : * won't have to try more than one or two strings before succeeding.
1615 : : *
1616 : : * Note that it's important for the character incrementer not to be too anal
1617 : : * about producing every possible character code, since in some cases the only
1618 : : * way to get a larger string is to increment a previous character position.
1619 : : * So we don't want to spend too much time trying every possible character
1620 : : * code at the last position. A good rule of thumb is to be sure that we
1621 : : * don't try more than 256*K values for a K-byte character (and definitely
1622 : : * not 256^K, which is what an exhaustive search would approach).
1623 : : */
1624 : : static Const *
1625 : 2386 : make_greater_string(const Const *str_const, FmgrInfo *ltproc, Oid collation)
1626 : : {
1627 : 2386 : Oid datatype = str_const->consttype;
1628 : : char *workstr;
1629 : : int len;
1630 : : Datum cmpstr;
1631 : 2386 : char *cmptxt = NULL;
1632 : : mbcharacter_incrementer charinc;
1633 : :
1634 : : /*
1635 : : * Get a modifiable copy of the prefix string in C-string format, and set
1636 : : * up the string we will compare to as a Datum. In C locale this can just
1637 : : * be the given prefix string, otherwise we need to add a suffix. Type
1638 : : * BYTEA sorts bytewise so it never needs a suffix either.
1639 : : */
1640 [ - + ]: 2386 : if (datatype == BYTEAOID)
1641 : : {
1642 : 0 : bytea *bstr = DatumGetByteaPP(str_const->constvalue);
1643 : :
1644 : 0 : len = VARSIZE_ANY_EXHDR(bstr);
1645 : 0 : workstr = (char *) palloc(len);
1646 : 0 : memcpy(workstr, VARDATA_ANY(bstr), len);
1647 : : Assert(bstr == DatumGetPointer(str_const->constvalue));
1648 : 0 : cmpstr = str_const->constvalue;
1649 : : }
1650 : : else
1651 : : {
1652 [ - + ]: 2386 : if (datatype == NAMEOID)
1653 : 0 : workstr = DatumGetCString(DirectFunctionCall1(nameout,
1654 : : str_const->constvalue));
1655 : : else
1656 : 2386 : workstr = TextDatumGetCString(str_const->constvalue);
1657 : 2386 : len = strlen(workstr);
1658 [ + - + + ]: 2386 : if (len == 0 || pg_newlocale_from_collation(collation)->collate_is_c)
1659 : 2361 : cmpstr = str_const->constvalue;
1660 : : else
1661 : : {
1662 : : /* If first time through, determine the suffix to use */
1663 : : static char suffixchar = 0;
1664 : : static Oid suffixcollation = 0;
1665 : :
1666 [ + + - + ]: 25 : if (!suffixchar || suffixcollation != collation)
1667 : : {
1668 : : char *best;
1669 : :
1670 : 4 : best = "Z";
1671 [ - + ]: 4 : if (varstr_cmp(best, 1, "z", 1, collation) < 0)
1672 : 0 : best = "z";
1673 [ - + ]: 4 : if (varstr_cmp(best, 1, "y", 1, collation) < 0)
1674 : 0 : best = "y";
1675 [ - + ]: 4 : if (varstr_cmp(best, 1, "9", 1, collation) < 0)
1676 : 0 : best = "9";
1677 : 4 : suffixchar = *best;
1678 : 4 : suffixcollation = collation;
1679 : : }
1680 : :
1681 : : /* And build the string to compare to */
1682 [ - + ]: 25 : if (datatype == NAMEOID)
1683 : : {
1684 : 0 : cmptxt = palloc(len + 2);
1685 : 0 : memcpy(cmptxt, workstr, len);
1686 : 0 : cmptxt[len] = suffixchar;
1687 : 0 : cmptxt[len + 1] = '\0';
1688 : 0 : cmpstr = PointerGetDatum(cmptxt);
1689 : : }
1690 : : else
1691 : : {
1692 : 25 : cmptxt = palloc(VARHDRSZ + len + 1);
1693 : 25 : SET_VARSIZE(cmptxt, VARHDRSZ + len + 1);
1694 : 25 : memcpy(VARDATA(cmptxt), workstr, len);
1695 : 25 : *(VARDATA(cmptxt) + len) = suffixchar;
1696 : 25 : cmpstr = PointerGetDatum(cmptxt);
1697 : : }
1698 : : }
1699 : : }
1700 : :
1701 : : /* Select appropriate character-incrementer function */
1702 [ - + ]: 2386 : if (datatype == BYTEAOID)
1703 : 0 : charinc = byte_increment;
1704 : : else
1705 : 2386 : charinc = pg_database_encoding_character_incrementer();
1706 : :
1707 : : /* And search ... */
1708 [ + - ]: 2386 : while (len > 0)
1709 : : {
1710 : : int charlen;
1711 : : unsigned char *lastchar;
1712 : :
1713 : : /* Identify the last character --- for bytea, just the last byte */
1714 [ - + ]: 2386 : if (datatype == BYTEAOID)
1715 : 0 : charlen = 1;
1716 : : else
1717 : 2386 : charlen = len - pg_mbcliplen(workstr, len, len - 1);
1718 : 2386 : lastchar = (unsigned char *) (workstr + len - charlen);
1719 : :
1720 : : /*
1721 : : * Try to generate a larger string by incrementing the last character
1722 : : * (for BYTEA, we treat each byte as a character).
1723 : : *
1724 : : * Note: the incrementer function is expected to return true if it's
1725 : : * generated a valid-per-the-encoding new character, otherwise false.
1726 : : * The contents of the character on false return are unspecified.
1727 : : */
1728 [ + - ]: 2386 : while (charinc(lastchar, charlen))
1729 : : {
1730 : : Const *workstr_const;
1731 : :
1732 [ - + ]: 2386 : if (datatype == BYTEAOID)
1733 : 0 : workstr_const = string_to_bytea_const(workstr, len);
1734 : : else
1735 : 2386 : workstr_const = string_to_const(workstr, datatype);
1736 : :
1737 [ + - ]: 2386 : if (DatumGetBool(FunctionCall2Coll(ltproc,
1738 : : collation,
1739 : : cmpstr,
1740 : : workstr_const->constvalue)))
1741 : : {
1742 : : /* Successfully made a string larger than cmpstr */
1743 [ + + ]: 2386 : if (cmptxt)
1744 : 25 : pfree(cmptxt);
1745 : 2386 : pfree(workstr);
1746 : 2386 : return workstr_const;
1747 : : }
1748 : :
1749 : : /* No good, release unusable value and try again */
1750 : 0 : pfree(DatumGetPointer(workstr_const->constvalue));
1751 : 0 : pfree(workstr_const);
1752 : : }
1753 : :
1754 : : /*
1755 : : * No luck here, so truncate off the last character and try to
1756 : : * increment the next one.
1757 : : */
1758 : 0 : len -= charlen;
1759 : 0 : workstr[len] = '\0';
1760 : : }
1761 : :
1762 : : /* Failed... */
1763 [ # # ]: 0 : if (cmptxt)
1764 : 0 : pfree(cmptxt);
1765 : 0 : pfree(workstr);
1766 : :
1767 : 0 : return NULL;
1768 : : }
1769 : :
1770 : : /*
1771 : : * Generate a Datum of the appropriate type from a C string.
1772 : : * Note that all of the supported types are pass-by-ref, so the
1773 : : * returned value should be pfree'd if no longer needed.
1774 : : */
1775 : : static Datum
1776 : 17810 : string_to_datum(const char *str, Oid datatype)
1777 : : {
1778 : : Assert(str != NULL);
1779 : :
1780 : : /*
1781 : : * We cheat a little by assuming that CStringGetTextDatum() will do for
1782 : : * bpchar and varchar constants too...
1783 : : */
1784 [ - + ]: 17810 : if (datatype == NAMEOID)
1785 : 0 : return DirectFunctionCall1(namein, CStringGetDatum(str));
1786 [ - + ]: 17810 : else if (datatype == BYTEAOID)
1787 : 0 : return DirectFunctionCall1(byteain, CStringGetDatum(str));
1788 : : else
1789 : 17810 : return CStringGetTextDatum(str);
1790 : : }
1791 : :
1792 : : /*
1793 : : * Generate a Const node of the appropriate type from a C string.
1794 : : */
1795 : : static Const *
1796 : 17810 : string_to_const(const char *str, Oid datatype)
1797 : : {
1798 : 17810 : Datum conval = string_to_datum(str, datatype);
1799 : : Oid collation;
1800 : : int constlen;
1801 : :
1802 : : /*
1803 : : * We only need to support a few datatypes here, so hard-wire properties
1804 : : * instead of incurring the expense of catalog lookups.
1805 : : */
1806 [ + - - - ]: 17810 : switch (datatype)
1807 : : {
1808 : 17810 : case TEXTOID:
1809 : : case VARCHAROID:
1810 : : case BPCHAROID:
1811 : 17810 : collation = DEFAULT_COLLATION_OID;
1812 : 17810 : constlen = -1;
1813 : 17810 : break;
1814 : :
1815 : 0 : case NAMEOID:
1816 : 0 : collation = C_COLLATION_OID;
1817 : 0 : constlen = NAMEDATALEN;
1818 : 0 : break;
1819 : :
1820 : 0 : case BYTEAOID:
1821 : 0 : collation = InvalidOid;
1822 : 0 : constlen = -1;
1823 : 0 : break;
1824 : :
1825 : 0 : default:
1826 [ # # ]: 0 : elog(ERROR, "unexpected datatype in string_to_const: %u",
1827 : : datatype);
1828 : : return NULL;
1829 : : }
1830 : :
1831 : 17810 : return makeConst(datatype, -1, collation, constlen,
1832 : : conval, false, false);
1833 : : }
1834 : :
1835 : : /*
1836 : : * Generate a Const node of bytea type from a binary C string and a length.
1837 : : */
1838 : : static Const *
1839 : 10 : string_to_bytea_const(const char *str, size_t str_len)
1840 : : {
1841 : 10 : bytea *bstr = palloc(VARHDRSZ + str_len);
1842 : : Datum conval;
1843 : :
1844 : 10 : memcpy(VARDATA(bstr), str, str_len);
1845 : 10 : SET_VARSIZE(bstr, VARHDRSZ + str_len);
1846 : 10 : conval = PointerGetDatum(bstr);
1847 : :
1848 : 10 : return makeConst(BYTEAOID, -1, InvalidOid, -1, conval, false, false);
1849 : : }
|