PostgreSQL Source Code  git master
like_support.c File Reference
#include "postgres.h"
#include <math.h>
#include "access/htup_details.h"
#include "access/stratnum.h"
#include "catalog/pg_collation.h"
#include "catalog/pg_operator.h"
#include "catalog/pg_opfamily.h"
#include "catalog/pg_statistic.h"
#include "catalog/pg_type.h"
#include "mb/pg_wchar.h"
#include "nodes/makefuncs.h"
#include "nodes/nodeFuncs.h"
#include "nodes/supportnodes.h"
#include "utils/builtins.h"
#include "utils/datum.h"
#include "utils/lsyscache.h"
#include "utils/pg_locale.h"
#include "utils/selfuncs.h"
#include "utils/varlena.h"
Include dependency graph for like_support.c:

Go to the source code of this file.

Macros

#define FIXED_CHAR_SEL   0.20 /* about 1/5 */
 
#define CHAR_RANGE_SEL   0.25
 
#define ANY_CHAR_SEL   0.9 /* not 1, since it won't match end-of-string */
 
#define FULL_WILDCARD_SEL   5.0
 
#define PARTIAL_WILDCARD_SEL   2.0
 

Enumerations

enum  Pattern_Type {
  Pattern_Type_Like, Pattern_Type_Like_IC, Pattern_Type_Regex, Pattern_Type_Regex_IC,
  Pattern_Type_Prefix
}
 
enum  Pattern_Prefix_Status { Pattern_Prefix_None, Pattern_Prefix_Partial, Pattern_Prefix_Exact }
 

Functions

static Nodelike_regex_support (Node *rawreq, Pattern_Type ptype)
 
static Listmatch_pattern_prefix (Node *leftop, Node *rightop, Pattern_Type ptype, Oid expr_coll, Oid opfamily, Oid indexcollation)
 
static double patternsel_common (PlannerInfo *root, Oid oprid, Oid opfuncid, List *args, int varRelid, Oid collation, Pattern_Type ptype, bool negate)
 
static Pattern_Prefix_Status pattern_fixed_prefix (Const *patt, Pattern_Type ptype, Oid collation, Const **prefix, Selectivity *rest_selec)
 
static Selectivity prefix_selectivity (PlannerInfo *root, VariableStatData *vardata, Oid eqopr, Oid ltopr, Oid geopr, Const *prefixcon)
 
static Selectivity like_selectivity (const char *patt, int pattlen, bool case_insensitive)
 
static Selectivity regex_selectivity (const char *patt, int pattlen, bool case_insensitive, int fixed_prefix_len)
 
static int pattern_char_isalpha (char c, bool is_multibyte, pg_locale_t locale, bool locale_is_c)
 
static Constmake_greater_string (const Const *str_const, FmgrInfo *ltproc, Oid collation)
 
static Datum string_to_datum (const char *str, Oid datatype)
 
static Conststring_to_const (const char *str, Oid datatype)
 
static Conststring_to_bytea_const (const char *str, size_t str_len)
 
Datum textlike_support (PG_FUNCTION_ARGS)
 
Datum texticlike_support (PG_FUNCTION_ARGS)
 
Datum textregexeq_support (PG_FUNCTION_ARGS)
 
Datum texticregexeq_support (PG_FUNCTION_ARGS)
 
static double patternsel (PG_FUNCTION_ARGS, Pattern_Type ptype, bool negate)
 
Datum regexeqsel (PG_FUNCTION_ARGS)
 
Datum icregexeqsel (PG_FUNCTION_ARGS)
 
Datum likesel (PG_FUNCTION_ARGS)
 
Datum prefixsel (PG_FUNCTION_ARGS)
 
Datum iclikesel (PG_FUNCTION_ARGS)
 
Datum regexnesel (PG_FUNCTION_ARGS)
 
Datum icregexnesel (PG_FUNCTION_ARGS)
 
Datum nlikesel (PG_FUNCTION_ARGS)
 
Datum icnlikesel (PG_FUNCTION_ARGS)
 
static double patternjoinsel (PG_FUNCTION_ARGS, Pattern_Type ptype, bool negate)
 
Datum regexeqjoinsel (PG_FUNCTION_ARGS)
 
Datum icregexeqjoinsel (PG_FUNCTION_ARGS)
 
Datum likejoinsel (PG_FUNCTION_ARGS)
 
Datum prefixjoinsel (PG_FUNCTION_ARGS)
 
Datum iclikejoinsel (PG_FUNCTION_ARGS)
 
Datum regexnejoinsel (PG_FUNCTION_ARGS)
 
Datum icregexnejoinsel (PG_FUNCTION_ARGS)
 
Datum nlikejoinsel (PG_FUNCTION_ARGS)
 
Datum icnlikejoinsel (PG_FUNCTION_ARGS)
 
static Pattern_Prefix_Status like_fixed_prefix (Const *patt_const, bool case_insensitive, Oid collation, Const **prefix_const, Selectivity *rest_selec)
 
static Pattern_Prefix_Status regex_fixed_prefix (Const *patt_const, bool case_insensitive, Oid collation, Const **prefix_const, Selectivity *rest_selec)
 
static Selectivity regex_selectivity_sub (const char *patt, int pattlen, bool case_insensitive)
 
static bool byte_increment (unsigned char *ptr, int len)
 

Macro Definition Documentation

◆ ANY_CHAR_SEL

#define ANY_CHAR_SEL   0.9 /* not 1, since it won't match end-of-string */

Definition at line 1302 of file like_support.c.

Referenced by like_selectivity(), and regex_selectivity_sub().

◆ CHAR_RANGE_SEL

#define CHAR_RANGE_SEL   0.25

Definition at line 1301 of file like_support.c.

Referenced by regex_selectivity_sub().

◆ FIXED_CHAR_SEL

#define FIXED_CHAR_SEL   0.20 /* about 1/5 */

Definition at line 1300 of file like_support.c.

Referenced by like_selectivity(), regex_selectivity(), and regex_selectivity_sub().

◆ FULL_WILDCARD_SEL

#define FULL_WILDCARD_SEL   5.0

Definition at line 1303 of file like_support.c.

Referenced by like_selectivity(), and regex_selectivity().

◆ PARTIAL_WILDCARD_SEL

#define PARTIAL_WILDCARD_SEL   2.0

Definition at line 1304 of file like_support.c.

Referenced by regex_selectivity_sub().

Enumeration Type Documentation

◆ Pattern_Prefix_Status

Enumerator
Pattern_Prefix_None 
Pattern_Prefix_Partial 
Pattern_Prefix_Exact 

Definition at line 67 of file like_support.c.

◆ Pattern_Type

Enumerator
Pattern_Type_Like 
Pattern_Type_Like_IC 
Pattern_Type_Regex 
Pattern_Type_Regex_IC 
Pattern_Type_Prefix 

Definition at line 58 of file like_support.c.

Function Documentation

◆ byte_increment()

static bool byte_increment ( unsigned char *  ptr,
int  len 
)
static

Definition at line 1497 of file like_support.c.

Referenced by make_greater_string().

1498 {
1499  if (*ptr >= 255)
1500  return false;
1501  (*ptr)++;
1502  return true;
1503 }

◆ iclikejoinsel()

Datum iclikejoinsel ( PG_FUNCTION_ARGS  )

Definition at line 897 of file like_support.c.

References Pattern_Type_Like_IC, patternjoinsel(), and PG_RETURN_FLOAT8.

898 {
900 }
static double patternjoinsel(PG_FUNCTION_ARGS, Pattern_Type ptype, bool negate)
Definition: like_support.c:851
#define PG_RETURN_FLOAT8(x)
Definition: fmgr.h:356

◆ iclikesel()

Datum iclikesel ( PG_FUNCTION_ARGS  )

Definition at line 806 of file like_support.c.

References Pattern_Type_Like_IC, patternsel(), and PG_RETURN_FLOAT8.

807 {
809 }
static double patternsel(PG_FUNCTION_ARGS, Pattern_Type ptype, bool negate)
Definition: like_support.c:736
#define PG_RETURN_FLOAT8(x)
Definition: fmgr.h:356

◆ icnlikejoinsel()

Datum icnlikejoinsel ( PG_FUNCTION_ARGS  )

Definition at line 933 of file like_support.c.

References Pattern_Type_Like_IC, patternjoinsel(), and PG_RETURN_FLOAT8.

934 {
936 }
static double patternjoinsel(PG_FUNCTION_ARGS, Pattern_Type ptype, bool negate)
Definition: like_support.c:851
#define PG_RETURN_FLOAT8(x)
Definition: fmgr.h:356

◆ icnlikesel()

Datum icnlikesel ( PG_FUNCTION_ARGS  )

Definition at line 842 of file like_support.c.

References Pattern_Type_Like_IC, patternsel(), and PG_RETURN_FLOAT8.

843 {
845 }
static double patternsel(PG_FUNCTION_ARGS, Pattern_Type ptype, bool negate)
Definition: like_support.c:736
#define PG_RETURN_FLOAT8(x)
Definition: fmgr.h:356

◆ icregexeqjoinsel()

Datum icregexeqjoinsel ( PG_FUNCTION_ARGS  )

Definition at line 870 of file like_support.c.

References Pattern_Type_Regex_IC, patternjoinsel(), and PG_RETURN_FLOAT8.

871 {
873 }
static double patternjoinsel(PG_FUNCTION_ARGS, Pattern_Type ptype, bool negate)
Definition: like_support.c:851
#define PG_RETURN_FLOAT8(x)
Definition: fmgr.h:356

◆ icregexeqsel()

Datum icregexeqsel ( PG_FUNCTION_ARGS  )

Definition at line 778 of file like_support.c.

References Pattern_Type_Regex_IC, patternsel(), and PG_RETURN_FLOAT8.

779 {
781 }
static double patternsel(PG_FUNCTION_ARGS, Pattern_Type ptype, bool negate)
Definition: like_support.c:736
#define PG_RETURN_FLOAT8(x)
Definition: fmgr.h:356

◆ icregexnejoinsel()

Datum icregexnejoinsel ( PG_FUNCTION_ARGS  )

Definition at line 915 of file like_support.c.

References Pattern_Type_Regex_IC, patternjoinsel(), and PG_RETURN_FLOAT8.

916 {
918 }
static double patternjoinsel(PG_FUNCTION_ARGS, Pattern_Type ptype, bool negate)
Definition: like_support.c:851
#define PG_RETURN_FLOAT8(x)
Definition: fmgr.h:356

◆ icregexnesel()

Datum icregexnesel ( PG_FUNCTION_ARGS  )

Definition at line 824 of file like_support.c.

References Pattern_Type_Regex_IC, patternsel(), and PG_RETURN_FLOAT8.

825 {
827 }
static double patternsel(PG_FUNCTION_ARGS, Pattern_Type ptype, bool negate)
Definition: like_support.c:736
#define PG_RETURN_FLOAT8(x)
Definition: fmgr.h:356

◆ like_fixed_prefix()

static Pattern_Prefix_Status like_fixed_prefix ( Const patt_const,
bool  case_insensitive,
Oid  collation,
Const **  prefix_const,
Selectivity rest_selec 
)
static

Definition at line 968 of file like_support.c.

References Assert, Const::consttype, Const::constvalue, DatumGetByteaPP, DatumGetPointer, ereport, errcode(), errhint(), errmsg(), ERROR, lc_ctype_is_c(), like_selectivity(), locale, OidIsValid, palloc(), pattern_char_isalpha(), Pattern_Prefix_Exact, Pattern_Prefix_None, Pattern_Prefix_Partial, pfree(), pg_database_encoding_max_length(), pg_newlocale_from_collation(), string_to_bytea_const(), string_to_const(), TextDatumGetCString, VARDATA_ANY, and VARSIZE_ANY_EXHDR.

Referenced by pattern_fixed_prefix().

970 {
971  char *match;
972  char *patt;
973  int pattlen;
974  Oid typeid = patt_const->consttype;
975  int pos,
976  match_pos;
977  bool is_multibyte = (pg_database_encoding_max_length() > 1);
978  pg_locale_t locale = 0;
979  bool locale_is_c = false;
980 
981  /* the right-hand const is type text or bytea */
982  Assert(typeid == BYTEAOID || typeid == TEXTOID);
983 
984  if (case_insensitive)
985  {
986  if (typeid == BYTEAOID)
987  ereport(ERROR,
988  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
989  errmsg("case insensitive matching not supported on type bytea")));
990 
991  /* If case-insensitive, we need locale info */
992  if (lc_ctype_is_c(collation))
993  locale_is_c = true;
994  else if (collation != DEFAULT_COLLATION_OID)
995  {
996  if (!OidIsValid(collation))
997  {
998  /*
999  * This typically means that the parser could not resolve a
1000  * conflict of implicit collations, so report it that way.
1001  */
1002  ereport(ERROR,
1003  (errcode(ERRCODE_INDETERMINATE_COLLATION),
1004  errmsg("could not determine which collation to use for ILIKE"),
1005  errhint("Use the COLLATE clause to set the collation explicitly.")));
1006  }
1007  locale = pg_newlocale_from_collation(collation);
1008  }
1009  }
1010 
1011  if (typeid != BYTEAOID)
1012  {
1013  patt = TextDatumGetCString(patt_const->constvalue);
1014  pattlen = strlen(patt);
1015  }
1016  else
1017  {
1018  bytea *bstr = DatumGetByteaPP(patt_const->constvalue);
1019 
1020  pattlen = VARSIZE_ANY_EXHDR(bstr);
1021  patt = (char *) palloc(pattlen);
1022  memcpy(patt, VARDATA_ANY(bstr), pattlen);
1023  Assert((Pointer) bstr == DatumGetPointer(patt_const->constvalue));
1024  }
1025 
1026  match = palloc(pattlen + 1);
1027  match_pos = 0;
1028  for (pos = 0; pos < pattlen; pos++)
1029  {
1030  /* % and _ are wildcard characters in LIKE */
1031  if (patt[pos] == '%' ||
1032  patt[pos] == '_')
1033  break;
1034 
1035  /* Backslash escapes the next character */
1036  if (patt[pos] == '\\')
1037  {
1038  pos++;
1039  if (pos >= pattlen)
1040  break;
1041  }
1042 
1043  /* Stop if case-varying character (it's sort of a wildcard) */
1044  if (case_insensitive &&
1045  pattern_char_isalpha(patt[pos], is_multibyte, locale, locale_is_c))
1046  break;
1047 
1048  match[match_pos++] = patt[pos];
1049  }
1050 
1051  match[match_pos] = '\0';
1052 
1053  if (typeid != BYTEAOID)
1054  *prefix_const = string_to_const(match, typeid);
1055  else
1056  *prefix_const = string_to_bytea_const(match, match_pos);
1057 
1058  if (rest_selec != NULL)
1059  *rest_selec = like_selectivity(&patt[pos], pattlen - pos,
1060  case_insensitive);
1061 
1062  pfree(patt);
1063  pfree(match);
1064 
1065  /* in LIKE, an empty pattern is an exact match! */
1066  if (pos == pattlen)
1067  return Pattern_Prefix_Exact; /* reached end of pattern, so exact */
1068 
1069  if (match_pos > 0)
1070  return Pattern_Prefix_Partial;
1071 
1072  return Pattern_Prefix_None;
1073 }
Datum constvalue
Definition: primnodes.h:200
int errhint(const char *fmt,...)
Definition: elog.c:1069
#define VARDATA_ANY(PTR)
Definition: postgres.h:348
static Const * string_to_const(const char *str, Oid datatype)
static Const * string_to_bytea_const(const char *str, size_t str_len)
int errcode(int sqlerrcode)
Definition: elog.c:608
#define DatumGetByteaPP(X)
Definition: fmgr.h:285
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:645
Oid consttype
Definition: primnodes.h:196
void pfree(void *pointer)
Definition: mcxt.c:1056
char * Pointer
Definition: c.h:336
#define ERROR
Definition: elog.h:43
int pg_database_encoding_max_length(void)
Definition: wchar.c:1881
#define ereport(elevel, rest)
Definition: elog.h:141
pg_locale_t pg_newlocale_from_collation(Oid collid)
Definition: pg_locale.c:1323
#define TextDatumGetCString(d)
Definition: builtins.h:84
static Selectivity like_selectivity(const char *patt, int pattlen, bool case_insensitive)
static int pattern_char_isalpha(char c, bool is_multibyte, pg_locale_t locale, bool locale_is_c)
#define Assert(condition)
Definition: c.h:739
#define DatumGetPointer(X)
Definition: postgres.h:549
#define VARSIZE_ANY_EXHDR(PTR)
Definition: postgres.h:341
void * palloc(Size size)
Definition: mcxt.c:949
int errmsg(const char *fmt,...)
Definition: elog.c:822
static char * locale
Definition: initdb.c:125
Definition: c.h:556
bool lc_ctype_is_c(Oid collation)
Definition: pg_locale.c:1226

◆ like_regex_support()

static Node * like_regex_support ( Node rawreq,
Pattern_Type  ptype 
)
static

Definition at line 147 of file like_support.c.

References SupportRequestSelectivity::args, FuncExpr::args, OpExpr::args, Assert, DEFAULT_MATCH_SEL, SupportRequestSelectivity::funcid, SupportRequestIndexCondition::indexarg, SupportRequestIndexCondition::indexcollation, SupportRequestSelectivity::inputcollid, FuncExpr::inputcollid, OpExpr::inputcollid, InvalidOid, is_funcclause(), SupportRequestSelectivity::is_join, is_opclause(), IsA, linitial, list_length(), lsecond, match_pattern_prefix(), SupportRequestIndexCondition::node, SupportRequestIndexCondition::opfamily, patternsel_common(), SupportRequestSelectivity::root, s1, SupportRequestSelectivity::selectivity, and SupportRequestSelectivity::varRelid.

Referenced by texticlike_support(), texticregexeq_support(), textlike_support(), and textregexeq_support().

148 {
149  Node *ret = NULL;
150 
151  if (IsA(rawreq, SupportRequestSelectivity))
152  {
153  /*
154  * Make a selectivity estimate for a function call, just as we'd do if
155  * the call was via the corresponding operator.
156  */
158  Selectivity s1;
159 
160  if (req->is_join)
161  {
162  /*
163  * For the moment we just punt. If patternjoinsel is ever
164  * improved to do better, this should be made to call it.
165  */
166  s1 = DEFAULT_MATCH_SEL;
167  }
168  else
169  {
170  /* Share code with operator restriction selectivity functions */
171  s1 = patternsel_common(req->root,
172  InvalidOid,
173  req->funcid,
174  req->args,
175  req->varRelid,
176  req->inputcollid,
177  ptype,
178  false);
179  }
180  req->selectivity = s1;
181  ret = (Node *) req;
182  }
183  else if (IsA(rawreq, SupportRequestIndexCondition))
184  {
185  /* Try to convert operator/function call to index conditions */
187 
188  /*
189  * Currently we have no "reverse" match operators with the pattern on
190  * the left, so we only need consider cases with the indexkey on the
191  * left.
192  */
193  if (req->indexarg != 0)
194  return NULL;
195 
196  if (is_opclause(req->node))
197  {
198  OpExpr *clause = (OpExpr *) req->node;
199 
200  Assert(list_length(clause->args) == 2);
201  ret = (Node *)
202  match_pattern_prefix((Node *) linitial(clause->args),
203  (Node *) lsecond(clause->args),
204  ptype,
205  clause->inputcollid,
206  req->opfamily,
207  req->indexcollation);
208  }
209  else if (is_funcclause(req->node)) /* be paranoid */
210  {
211  FuncExpr *clause = (FuncExpr *) req->node;
212 
213  Assert(list_length(clause->args) == 2);
214  ret = (Node *)
215  match_pattern_prefix((Node *) linitial(clause->args),
216  (Node *) lsecond(clause->args),
217  ptype,
218  clause->inputcollid,
219  req->opfamily,
220  req->indexcollation);
221  }
222  }
223 
224  return ret;
225 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:576
List * args
Definition: primnodes.h:463
Definition: nodes.h:525
static List * match_pattern_prefix(Node *leftop, Node *rightop, Pattern_Type ptype, Oid expr_coll, Oid opfamily, Oid indexcollation)
Definition: like_support.c:232
double Selectivity
Definition: nodes.h:658
#define lsecond(l)
Definition: pg_list.h:200
static bool is_funcclause(const void *clause)
Definition: nodeFuncs.h:56
#define linitial(l)
Definition: pg_list.h:195
char * s1
struct PlannerInfo * root
Definition: supportnodes.h:96
#define DEFAULT_MATCH_SEL
Definition: selfuncs.h:43
#define InvalidOid
Definition: postgres_ext.h:36
Oid inputcollid
Definition: primnodes.h:462
#define Assert(condition)
Definition: c.h:739
static double patternsel_common(PlannerInfo *root, Oid oprid, Oid opfuncid, List *args, int varRelid, Oid collation, Pattern_Type ptype, bool negate)
Definition: like_support.c:459
static int list_length(const List *l)
Definition: pg_list.h:169
Oid inputcollid
Definition: primnodes.h:507
static bool is_opclause(const void *clause)
Definition: nodeFuncs.h:63
List * args
Definition: primnodes.h:508

◆ like_selectivity()

static Selectivity like_selectivity ( const char *  patt,
int  pattlen,
bool  case_insensitive 
)
static

Definition at line 1307 of file like_support.c.

References ANY_CHAR_SEL, FIXED_CHAR_SEL, and FULL_WILDCARD_SEL.

Referenced by like_fixed_prefix().

1308 {
1309  Selectivity sel = 1.0;
1310  int pos;
1311 
1312  /* Skip any leading wildcard; it's already factored into initial sel */
1313  for (pos = 0; pos < pattlen; pos++)
1314  {
1315  if (patt[pos] != '%' && patt[pos] != '_')
1316  break;
1317  }
1318 
1319  for (; pos < pattlen; pos++)
1320  {
1321  /* % and _ are wildcard characters in LIKE */
1322  if (patt[pos] == '%')
1323  sel *= FULL_WILDCARD_SEL;
1324  else if (patt[pos] == '_')
1325  sel *= ANY_CHAR_SEL;
1326  else if (patt[pos] == '\\')
1327  {
1328  /* Backslash quotes the next character */
1329  pos++;
1330  if (pos >= pattlen)
1331  break;
1332  sel *= FIXED_CHAR_SEL;
1333  }
1334  else
1335  sel *= FIXED_CHAR_SEL;
1336  }
1337  /* Could get sel > 1 if multiple wildcards */
1338  if (sel > 1.0)
1339  sel = 1.0;
1340  return sel;
1341 }
#define FULL_WILDCARD_SEL
double Selectivity
Definition: nodes.h:658
#define FIXED_CHAR_SEL
#define ANY_CHAR_SEL

◆ likejoinsel()

Datum likejoinsel ( PG_FUNCTION_ARGS  )

Definition at line 879 of file like_support.c.

References Pattern_Type_Like, patternjoinsel(), and PG_RETURN_FLOAT8.

880 {
882 }
static double patternjoinsel(PG_FUNCTION_ARGS, Pattern_Type ptype, bool negate)
Definition: like_support.c:851
#define PG_RETURN_FLOAT8(x)
Definition: fmgr.h:356

◆ likesel()

Datum likesel ( PG_FUNCTION_ARGS  )

Definition at line 787 of file like_support.c.

References Pattern_Type_Like, patternsel(), and PG_RETURN_FLOAT8.

788 {
790 }
static double patternsel(PG_FUNCTION_ARGS, Pattern_Type ptype, bool negate)
Definition: like_support.c:736
#define PG_RETURN_FLOAT8(x)
Definition: fmgr.h:356

◆ make_greater_string()

static Const * make_greater_string ( const Const str_const,
FmgrInfo ltproc,
Oid  collation 
)
static

Definition at line 1547 of file like_support.c.

References Assert, byte_increment(), Const::consttype, Const::constvalue, DatumGetBool, DatumGetByteaPP, DatumGetCString, DatumGetPointer, DirectFunctionCall1, FunctionCall2Coll(), lc_collate_is_c(), nameout(), palloc(), pfree(), pg_database_encoding_character_incrementer(), pg_mbcliplen(), PointerGetDatum, SET_VARSIZE, string_to_bytea_const(), string_to_const(), TextDatumGetCString, VARDATA, VARDATA_ANY, VARHDRSZ, VARSIZE_ANY_EXHDR, and varstr_cmp().

Referenced by match_pattern_prefix(), and prefix_selectivity().

1548 {
1549  Oid datatype = str_const->consttype;
1550  char *workstr;
1551  int len;
1552  Datum cmpstr;
1553  char *cmptxt = NULL;
1554  mbcharacter_incrementer charinc;
1555 
1556  /*
1557  * Get a modifiable copy of the prefix string in C-string format, and set
1558  * up the string we will compare to as a Datum. In C locale this can just
1559  * be the given prefix string, otherwise we need to add a suffix. Type
1560  * BYTEA sorts bytewise so it never needs a suffix either.
1561  */
1562  if (datatype == BYTEAOID)
1563  {
1564  bytea *bstr = DatumGetByteaPP(str_const->constvalue);
1565 
1566  len = VARSIZE_ANY_EXHDR(bstr);
1567  workstr = (char *) palloc(len);
1568  memcpy(workstr, VARDATA_ANY(bstr), len);
1569  Assert((Pointer) bstr == DatumGetPointer(str_const->constvalue));
1570  cmpstr = str_const->constvalue;
1571  }
1572  else
1573  {
1574  if (datatype == NAMEOID)
1576  str_const->constvalue));
1577  else
1578  workstr = TextDatumGetCString(str_const->constvalue);
1579  len = strlen(workstr);
1580  if (lc_collate_is_c(collation) || len == 0)
1581  cmpstr = str_const->constvalue;
1582  else
1583  {
1584  /* If first time through, determine the suffix to use */
1585  static char suffixchar = 0;
1586  static Oid suffixcollation = 0;
1587 
1588  if (!suffixchar || suffixcollation != collation)
1589  {
1590  char *best;
1591 
1592  best = "Z";
1593  if (varstr_cmp(best, 1, "z", 1, collation) < 0)
1594  best = "z";
1595  if (varstr_cmp(best, 1, "y", 1, collation) < 0)
1596  best = "y";
1597  if (varstr_cmp(best, 1, "9", 1, collation) < 0)
1598  best = "9";
1599  suffixchar = *best;
1600  suffixcollation = collation;
1601  }
1602 
1603  /* And build the string to compare to */
1604  if (datatype == NAMEOID)
1605  {
1606  cmptxt = palloc(len + 2);
1607  memcpy(cmptxt, workstr, len);
1608  cmptxt[len] = suffixchar;
1609  cmptxt[len + 1] = '\0';
1610  cmpstr = PointerGetDatum(cmptxt);
1611  }
1612  else
1613  {
1614  cmptxt = palloc(VARHDRSZ + len + 1);
1615  SET_VARSIZE(cmptxt, VARHDRSZ + len + 1);
1616  memcpy(VARDATA(cmptxt), workstr, len);
1617  *(VARDATA(cmptxt) + len) = suffixchar;
1618  cmpstr = PointerGetDatum(cmptxt);
1619  }
1620  }
1621  }
1622 
1623  /* Select appropriate character-incrementer function */
1624  if (datatype == BYTEAOID)
1625  charinc = byte_increment;
1626  else
1628 
1629  /* And search ... */
1630  while (len > 0)
1631  {
1632  int charlen;
1633  unsigned char *lastchar;
1634 
1635  /* Identify the last character --- for bytea, just the last byte */
1636  if (datatype == BYTEAOID)
1637  charlen = 1;
1638  else
1639  charlen = len - pg_mbcliplen(workstr, len, len - 1);
1640  lastchar = (unsigned char *) (workstr + len - charlen);
1641 
1642  /*
1643  * Try to generate a larger string by incrementing the last character
1644  * (for BYTEA, we treat each byte as a character).
1645  *
1646  * Note: the incrementer function is expected to return true if it's
1647  * generated a valid-per-the-encoding new character, otherwise false.
1648  * The contents of the character on false return are unspecified.
1649  */
1650  while (charinc(lastchar, charlen))
1651  {
1652  Const *workstr_const;
1653 
1654  if (datatype == BYTEAOID)
1655  workstr_const = string_to_bytea_const(workstr, len);
1656  else
1657  workstr_const = string_to_const(workstr, datatype);
1658 
1659  if (DatumGetBool(FunctionCall2Coll(ltproc,
1660  collation,
1661  cmpstr,
1662  workstr_const->constvalue)))
1663  {
1664  /* Successfully made a string larger than cmpstr */
1665  if (cmptxt)
1666  pfree(cmptxt);
1667  pfree(workstr);
1668  return workstr_const;
1669  }
1670 
1671  /* No good, release unusable value and try again */
1672  pfree(DatumGetPointer(workstr_const->constvalue));
1673  pfree(workstr_const);
1674  }
1675 
1676  /*
1677  * No luck here, so truncate off the last character and try to
1678  * increment the next one.
1679  */
1680  len -= charlen;
1681  workstr[len] = '\0';
1682  }
1683 
1684  /* Failed... */
1685  if (cmptxt)
1686  pfree(cmptxt);
1687  pfree(workstr);
1688 
1689  return NULL;
1690 }
Datum constvalue
Definition: primnodes.h:200
#define VARDATA_ANY(PTR)
Definition: postgres.h:348
#define VARDATA(PTR)
Definition: postgres.h:302
static Const * string_to_const(const char *str, Oid datatype)
#define PointerGetDatum(X)
Definition: postgres.h:556
#define VARHDRSZ
Definition: c.h:562
static Const * string_to_bytea_const(const char *str, size_t str_len)
#define DatumGetByteaPP(X)
Definition: fmgr.h:285
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:615
Datum FunctionCall2Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2)
Definition: fmgr.c:1150
unsigned int Oid
Definition: postgres_ext.h:31
Oid consttype
Definition: primnodes.h:196
void pfree(void *pointer)
Definition: mcxt.c:1056
char * Pointer
Definition: c.h:336
bool lc_collate_is_c(Oid collation)
Definition: pg_locale.c:1176
#define DatumGetCString(X)
Definition: postgres.h:566
int varstr_cmp(const char *arg1, int len1, const char *arg2, int len2, Oid collid)
Definition: varlena.c:1482
int pg_mbcliplen(const char *mbstr, int len, int limit)
Definition: mbutils.c:862
#define DatumGetBool(X)
Definition: postgres.h:393
static bool byte_increment(unsigned char *ptr, int len)
#define TextDatumGetCString(d)
Definition: builtins.h:84
uintptr_t Datum
Definition: postgres.h:367
#define Assert(condition)
Definition: c.h:739
#define DatumGetPointer(X)
Definition: postgres.h:549
bool(* mbcharacter_incrementer)(unsigned char *mbstr, int len)
Definition: pg_wchar.h:369
#define VARSIZE_ANY_EXHDR(PTR)
Definition: postgres.h:341
void * palloc(Size size)
Definition: mcxt.c:949
mbcharacter_incrementer pg_database_encoding_character_incrementer(void)
Definition: wchar.c:1890
Definition: c.h:556
#define SET_VARSIZE(PTR, len)
Definition: postgres.h:329
Datum nameout(PG_FUNCTION_ARGS)
Definition: name.c:71

◆ match_pattern_prefix()

static List * match_pattern_prefix ( Node leftop,
Node rightop,
Pattern_Type  ptype,
Oid  expr_coll,
Oid  opfamily,
Oid  indexcollation 
)
static

Definition at line 232 of file like_support.c.

References Assert, Const::consttype, exprType(), fmgr_info(), get_collation_isdeterministic(), get_opcode(), InvalidOid, IsA, lappend(), lc_collate_is_c(), list_make1, make_greater_string(), make_opclause(), NIL, op_in_opfamily(), pattern_fixed_prefix(), Pattern_Prefix_Exact, and Pattern_Prefix_None.

Referenced by like_regex_support().

238 {
239  List *result;
240  Const *patt;
241  Const *prefix;
242  Pattern_Prefix_Status pstatus;
243  Oid ldatatype;
244  Oid rdatatype;
245  Oid eqopr;
246  Oid ltopr;
247  Oid geopr;
248  bool collation_aware;
249  Expr *expr;
250  FmgrInfo ltproc;
251  Const *greaterstr;
252 
253  /*
254  * Can't do anything with a non-constant or NULL pattern argument.
255  *
256  * Note that since we restrict ourselves to cases with a hard constant on
257  * the RHS, it's a-fortiori a pseudoconstant, and we don't need to worry
258  * about verifying that.
259  */
260  if (!IsA(rightop, Const) ||
261  ((Const *) rightop)->constisnull)
262  return NIL;
263  patt = (Const *) rightop;
264 
265  /*
266  * Not supported if the expression collation is nondeterministic. The
267  * optimized equality or prefix tests use bytewise comparisons, which is
268  * not consistent with nondeterministic collations. The actual
269  * pattern-matching implementation functions will later error out that
270  * pattern-matching is not supported with nondeterministic collations. (We
271  * could also error out here, but by doing it later we get more precise
272  * error messages.) (It should be possible to support at least
273  * Pattern_Prefix_Exact, but no point as long as the actual
274  * pattern-matching implementations don't support it.)
275  *
276  * expr_coll is not set for a non-collation-aware data type such as bytea.
277  */
278  if (expr_coll && !get_collation_isdeterministic(expr_coll))
279  return NIL;
280 
281  /*
282  * Try to extract a fixed prefix from the pattern.
283  */
284  pstatus = pattern_fixed_prefix(patt, ptype, expr_coll,
285  &prefix, NULL);
286 
287  /* fail if no fixed prefix */
288  if (pstatus == Pattern_Prefix_None)
289  return NIL;
290 
291  /*
292  * Identify the operators we want to use, based on the type of the
293  * left-hand argument. Usually these are just the type's regular
294  * comparison operators, but if we are considering one of the semi-legacy
295  * "pattern" opclasses, use the "pattern" operators instead. Those are
296  * not collation-sensitive but always use C collation, as we want. The
297  * selected operators also determine the needed type of the prefix
298  * constant.
299  */
300  ldatatype = exprType(leftop);
301  switch (ldatatype)
302  {
303  case TEXTOID:
304  if (opfamily == TEXT_PATTERN_BTREE_FAM_OID ||
305  opfamily == TEXT_SPGIST_FAM_OID)
306  {
307  eqopr = TextEqualOperator;
308  ltopr = TextPatternLessOperator;
309  geopr = TextPatternGreaterEqualOperator;
310  collation_aware = false;
311  }
312  else
313  {
314  eqopr = TextEqualOperator;
315  ltopr = TextLessOperator;
316  geopr = TextGreaterEqualOperator;
317  collation_aware = true;
318  }
319  rdatatype = TEXTOID;
320  break;
321  case NAMEOID:
322 
323  /*
324  * Note that here, we need the RHS type to be text, so that the
325  * comparison value isn't improperly truncated to NAMEDATALEN.
326  */
327  eqopr = NameEqualTextOperator;
328  ltopr = NameLessTextOperator;
329  geopr = NameGreaterEqualTextOperator;
330  collation_aware = true;
331  rdatatype = TEXTOID;
332  break;
333  case BPCHAROID:
334  if (opfamily == BPCHAR_PATTERN_BTREE_FAM_OID)
335  {
336  eqopr = BpcharEqualOperator;
337  ltopr = BpcharPatternLessOperator;
338  geopr = BpcharPatternGreaterEqualOperator;
339  collation_aware = false;
340  }
341  else
342  {
343  eqopr = BpcharEqualOperator;
344  ltopr = BpcharLessOperator;
345  geopr = BpcharGreaterEqualOperator;
346  collation_aware = true;
347  }
348  rdatatype = BPCHAROID;
349  break;
350  case BYTEAOID:
351  eqopr = ByteaEqualOperator;
352  ltopr = ByteaLessOperator;
353  geopr = ByteaGreaterEqualOperator;
354  collation_aware = false;
355  rdatatype = BYTEAOID;
356  break;
357  default:
358  /* Can't get here unless we're attached to the wrong operator */
359  return NIL;
360  }
361 
362  /*
363  * If necessary, verify that the index's collation behavior is compatible.
364  * For an exact-match case, we don't have to be picky. Otherwise, insist
365  * that the index collation be "C". Note that here we are looking at the
366  * index's collation, not the expression's collation -- this test is *not*
367  * dependent on the LIKE/regex operator's collation.
368  */
369  if (collation_aware)
370  {
371  if (!(pstatus == Pattern_Prefix_Exact ||
372  lc_collate_is_c(indexcollation)))
373  return NIL;
374  }
375 
376  /*
377  * If necessary, coerce the prefix constant to the right type. The given
378  * prefix constant is either text or bytea type, therefore the only case
379  * where we need to do anything is when converting text to bpchar. Those
380  * two types are binary-compatible, so relabeling the Const node is
381  * sufficient.
382  */
383  if (prefix->consttype != rdatatype)
384  {
385  Assert(prefix->consttype == TEXTOID &&
386  rdatatype == BPCHAROID);
387  prefix->consttype = rdatatype;
388  }
389 
390  /*
391  * If we found an exact-match pattern, generate an "=" indexqual.
392  *
393  * Here and below, check to see whether the desired operator is actually
394  * supported by the index opclass, and fail quietly if not. This allows
395  * us to not be concerned with specific opclasses (except for the legacy
396  * "pattern" cases); any index that correctly implements the operators
397  * will work.
398  */
399  if (pstatus == Pattern_Prefix_Exact)
400  {
401  if (!op_in_opfamily(eqopr, opfamily))
402  return NIL;
403  expr = make_opclause(eqopr, BOOLOID, false,
404  (Expr *) leftop, (Expr *) prefix,
405  InvalidOid, indexcollation);
406  result = list_make1(expr);
407  return result;
408  }
409 
410  /*
411  * Otherwise, we have a nonempty required prefix of the values.
412  *
413  * We can always say "x >= prefix".
414  */
415  if (!op_in_opfamily(geopr, opfamily))
416  return NIL;
417  expr = make_opclause(geopr, BOOLOID, false,
418  (Expr *) leftop, (Expr *) prefix,
419  InvalidOid, indexcollation);
420  result = list_make1(expr);
421 
422  /*-------
423  * If we can create a string larger than the prefix, we can say
424  * "x < greaterstr". NB: we rely on make_greater_string() to generate
425  * a guaranteed-greater string, not just a probably-greater string.
426  * In general this is only guaranteed in C locale, so we'd better be
427  * using a C-locale index collation.
428  *-------
429  */
430  if (!op_in_opfamily(ltopr, opfamily))
431  return result;
432  fmgr_info(get_opcode(ltopr), &ltproc);
433  greaterstr = make_greater_string(prefix, &ltproc, indexcollation);
434  if (greaterstr)
435  {
436  expr = make_opclause(ltopr, BOOLOID, false,
437  (Expr *) leftop, (Expr *) greaterstr,
438  InvalidOid, indexcollation);
439  result = lappend(result, expr);
440  }
441 
442  return result;
443 }
#define NIL
Definition: pg_list.h:65
bool op_in_opfamily(Oid opno, Oid opfamily)
Definition: lsyscache.c:63
Definition: fmgr.h:56
#define IsA(nodeptr, _type_)
Definition: nodes.h:576
bool get_collation_isdeterministic(Oid colloid)
Definition: lsyscache.c:942
unsigned int Oid
Definition: postgres_ext.h:31
Expr * make_opclause(Oid opno, Oid opresulttype, bool opretset, Expr *leftop, Expr *rightop, Oid opcollid, Oid inputcollid)
Definition: makefuncs.c:607
static Pattern_Prefix_Status pattern_fixed_prefix(Const *patt, Pattern_Type ptype, Oid collation, Const **prefix, Selectivity *rest_selec)
#define list_make1(x1)
Definition: pg_list.h:227
Oid consttype
Definition: primnodes.h:196
bool lc_collate_is_c(Oid collation)
Definition: pg_locale.c:1176
void fmgr_info(Oid functionId, FmgrInfo *finfo)
Definition: fmgr.c:124
List * lappend(List *list, void *datum)
Definition: list.c:322
Pattern_Prefix_Status
Definition: like_support.c:67
static Const * make_greater_string(const Const *str_const, FmgrInfo *ltproc, Oid collation)
#define InvalidOid
Definition: postgres_ext.h:36
RegProcedure get_opcode(Oid opno)
Definition: lsyscache.c:1092
#define Assert(condition)
Definition: c.h:739
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:41
Definition: pg_list.h:50

◆ nlikejoinsel()

Datum nlikejoinsel ( PG_FUNCTION_ARGS  )

Definition at line 924 of file like_support.c.

References Pattern_Type_Like, patternjoinsel(), and PG_RETURN_FLOAT8.

925 {
927 }
static double patternjoinsel(PG_FUNCTION_ARGS, Pattern_Type ptype, bool negate)
Definition: like_support.c:851
#define PG_RETURN_FLOAT8(x)
Definition: fmgr.h:356

◆ nlikesel()

Datum nlikesel ( PG_FUNCTION_ARGS  )

Definition at line 833 of file like_support.c.

References Pattern_Type_Like, patternsel(), and PG_RETURN_FLOAT8.

834 {
836 }
static double patternsel(PG_FUNCTION_ARGS, Pattern_Type ptype, bool negate)
Definition: like_support.c:736
#define PG_RETURN_FLOAT8(x)
Definition: fmgr.h:356

◆ pattern_char_isalpha()

static int pattern_char_isalpha ( char  c,
bool  is_multibyte,
pg_locale_t  locale,
bool  locale_is_c 
)
static

Definition at line 1473 of file like_support.c.

References pg_locale_struct::info, IS_HIGHBIT_SET, isalpha_l, and pg_locale_struct::provider.

Referenced by like_fixed_prefix().

1475 {
1476  if (locale_is_c)
1477  return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z');
1478  else if (is_multibyte && IS_HIGHBIT_SET(c))
1479  return true;
1480  else if (locale && locale->provider == COLLPROVIDER_ICU)
1481  return IS_HIGHBIT_SET(c) ||
1482  (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z');
1483 #ifdef HAVE_LOCALE_T
1484  else if (locale && locale->provider == COLLPROVIDER_LIBC)
1485  return isalpha_l((unsigned char) c, locale->info.lt);
1486 #endif
1487  else
1488  return isalpha((unsigned char) c);
1489 }
union pg_locale_struct::@144 info
#define isalpha_l
Definition: win32_port.h:370
#define IS_HIGHBIT_SET(ch)
Definition: c.h:1106
char * c

◆ pattern_fixed_prefix()

static Pattern_Prefix_Status pattern_fixed_prefix ( Const patt,
Pattern_Type  ptype,
Oid  collation,
Const **  prefix,
Selectivity rest_selec 
)
static

Definition at line 1144 of file like_support.c.

References Const::constbyval, Const::constcollid, Const::constisnull, Const::constlen, Const::consttype, Const::consttypmod, Const::constvalue, datumCopy(), elog, ERROR, like_fixed_prefix(), makeConst(), Pattern_Prefix_None, Pattern_Prefix_Partial, Pattern_Type_Like, Pattern_Type_Like_IC, Pattern_Type_Prefix, Pattern_Type_Regex, Pattern_Type_Regex_IC, and regex_fixed_prefix().

Referenced by match_pattern_prefix(), and patternsel_common().

1146 {
1147  Pattern_Prefix_Status result;
1148 
1149  switch (ptype)
1150  {
1151  case Pattern_Type_Like:
1152  result = like_fixed_prefix(patt, false, collation,
1153  prefix, rest_selec);
1154  break;
1155  case Pattern_Type_Like_IC:
1156  result = like_fixed_prefix(patt, true, collation,
1157  prefix, rest_selec);
1158  break;
1159  case Pattern_Type_Regex:
1160  result = regex_fixed_prefix(patt, false, collation,
1161  prefix, rest_selec);
1162  break;
1163  case Pattern_Type_Regex_IC:
1164  result = regex_fixed_prefix(patt, true, collation,
1165  prefix, rest_selec);
1166  break;
1167  case Pattern_Type_Prefix:
1168  /* Prefix type work is trivial. */
1169  result = Pattern_Prefix_Partial;
1170  *rest_selec = 1.0; /* all */
1171  *prefix = makeConst(patt->consttype,
1172  patt->consttypmod,
1173  patt->constcollid,
1174  patt->constlen,
1175  datumCopy(patt->constvalue,
1176  patt->constbyval,
1177  patt->constlen),
1178  patt->constisnull,
1179  patt->constbyval);
1180  break;
1181  default:
1182  elog(ERROR, "unrecognized ptype: %d", (int) ptype);
1183  result = Pattern_Prefix_None; /* keep compiler quiet */
1184  break;
1185  }
1186  return result;
1187 }
Datum constvalue
Definition: primnodes.h:200
bool constbyval
Definition: primnodes.h:203
Const * makeConst(Oid consttype, int32 consttypmod, Oid constcollid, int constlen, Datum constvalue, bool constisnull, bool constbyval)
Definition: makefuncs.c:297
int constlen
Definition: primnodes.h:199
Oid consttype
Definition: primnodes.h:196
#define ERROR
Definition: elog.h:43
Oid constcollid
Definition: primnodes.h:198
static Pattern_Prefix_Status like_fixed_prefix(Const *patt_const, bool case_insensitive, Oid collation, Const **prefix_const, Selectivity *rest_selec)
Definition: like_support.c:968
Datum datumCopy(Datum value, bool typByVal, int typLen)
Definition: datum.c:130
Pattern_Prefix_Status
Definition: like_support.c:67
static Pattern_Prefix_Status regex_fixed_prefix(Const *patt_const, bool case_insensitive, Oid collation, Const **prefix_const, Selectivity *rest_selec)
int32 consttypmod
Definition: primnodes.h:197
#define elog(elevel,...)
Definition: elog.h:228
bool constisnull
Definition: primnodes.h:201

◆ patternjoinsel()

static double patternjoinsel ( PG_FUNCTION_ARGS  ,
Pattern_Type  ptype,
bool  negate 
)
static

Definition at line 851 of file like_support.c.

References DEFAULT_MATCH_SEL.

Referenced by iclikejoinsel(), icnlikejoinsel(), icregexeqjoinsel(), icregexnejoinsel(), likejoinsel(), nlikejoinsel(), prefixjoinsel(), regexeqjoinsel(), and regexnejoinsel().

852 {
853  /* For the moment we just punt. */
854  return negate ? (1.0 - DEFAULT_MATCH_SEL) : DEFAULT_MATCH_SEL;
855 }
#define DEFAULT_MATCH_SEL
Definition: selfuncs.h:43

◆ patternsel()

static double patternsel ( PG_FUNCTION_ARGS  ,
Pattern_Type  ptype,
bool  negate 
)
static

Definition at line 736 of file like_support.c.

References generate_unaccent_rules::args, elog, ERROR, get_negator(), InvalidOid, OidIsValid, patternsel_common(), PG_GET_COLLATION, PG_GETARG_INT32, PG_GETARG_OID, and PG_GETARG_POINTER.

Referenced by iclikesel(), icnlikesel(), icregexeqsel(), icregexnesel(), likesel(), nlikesel(), prefixsel(), regexeqsel(), and regexnesel().

737 {
739  Oid operator = PG_GETARG_OID(1);
740  List *args = (List *) PG_GETARG_POINTER(2);
741  int varRelid = PG_GETARG_INT32(3);
742  Oid collation = PG_GET_COLLATION();
743 
744  /*
745  * If this is for a NOT LIKE or similar operator, get the corresponding
746  * positive-match operator and work with that.
747  */
748  if (negate)
749  {
750  operator = get_negator(operator);
751  if (!OidIsValid(operator))
752  elog(ERROR, "patternsel called for operator without a negator");
753  }
754 
755  return patternsel_common(root,
756  operator,
757  InvalidOid,
758  args,
759  varRelid,
760  collation,
761  ptype,
762  negate);
763 }
#define PG_GETARG_INT32(n)
Definition: fmgr.h:264
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:271
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:645
#define PG_GET_COLLATION()
Definition: fmgr.h:193
#define ERROR
Definition: elog.h:43
#define PG_GETARG_OID(n)
Definition: fmgr.h:270
#define InvalidOid
Definition: postgres_ext.h:36
static double patternsel_common(PlannerInfo *root, Oid oprid, Oid opfuncid, List *args, int varRelid, Oid collation, Pattern_Type ptype, bool negate)
Definition: like_support.c:459
#define elog(elevel,...)
Definition: elog.h:228
Oid get_negator(Oid opno)
Definition: lsyscache.c:1335
Definition: pg_list.h:50

◆ patternsel_common()

static double patternsel_common ( PlannerInfo root,
Oid  oprid,
Oid  opfuncid,
List args,
int  varRelid,
Oid  collation,
Pattern_Type  ptype,
bool  negate 
)
static

Definition at line 459 of file like_support.c.

References Assert, CLAMP_PROBABILITY, Const::consttype, Const::constvalue, DatumGetPointer, DEFAULT_MATCH_SEL, fmgr_info(), get_opcode(), get_restriction_variable(), GETSTRUCT, HeapTupleIsValid, histogram_selectivity(), IsA, mcv_selectivity(), OidIsValid, pattern_fixed_prefix(), Pattern_Prefix_Exact, Pattern_Prefix_Partial, pfree(), prefix_selectivity(), prefixsel(), ReleaseVariableStats, VariableStatData::statsTuple, var_eq_const(), and VariableStatData::vartype.

Referenced by like_regex_support(), and patternsel().

467 {
468  VariableStatData vardata;
469  Node *other;
470  bool varonleft;
471  Datum constval;
472  Oid consttype;
473  Oid vartype;
474  Oid rdatatype;
475  Oid eqopr;
476  Oid ltopr;
477  Oid geopr;
478  Pattern_Prefix_Status pstatus;
479  Const *patt;
480  Const *prefix = NULL;
481  Selectivity rest_selec = 0;
482  double nullfrac = 0.0;
483  double result;
484 
485  /*
486  * Initialize result to the appropriate default estimate depending on
487  * whether it's a match or not-match operator.
488  */
489  if (negate)
490  result = 1.0 - DEFAULT_MATCH_SEL;
491  else
492  result = DEFAULT_MATCH_SEL;
493 
494  /*
495  * If expression is not variable op constant, then punt and return the
496  * default estimate.
497  */
498  if (!get_restriction_variable(root, args, varRelid,
499  &vardata, &other, &varonleft))
500  return result;
501  if (!varonleft || !IsA(other, Const))
502  {
503  ReleaseVariableStats(vardata);
504  return result;
505  }
506 
507  /*
508  * If the constant is NULL, assume operator is strict and return zero, ie,
509  * operator will never return TRUE. (It's zero even for a negator op.)
510  */
511  if (((Const *) other)->constisnull)
512  {
513  ReleaseVariableStats(vardata);
514  return 0.0;
515  }
516  constval = ((Const *) other)->constvalue;
517  consttype = ((Const *) other)->consttype;
518 
519  /*
520  * The right-hand const is type text or bytea for all supported operators.
521  * We do not expect to see binary-compatible types here, since
522  * const-folding should have relabeled the const to exactly match the
523  * operator's declared type.
524  */
525  if (consttype != TEXTOID && consttype != BYTEAOID)
526  {
527  ReleaseVariableStats(vardata);
528  return result;
529  }
530 
531  /*
532  * Similarly, the exposed type of the left-hand side should be one of
533  * those we know. (Do not look at vardata.atttype, which might be
534  * something binary-compatible but different.) We can use it to identify
535  * the comparison operators and the required type of the comparison
536  * constant, much as in match_pattern_prefix().
537  *
538  * NOTE: this logic does not consider collations. Ideally we'd force use
539  * of "C" collation, but since ANALYZE only generates statistics for the
540  * column's specified collation, we have little choice but to use those.
541  * But our results are so approximate anyway that it probably hardly
542  * matters.
543  */
544  vartype = vardata.vartype;
545 
546  switch (vartype)
547  {
548  case TEXTOID:
549  eqopr = TextEqualOperator;
550  ltopr = TextLessOperator;
551  geopr = TextGreaterEqualOperator;
552  rdatatype = TEXTOID;
553  break;
554  case NAMEOID:
555 
556  /*
557  * Note that here, we need the RHS type to be text, so that the
558  * comparison value isn't improperly truncated to NAMEDATALEN.
559  */
560  eqopr = NameEqualTextOperator;
561  ltopr = NameLessTextOperator;
562  geopr = NameGreaterEqualTextOperator;
563  rdatatype = TEXTOID;
564  break;
565  case BPCHAROID:
566  eqopr = BpcharEqualOperator;
567  ltopr = BpcharLessOperator;
568  geopr = BpcharGreaterEqualOperator;
569  rdatatype = BPCHAROID;
570  break;
571  case BYTEAOID:
572  eqopr = ByteaEqualOperator;
573  ltopr = ByteaLessOperator;
574  geopr = ByteaGreaterEqualOperator;
575  rdatatype = BYTEAOID;
576  break;
577  default:
578  /* Can't get here unless we're attached to the wrong operator */
579  ReleaseVariableStats(vardata);
580  return result;
581  }
582 
583  /*
584  * Grab the nullfrac for use below.
585  */
586  if (HeapTupleIsValid(vardata.statsTuple))
587  {
588  Form_pg_statistic stats;
589 
590  stats = (Form_pg_statistic) GETSTRUCT(vardata.statsTuple);
591  nullfrac = stats->stanullfrac;
592  }
593 
594  /*
595  * Pull out any fixed prefix implied by the pattern, and estimate the
596  * fractional selectivity of the remainder of the pattern. Unlike many
597  * other selectivity estimators, we use the pattern operator's actual
598  * collation for this step. This is not because we expect the collation
599  * to make a big difference in the selectivity estimate (it seldom would),
600  * but because we want to be sure we cache compiled regexps under the
601  * right cache key, so that they can be re-used at runtime.
602  */
603  patt = (Const *) other;
604  pstatus = pattern_fixed_prefix(patt, ptype, collation,
605  &prefix, &rest_selec);
606 
607  /*
608  * If necessary, coerce the prefix constant to the right type. The only
609  * case where we need to do anything is when converting text to bpchar.
610  * Those two types are binary-compatible, so relabeling the Const node is
611  * sufficient.
612  */
613  if (prefix && prefix->consttype != rdatatype)
614  {
615  Assert(prefix->consttype == TEXTOID &&
616  rdatatype == BPCHAROID);
617  prefix->consttype = rdatatype;
618  }
619 
620  if (pstatus == Pattern_Prefix_Exact)
621  {
622  /*
623  * Pattern specifies an exact match, so estimate as for '='
624  */
625  result = var_eq_const(&vardata, eqopr, prefix->constvalue,
626  false, true, false);
627  }
628  else
629  {
630  /*
631  * Not exact-match pattern. If we have a sufficiently large
632  * histogram, estimate selectivity for the histogram part of the
633  * population by counting matches in the histogram. If not, estimate
634  * selectivity of the fixed prefix and remainder of pattern
635  * separately, then combine the two to get an estimate of the
636  * selectivity for the part of the column population represented by
637  * the histogram. (For small histograms, we combine these
638  * approaches.)
639  *
640  * We then add up data for any most-common-values values; these are
641  * not in the histogram population, and we can get exact answers for
642  * them by applying the pattern operator, so there's no reason to
643  * approximate. (If the MCVs cover a significant part of the total
644  * population, this gives us a big leg up in accuracy.)
645  */
646  Selectivity selec;
647  int hist_size;
648  FmgrInfo opproc;
649  double mcv_selec,
650  sumcommon;
651 
652  /* Try to use the histogram entries to get selectivity */
653  if (!OidIsValid(opfuncid))
654  opfuncid = get_opcode(oprid);
655  fmgr_info(opfuncid, &opproc);
656 
657  selec = histogram_selectivity(&vardata, &opproc, constval, true,
658  10, 1, &hist_size);
659 
660  /* If not at least 100 entries, use the heuristic method */
661  if (hist_size < 100)
662  {
663  Selectivity heursel;
665 
666  if (pstatus == Pattern_Prefix_Partial)
667  prefixsel = prefix_selectivity(root, &vardata,
668  eqopr, ltopr, geopr,
669  prefix);
670  else
671  prefixsel = 1.0;
672  heursel = prefixsel * rest_selec;
673 
674  if (selec < 0) /* fewer than 10 histogram entries? */
675  selec = heursel;
676  else
677  {
678  /*
679  * For histogram sizes from 10 to 100, we combine the
680  * histogram and heuristic selectivities, putting increasingly
681  * more trust in the histogram for larger sizes.
682  */
683  double hist_weight = hist_size / 100.0;
684 
685  selec = selec * hist_weight + heursel * (1.0 - hist_weight);
686  }
687  }
688 
689  /* In any case, don't believe extremely small or large estimates. */
690  if (selec < 0.0001)
691  selec = 0.0001;
692  else if (selec > 0.9999)
693  selec = 0.9999;
694 
695  /*
696  * If we have most-common-values info, add up the fractions of the MCV
697  * entries that satisfy MCV OP PATTERN. These fractions contribute
698  * directly to the result selectivity. Also add up the total fraction
699  * represented by MCV entries.
700  */
701  mcv_selec = mcv_selectivity(&vardata, &opproc, constval, true,
702  &sumcommon);
703 
704  /*
705  * Now merge the results from the MCV and histogram calculations,
706  * realizing that the histogram covers only the non-null values that
707  * are not listed in MCV.
708  */
709  selec *= 1.0 - nullfrac - sumcommon;
710  selec += mcv_selec;
711  result = selec;
712  }
713 
714  /* now adjust if we wanted not-match rather than match */
715  if (negate)
716  result = 1.0 - result - nullfrac;
717 
718  /* result should be in range, but make sure... */
719  CLAMP_PROBABILITY(result);
720 
721  if (prefix)
722  {
723  pfree(DatumGetPointer(prefix->constvalue));
724  pfree(prefix);
725  }
726 
727  ReleaseVariableStats(vardata);
728 
729  return result;
730 }
Datum constvalue
Definition: primnodes.h:200
Definition: fmgr.h:56
#define IsA(nodeptr, _type_)
Definition: nodes.h:576
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
HeapTuple statsTuple
Definition: selfuncs.h:71
Oid oprid(Operator op)
Definition: parse_oper.c:245
bool get_restriction_variable(PlannerInfo *root, List *args, int varRelid, VariableStatData *vardata, Node **other, bool *varonleft)
Definition: selfuncs.c:4296
double var_eq_const(VariableStatData *vardata, Oid operator, Datum constval, bool constisnull, bool varonleft, bool negate)
Definition: selfuncs.c:289
Definition: nodes.h:525
double Selectivity
Definition: nodes.h:658
unsigned int Oid
Definition: postgres_ext.h:31
FormData_pg_statistic * Form_pg_statistic
Definition: pg_statistic.h:134
#define OidIsValid(objectId)
Definition: c.h:645
static Pattern_Prefix_Status pattern_fixed_prefix(Const *patt, Pattern_Type ptype, Oid collation, Const **prefix, Selectivity *rest_selec)
#define CLAMP_PROBABILITY(p)
Definition: selfuncs.h:57
Oid consttype
Definition: primnodes.h:196
void pfree(void *pointer)
Definition: mcxt.c:1056
void fmgr_info(Oid functionId, FmgrInfo *finfo)
Definition: fmgr.c:124
static Selectivity prefix_selectivity(PlannerInfo *root, VariableStatData *vardata, Oid eqopr, Oid ltopr, Oid geopr, Const *prefixcon)
#define DEFAULT_MATCH_SEL
Definition: selfuncs.h:43
Pattern_Prefix_Status
Definition: like_support.c:67
uintptr_t Datum
Definition: postgres.h:367
double histogram_selectivity(VariableStatData *vardata, FmgrInfo *opproc, Datum constval, bool varonleft, int min_hist_size, int n_skip, int *hist_size)
Definition: selfuncs.c:779
double mcv_selectivity(VariableStatData *vardata, FmgrInfo *opproc, Datum constval, bool varonleft, double *sumcommonp)
Definition: selfuncs.c:707
RegProcedure get_opcode(Oid opno)
Definition: lsyscache.c:1092
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define Assert(condition)
Definition: c.h:739
#define DatumGetPointer(X)
Definition: postgres.h:549
#define ReleaseVariableStats(vardata)
Definition: selfuncs.h:81
Datum prefixsel(PG_FUNCTION_ARGS)
Definition: like_support.c:796

◆ prefix_selectivity()

static Selectivity prefix_selectivity ( PlannerInfo root,
VariableStatData vardata,
Oid  eqopr,
Oid  ltopr,
Oid  geopr,
Const prefixcon 
)
static

Definition at line 1208 of file like_support.c.

References Assert, Const::consttype, Const::constvalue, DEFAULT_MATCH_SEL, fmgr_info(), get_attstatsslot(), get_opcode(), HeapTupleIsValid, ineq_histogram_selectivity(), InvalidOid, make_greater_string(), Max, prefixsel(), AttStatsSlot::stacoll, VariableStatData::statsTuple, and var_eq_const().

Referenced by patternsel_common().

1211 {
1213  FmgrInfo opproc;
1214  AttStatsSlot sslot;
1215  Const *greaterstrcon;
1216  Selectivity eq_sel;
1217 
1218  /* Estimate the selectivity of "x >= prefix" */
1219  fmgr_info(get_opcode(geopr), &opproc);
1220 
1221  prefixsel = ineq_histogram_selectivity(root, vardata,
1222  &opproc, true, true,
1223  prefixcon->constvalue,
1224  prefixcon->consttype);
1225 
1226  if (prefixsel < 0.0)
1227  {
1228  /* No histogram is present ... return a suitable default estimate */
1229  return DEFAULT_MATCH_SEL;
1230  }
1231 
1232  /*-------
1233  * If we can create a string larger than the prefix, say
1234  * "x < greaterstr". We try to generate the string referencing the
1235  * collation of the var's statistics, but if that's not available,
1236  * use DEFAULT_COLLATION_OID.
1237  *-------
1238  */
1239  if (HeapTupleIsValid(vardata->statsTuple) &&
1240  get_attstatsslot(&sslot, vardata->statsTuple,
1241  STATISTIC_KIND_HISTOGRAM, InvalidOid, 0))
1242  /* sslot.stacoll is set up */ ;
1243  else
1244  sslot.stacoll = DEFAULT_COLLATION_OID;
1245  fmgr_info(get_opcode(ltopr), &opproc);
1246  greaterstrcon = make_greater_string(prefixcon, &opproc, sslot.stacoll);
1247  if (greaterstrcon)
1248  {
1249  Selectivity topsel;
1250 
1251  topsel = ineq_histogram_selectivity(root, vardata,
1252  &opproc, false, false,
1253  greaterstrcon->constvalue,
1254  greaterstrcon->consttype);
1255 
1256  /* ineq_histogram_selectivity worked before, it shouldn't fail now */
1257  Assert(topsel >= 0.0);
1258 
1259  /*
1260  * Merge the two selectivities in the same way as for a range query
1261  * (see clauselist_selectivity()). Note that we don't need to worry
1262  * about double-exclusion of nulls, since ineq_histogram_selectivity
1263  * doesn't count those anyway.
1264  */
1265  prefixsel = topsel + prefixsel - 1.0;
1266  }
1267 
1268  /*
1269  * If the prefix is long then the two bounding values might be too close
1270  * together for the histogram to distinguish them usefully, resulting in a
1271  * zero estimate (plus or minus roundoff error). To avoid returning a
1272  * ridiculously small estimate, compute the estimated selectivity for
1273  * "variable = 'foo'", and clamp to that. (Obviously, the resultant
1274  * estimate should be at least that.)
1275  *
1276  * We apply this even if we couldn't make a greater string. That case
1277  * suggests that the prefix is near the maximum possible, and thus
1278  * probably off the end of the histogram, and thus we probably got a very
1279  * small estimate from the >= condition; so we still need to clamp.
1280  */
1281  eq_sel = var_eq_const(vardata, eqopr, prefixcon->constvalue,
1282  false, true, false);
1283 
1284  prefixsel = Max(prefixsel, eq_sel);
1285 
1286  return prefixsel;
1287 }
Datum constvalue
Definition: primnodes.h:200
Definition: fmgr.h:56
HeapTuple statsTuple
Definition: selfuncs.h:71
double var_eq_const(VariableStatData *vardata, Oid operator, Datum constval, bool constisnull, bool varonleft, bool negate)
Definition: selfuncs.c:289
double Selectivity
Definition: nodes.h:658
Oid consttype
Definition: primnodes.h:196
void fmgr_info(Oid functionId, FmgrInfo *finfo)
Definition: fmgr.c:124
double ineq_histogram_selectivity(PlannerInfo *root, VariableStatData *vardata, FmgrInfo *opproc, bool isgt, bool iseq, Datum constval, Oid consttype)
Definition: selfuncs.c:847
#define DEFAULT_MATCH_SEL
Definition: selfuncs.h:43
static Const * make_greater_string(const Const *str_const, FmgrInfo *ltproc, Oid collation)
#define InvalidOid
Definition: postgres_ext.h:36
RegProcedure get_opcode(Oid opno)
Definition: lsyscache.c:1092
#define Max(x, y)
Definition: c.h:905
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
bool get_attstatsslot(AttStatsSlot *sslot, HeapTuple statstuple, int reqkind, Oid reqop, int flags)
Definition: lsyscache.c:2942
#define Assert(condition)
Definition: c.h:739
Datum prefixsel(PG_FUNCTION_ARGS)
Definition: like_support.c:796

◆ prefixjoinsel()

Datum prefixjoinsel ( PG_FUNCTION_ARGS  )

Definition at line 888 of file like_support.c.

References Pattern_Type_Prefix, patternjoinsel(), and PG_RETURN_FLOAT8.

889 {
891 }
static double patternjoinsel(PG_FUNCTION_ARGS, Pattern_Type ptype, bool negate)
Definition: like_support.c:851
#define PG_RETURN_FLOAT8(x)
Definition: fmgr.h:356

◆ prefixsel()

Datum prefixsel ( PG_FUNCTION_ARGS  )

Definition at line 796 of file like_support.c.

References Pattern_Type_Prefix, patternsel(), and PG_RETURN_FLOAT8.

Referenced by patternsel_common(), and prefix_selectivity().

797 {
799 }
static double patternsel(PG_FUNCTION_ARGS, Pattern_Type ptype, bool negate)
Definition: like_support.c:736
#define PG_RETURN_FLOAT8(x)
Definition: fmgr.h:356

◆ regex_fixed_prefix()

static Pattern_Prefix_Status regex_fixed_prefix ( Const patt_const,
bool  case_insensitive,
Oid  collation,
Const **  prefix_const,
Selectivity rest_selec 
)
static

Definition at line 1076 of file like_support.c.

References Const::consttype, Const::constvalue, DatumGetTextPP, ereport, errcode(), errmsg(), ERROR, Pattern_Prefix_Exact, Pattern_Prefix_None, Pattern_Prefix_Partial, pfree(), regex_selectivity(), regexp_fixed_prefix(), string_to_const(), and TextDatumGetCString.

Referenced by pattern_fixed_prefix().

1078 {
1079  Oid typeid = patt_const->consttype;
1080  char *prefix;
1081  bool exact;
1082 
1083  /*
1084  * Should be unnecessary, there are no bytea regex operators defined. As
1085  * such, it should be noted that the rest of this function has *not* been
1086  * made safe for binary (possibly NULL containing) strings.
1087  */
1088  if (typeid == BYTEAOID)
1089  ereport(ERROR,
1090  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1091  errmsg("regular-expression matching not supported on type bytea")));
1092 
1093  /* Use the regexp machinery to extract the prefix, if any */
1094  prefix = regexp_fixed_prefix(DatumGetTextPP(patt_const->constvalue),
1095  case_insensitive, collation,
1096  &exact);
1097 
1098  if (prefix == NULL)
1099  {
1100  *prefix_const = NULL;
1101 
1102  if (rest_selec != NULL)
1103  {
1104  char *patt = TextDatumGetCString(patt_const->constvalue);
1105 
1106  *rest_selec = regex_selectivity(patt, strlen(patt),
1107  case_insensitive,
1108  0);
1109  pfree(patt);
1110  }
1111 
1112  return Pattern_Prefix_None;
1113  }
1114 
1115  *prefix_const = string_to_const(prefix, typeid);
1116 
1117  if (rest_selec != NULL)
1118  {
1119  if (exact)
1120  {
1121  /* Exact match, so there's no additional selectivity */
1122  *rest_selec = 1.0;
1123  }
1124  else
1125  {
1126  char *patt = TextDatumGetCString(patt_const->constvalue);
1127 
1128  *rest_selec = regex_selectivity(patt, strlen(patt),
1129  case_insensitive,
1130  strlen(prefix));
1131  pfree(patt);
1132  }
1133  }
1134 
1135  pfree(prefix);
1136 
1137  if (exact)
1138  return Pattern_Prefix_Exact; /* pattern specifies exact match */
1139  else
1140  return Pattern_Prefix_Partial;
1141 }
Datum constvalue
Definition: primnodes.h:200
static Const * string_to_const(const char *str, Oid datatype)
#define DatumGetTextPP(X)
Definition: fmgr.h:286
int errcode(int sqlerrcode)
Definition: elog.c:608
unsigned int Oid
Definition: postgres_ext.h:31
Oid consttype
Definition: primnodes.h:196
void pfree(void *pointer)
Definition: mcxt.c:1056
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:141
#define TextDatumGetCString(d)
Definition: builtins.h:84
static Selectivity regex_selectivity(const char *patt, int pattlen, bool case_insensitive, int fixed_prefix_len)
char * regexp_fixed_prefix(text *text_re, bool case_insensitive, Oid collation, bool *exact)
Definition: regexp.c:1503
int errmsg(const char *fmt,...)
Definition: elog.c:822

◆ regex_selectivity()

static Selectivity regex_selectivity ( const char *  patt,
int  pattlen,
bool  case_insensitive,
int  fixed_prefix_len 
)
static

Definition at line 1436 of file like_support.c.

References CLAMP_PROBABILITY, FIXED_CHAR_SEL, FULL_WILDCARD_SEL, and regex_selectivity_sub().

Referenced by regex_fixed_prefix().

1438 {
1439  Selectivity sel;
1440 
1441  /* If patt doesn't end with $, consider it to have a trailing wildcard */
1442  if (pattlen > 0 && patt[pattlen - 1] == '$' &&
1443  (pattlen == 1 || patt[pattlen - 2] != '\\'))
1444  {
1445  /* has trailing $ */
1446  sel = regex_selectivity_sub(patt, pattlen - 1, case_insensitive);
1447  }
1448  else
1449  {
1450  /* no trailing $ */
1451  sel = regex_selectivity_sub(patt, pattlen, case_insensitive);
1452  sel *= FULL_WILDCARD_SEL;
1453  }
1454 
1455  /* If there's a fixed prefix, discount its selectivity */
1456  if (fixed_prefix_len > 0)
1457  sel /= pow(FIXED_CHAR_SEL, fixed_prefix_len);
1458 
1459  /* Make sure result stays in range */
1460  CLAMP_PROBABILITY(sel);
1461  return sel;
1462 }
static Selectivity regex_selectivity_sub(const char *patt, int pattlen, bool case_insensitive)
#define FULL_WILDCARD_SEL
double Selectivity
Definition: nodes.h:658
#define CLAMP_PROBABILITY(p)
Definition: selfuncs.h:57
#define FIXED_CHAR_SEL

◆ regex_selectivity_sub()

static Selectivity regex_selectivity_sub ( const char *  patt,
int  pattlen,
bool  case_insensitive 
)
static

Definition at line 1344 of file like_support.c.

References ANY_CHAR_SEL, CHAR_RANGE_SEL, FIXED_CHAR_SEL, and PARTIAL_WILDCARD_SEL.

Referenced by regex_selectivity().

1345 {
1346  Selectivity sel = 1.0;
1347  int paren_depth = 0;
1348  int paren_pos = 0; /* dummy init to keep compiler quiet */
1349  int pos;
1350 
1351  for (pos = 0; pos < pattlen; pos++)
1352  {
1353  if (patt[pos] == '(')
1354  {
1355  if (paren_depth == 0)
1356  paren_pos = pos; /* remember start of parenthesized item */
1357  paren_depth++;
1358  }
1359  else if (patt[pos] == ')' && paren_depth > 0)
1360  {
1361  paren_depth--;
1362  if (paren_depth == 0)
1363  sel *= regex_selectivity_sub(patt + (paren_pos + 1),
1364  pos - (paren_pos + 1),
1365  case_insensitive);
1366  }
1367  else if (patt[pos] == '|' && paren_depth == 0)
1368  {
1369  /*
1370  * If unquoted | is present at paren level 0 in pattern, we have
1371  * multiple alternatives; sum their probabilities.
1372  */
1373  sel += regex_selectivity_sub(patt + (pos + 1),
1374  pattlen - (pos + 1),
1375  case_insensitive);
1376  break; /* rest of pattern is now processed */
1377  }
1378  else if (patt[pos] == '[')
1379  {
1380  bool negclass = false;
1381 
1382  if (patt[++pos] == '^')
1383  {
1384  negclass = true;
1385  pos++;
1386  }
1387  if (patt[pos] == ']') /* ']' at start of class is not special */
1388  pos++;
1389  while (pos < pattlen && patt[pos] != ']')
1390  pos++;
1391  if (paren_depth == 0)
1392  sel *= (negclass ? (1.0 - CHAR_RANGE_SEL) : CHAR_RANGE_SEL);
1393  }
1394  else if (patt[pos] == '.')
1395  {
1396  if (paren_depth == 0)
1397  sel *= ANY_CHAR_SEL;
1398  }
1399  else if (patt[pos] == '*' ||
1400  patt[pos] == '?' ||
1401  patt[pos] == '+')
1402  {
1403  /* Ought to be smarter about quantifiers... */
1404  if (paren_depth == 0)
1405  sel *= PARTIAL_WILDCARD_SEL;
1406  }
1407  else if (patt[pos] == '{')
1408  {
1409  while (pos < pattlen && patt[pos] != '}')
1410  pos++;
1411  if (paren_depth == 0)
1412  sel *= PARTIAL_WILDCARD_SEL;
1413  }
1414  else if (patt[pos] == '\\')
1415  {
1416  /* backslash quotes the next character */
1417  pos++;
1418  if (pos >= pattlen)
1419  break;
1420  if (paren_depth == 0)
1421  sel *= FIXED_CHAR_SEL;
1422  }
1423  else
1424  {
1425  if (paren_depth == 0)
1426  sel *= FIXED_CHAR_SEL;
1427  }
1428  }
1429  /* Could get sel > 1 if multiple wildcards */
1430  if (sel > 1.0)
1431  sel = 1.0;
1432  return sel;
1433 }
static Selectivity regex_selectivity_sub(const char *patt, int pattlen, bool case_insensitive)
double Selectivity
Definition: nodes.h:658
#define FIXED_CHAR_SEL
#define ANY_CHAR_SEL
#define PARTIAL_WILDCARD_SEL
#define CHAR_RANGE_SEL

◆ regexeqjoinsel()

Datum regexeqjoinsel ( PG_FUNCTION_ARGS  )

Definition at line 861 of file like_support.c.

References Pattern_Type_Regex, patternjoinsel(), and PG_RETURN_FLOAT8.

862 {
864 }
static double patternjoinsel(PG_FUNCTION_ARGS, Pattern_Type ptype, bool negate)
Definition: like_support.c:851
#define PG_RETURN_FLOAT8(x)
Definition: fmgr.h:356

◆ regexeqsel()

Datum regexeqsel ( PG_FUNCTION_ARGS  )

Definition at line 769 of file like_support.c.

References Pattern_Type_Regex, patternsel(), and PG_RETURN_FLOAT8.

770 {
772 }
static double patternsel(PG_FUNCTION_ARGS, Pattern_Type ptype, bool negate)
Definition: like_support.c:736
#define PG_RETURN_FLOAT8(x)
Definition: fmgr.h:356

◆ regexnejoinsel()

Datum regexnejoinsel ( PG_FUNCTION_ARGS  )

Definition at line 906 of file like_support.c.

References Pattern_Type_Regex, patternjoinsel(), and PG_RETURN_FLOAT8.

907 {
909 }
static double patternjoinsel(PG_FUNCTION_ARGS, Pattern_Type ptype, bool negate)
Definition: like_support.c:851
#define PG_RETURN_FLOAT8(x)
Definition: fmgr.h:356

◆ regexnesel()

Datum regexnesel ( PG_FUNCTION_ARGS  )

Definition at line 815 of file like_support.c.

References Pattern_Type_Regex, patternsel(), and PG_RETURN_FLOAT8.

816 {
818 }
static double patternsel(PG_FUNCTION_ARGS, Pattern_Type ptype, bool negate)
Definition: like_support.c:736
#define PG_RETURN_FLOAT8(x)
Definition: fmgr.h:356

◆ string_to_bytea_const()

static Const * string_to_bytea_const ( const char *  str,
size_t  str_len 
)
static

Definition at line 1761 of file like_support.c.

References InvalidOid, makeConst(), palloc(), PointerGetDatum, SET_VARSIZE, VARDATA, and VARHDRSZ.

Referenced by like_fixed_prefix(), and make_greater_string().

1762 {
1763  bytea *bstr = palloc(VARHDRSZ + str_len);
1764  Datum conval;
1765 
1766  memcpy(VARDATA(bstr), str, str_len);
1767  SET_VARSIZE(bstr, VARHDRSZ + str_len);
1768  conval = PointerGetDatum(bstr);
1769 
1770  return makeConst(BYTEAOID, -1, InvalidOid, -1, conval, false, false);
1771 }
#define VARDATA(PTR)
Definition: postgres.h:302
#define PointerGetDatum(X)
Definition: postgres.h:556
#define VARHDRSZ
Definition: c.h:562
Const * makeConst(Oid consttype, int32 consttypmod, Oid constcollid, int constlen, Datum constvalue, bool constisnull, bool constbyval)
Definition: makefuncs.c:297
uintptr_t Datum
Definition: postgres.h:367
#define InvalidOid
Definition: postgres_ext.h:36
void * palloc(Size size)
Definition: mcxt.c:949
Definition: c.h:556
#define SET_VARSIZE(PTR, len)
Definition: postgres.h:329

◆ string_to_const()

static Const * string_to_const ( const char *  str,
Oid  datatype 
)
static

Definition at line 1718 of file like_support.c.

References elog, ERROR, InvalidOid, makeConst(), NAMEDATALEN, and string_to_datum().

Referenced by like_fixed_prefix(), make_greater_string(), and regex_fixed_prefix().

1719 {
1720  Datum conval = string_to_datum(str, datatype);
1721  Oid collation;
1722  int constlen;
1723 
1724  /*
1725  * We only need to support a few datatypes here, so hard-wire properties
1726  * instead of incurring the expense of catalog lookups.
1727  */
1728  switch (datatype)
1729  {
1730  case TEXTOID:
1731  case VARCHAROID:
1732  case BPCHAROID:
1733  collation = DEFAULT_COLLATION_OID;
1734  constlen = -1;
1735  break;
1736 
1737  case NAMEOID:
1738  collation = C_COLLATION_OID;
1739  constlen = NAMEDATALEN;
1740  break;
1741 
1742  case BYTEAOID:
1743  collation = InvalidOid;
1744  constlen = -1;
1745  break;
1746 
1747  default:
1748  elog(ERROR, "unexpected datatype in string_to_const: %u",
1749  datatype);
1750  return NULL;
1751  }
1752 
1753  return makeConst(datatype, -1, collation, constlen,
1754  conval, false, false);
1755 }
unsigned int Oid
Definition: postgres_ext.h:31
Const * makeConst(Oid consttype, int32 consttypmod, Oid constcollid, int constlen, Datum constvalue, bool constisnull, bool constbyval)
Definition: makefuncs.c:297
#define NAMEDATALEN
static Datum string_to_datum(const char *str, Oid datatype)
#define ERROR
Definition: elog.h:43
uintptr_t Datum
Definition: postgres.h:367
#define InvalidOid
Definition: postgres_ext.h:36
#define elog(elevel,...)
Definition: elog.h:228

◆ string_to_datum()

static Datum string_to_datum ( const char *  str,
Oid  datatype 
)
static

Definition at line 1698 of file like_support.c.

References Assert, byteain(), CStringGetDatum, CStringGetTextDatum, DirectFunctionCall1, and namein().

Referenced by string_to_const().

1699 {
1700  Assert(str != NULL);
1701 
1702  /*
1703  * We cheat a little by assuming that CStringGetTextDatum() will do for
1704  * bpchar and varchar constants too...
1705  */
1706  if (datatype == NAMEOID)
1708  else if (datatype == BYTEAOID)
1710  else
1711  return CStringGetTextDatum(str);
1712 }
Datum namein(PG_FUNCTION_ARGS)
Definition: name.c:48
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:615
Datum byteain(PG_FUNCTION_ARGS)
Definition: varlena.c:277
#define CStringGetDatum(X)
Definition: postgres.h:578
#define Assert(condition)
Definition: c.h:739
#define CStringGetTextDatum(s)
Definition: builtins.h:83

◆ texticlike_support()

Datum texticlike_support ( PG_FUNCTION_ARGS  )

Definition at line 122 of file like_support.c.

References like_regex_support(), Pattern_Type_Like_IC, PG_GETARG_POINTER, and PG_RETURN_POINTER.

123 {
124  Node *rawreq = (Node *) PG_GETARG_POINTER(0);
125 
127 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:351
Definition: nodes.h:525
static Node * like_regex_support(Node *rawreq, Pattern_Type ptype)
Definition: like_support.c:147
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:271

◆ texticregexeq_support()

Datum texticregexeq_support ( PG_FUNCTION_ARGS  )

Definition at line 138 of file like_support.c.

References like_regex_support(), Pattern_Type_Regex_IC, PG_GETARG_POINTER, and PG_RETURN_POINTER.

139 {
140  Node *rawreq = (Node *) PG_GETARG_POINTER(0);
141 
143 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:351
Definition: nodes.h:525
static Node * like_regex_support(Node *rawreq, Pattern_Type ptype)
Definition: like_support.c:147
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:271

◆ textlike_support()

Datum textlike_support ( PG_FUNCTION_ARGS  )

Definition at line 114 of file like_support.c.

References like_regex_support(), Pattern_Type_Like, PG_GETARG_POINTER, and PG_RETURN_POINTER.

115 {
116  Node *rawreq = (Node *) PG_GETARG_POINTER(0);
117 
119 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:351
Definition: nodes.h:525
static Node * like_regex_support(Node *rawreq, Pattern_Type ptype)
Definition: like_support.c:147
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:271

◆ textregexeq_support()

Datum textregexeq_support ( PG_FUNCTION_ARGS  )

Definition at line 130 of file like_support.c.

References like_regex_support(), Pattern_Type_Regex, PG_GETARG_POINTER, and PG_RETURN_POINTER.

131 {
132  Node *rawreq = (Node *) PG_GETARG_POINTER(0);
133 
135 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:351
Definition: nodes.h:525
static Node * like_regex_support(Node *rawreq, Pattern_Type ptype)
Definition: like_support.c:147
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:271