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, Oid collation, 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 1292 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 1291 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 1290 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 1293 of file like_support.c.

Referenced by like_selectivity(), and regex_selectivity().

◆ PARTIAL_WILDCARD_SEL

#define PARTIAL_WILDCARD_SEL   2.0

Definition at line 1294 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 1487 of file like_support.c.

Referenced by make_greater_string().

1488 {
1489  if (*ptr >= 255)
1490  return false;
1491  (*ptr)++;
1492  return true;
1493 }

◆ iclikejoinsel()

Datum iclikejoinsel ( PG_FUNCTION_ARGS  )

Definition at line 895 of file like_support.c.

References Pattern_Type_Like_IC, patternjoinsel(), and PG_RETURN_FLOAT8.

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

◆ iclikesel()

Datum iclikesel ( PG_FUNCTION_ARGS  )

Definition at line 804 of file like_support.c.

References Pattern_Type_Like_IC, patternsel(), and PG_RETURN_FLOAT8.

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

◆ icnlikejoinsel()

Datum icnlikejoinsel ( PG_FUNCTION_ARGS  )

Definition at line 931 of file like_support.c.

References Pattern_Type_Like_IC, patternjoinsel(), and PG_RETURN_FLOAT8.

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

◆ icnlikesel()

Datum icnlikesel ( PG_FUNCTION_ARGS  )

Definition at line 840 of file like_support.c.

References Pattern_Type_Like_IC, patternsel(), and PG_RETURN_FLOAT8.

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

◆ icregexeqjoinsel()

Datum icregexeqjoinsel ( PG_FUNCTION_ARGS  )

Definition at line 868 of file like_support.c.

References Pattern_Type_Regex_IC, patternjoinsel(), and PG_RETURN_FLOAT8.

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

◆ icregexeqsel()

Datum icregexeqsel ( PG_FUNCTION_ARGS  )

Definition at line 776 of file like_support.c.

References Pattern_Type_Regex_IC, patternsel(), and PG_RETURN_FLOAT8.

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

◆ icregexnejoinsel()

Datum icregexnejoinsel ( PG_FUNCTION_ARGS  )

Definition at line 913 of file like_support.c.

References Pattern_Type_Regex_IC, patternjoinsel(), and PG_RETURN_FLOAT8.

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

◆ icregexnesel()

Datum icregexnesel ( PG_FUNCTION_ARGS  )

Definition at line 822 of file like_support.c.

References Pattern_Type_Regex_IC, patternsel(), and PG_RETURN_FLOAT8.

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

◆ 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 966 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().

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

◆ like_regex_support()

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

Definition at line 148 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().

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

◆ like_selectivity()

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

Definition at line 1297 of file like_support.c.

References ANY_CHAR_SEL, FIXED_CHAR_SEL, and FULL_WILDCARD_SEL.

Referenced by like_fixed_prefix().

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

◆ likejoinsel()

Datum likejoinsel ( PG_FUNCTION_ARGS  )

Definition at line 877 of file like_support.c.

References Pattern_Type_Like, patternjoinsel(), and PG_RETURN_FLOAT8.

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

◆ likesel()

Datum likesel ( PG_FUNCTION_ARGS  )

Definition at line 785 of file like_support.c.

References Pattern_Type_Like, patternsel(), and PG_RETURN_FLOAT8.

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

◆ make_greater_string()

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

Definition at line 1537 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().

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

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

◆ nlikejoinsel()

Datum nlikejoinsel ( PG_FUNCTION_ARGS  )

Definition at line 922 of file like_support.c.

References Pattern_Type_Like, patternjoinsel(), and PG_RETURN_FLOAT8.

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

◆ nlikesel()

Datum nlikesel ( PG_FUNCTION_ARGS  )

Definition at line 831 of file like_support.c.

References Pattern_Type_Like, patternsel(), and PG_RETURN_FLOAT8.

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

◆ 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 1463 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().

1465 {
1466  if (locale_is_c)
1467  return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z');
1468  else if (is_multibyte && IS_HIGHBIT_SET(c))
1469  return true;
1470  else if (locale && locale->provider == COLLPROVIDER_ICU)
1471  return IS_HIGHBIT_SET(c) ||
1472  (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z');
1473 #ifdef HAVE_LOCALE_T
1474  else if (locale && locale->provider == COLLPROVIDER_LIBC)
1475  return isalpha_l((unsigned char) c, locale->info.lt);
1476 #endif
1477  else
1478  return isalpha((unsigned char) c);
1479 }
#define isalpha_l
Definition: win32_port.h:370
#define IS_HIGHBIT_SET(ch)
Definition: c.h:1097
char * c
union pg_locale_struct::@142 info

◆ 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 1142 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().

1144 {
1145  Pattern_Prefix_Status result;
1146 
1147  switch (ptype)
1148  {
1149  case Pattern_Type_Like:
1150  result = like_fixed_prefix(patt, false, collation,
1151  prefix, rest_selec);
1152  break;
1153  case Pattern_Type_Like_IC:
1154  result = like_fixed_prefix(patt, true, collation,
1155  prefix, rest_selec);
1156  break;
1157  case Pattern_Type_Regex:
1158  result = regex_fixed_prefix(patt, false, collation,
1159  prefix, rest_selec);
1160  break;
1161  case Pattern_Type_Regex_IC:
1162  result = regex_fixed_prefix(patt, true, collation,
1163  prefix, rest_selec);
1164  break;
1165  case Pattern_Type_Prefix:
1166  /* Prefix type work is trivial. */
1167  result = Pattern_Prefix_Partial;
1168  *rest_selec = 1.0; /* all */
1169  *prefix = makeConst(patt->consttype,
1170  patt->consttypmod,
1171  patt->constcollid,
1172  patt->constlen,
1173  datumCopy(patt->constvalue,
1174  patt->constbyval,
1175  patt->constlen),
1176  patt->constisnull,
1177  patt->constbyval);
1178  break;
1179  default:
1180  elog(ERROR, "unrecognized ptype: %d", (int) ptype);
1181  result = Pattern_Prefix_None; /* keep compiler quiet */
1182  break;
1183  }
1184  return result;
1185 }
Datum constvalue
Definition: primnodes.h:214
bool constbyval
Definition: primnodes.h:217
Const * makeConst(Oid consttype, int32 consttypmod, Oid constcollid, int constlen, Datum constvalue, bool constisnull, bool constbyval)
Definition: makefuncs.c:299
int constlen
Definition: primnodes.h:213
Oid consttype
Definition: primnodes.h:210
#define ERROR
Definition: elog.h:43
Oid constcollid
Definition: primnodes.h:212
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:966
Datum datumCopy(Datum value, bool typByVal, int typLen)
Definition: datum.c:131
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:211
#define elog(elevel,...)
Definition: elog.h:214
bool constisnull
Definition: primnodes.h:215

◆ patternjoinsel()

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

Definition at line 849 of file like_support.c.

References DEFAULT_MATCH_SEL.

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

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

◆ patternsel()

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

Definition at line 734 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().

735 {
737  Oid operator = PG_GETARG_OID(1);
738  List *args = (List *) PG_GETARG_POINTER(2);
739  int varRelid = PG_GETARG_INT32(3);
740  Oid collation = PG_GET_COLLATION();
741 
742  /*
743  * If this is for a NOT LIKE or similar operator, get the corresponding
744  * positive-match operator and work with that.
745  */
746  if (negate)
747  {
748  operator = get_negator(operator);
749  if (!OidIsValid(operator))
750  elog(ERROR, "patternsel called for operator without a negator");
751  }
752 
753  return patternsel_common(root,
754  operator,
755  InvalidOid,
756  args,
757  varRelid,
758  collation,
759  ptype,
760  negate);
761 }
#define PG_GETARG_INT32(n)
Definition: fmgr.h:269
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:276
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:651
#define PG_GET_COLLATION()
Definition: fmgr.h:198
#define ERROR
Definition: elog.h:43
#define PG_GETARG_OID(n)
Definition: fmgr.h:275
#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:460
#define elog(elevel,...)
Definition: elog.h:214
Oid get_negator(Oid opno)
Definition: lsyscache.c:1445
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 460 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().

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

◆ prefix_selectivity()

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

Definition at line 1206 of file like_support.c.

References Assert, Const::consttype, Const::constvalue, DEFAULT_MATCH_SEL, fmgr_info(), get_opcode(), ineq_histogram_selectivity(), make_greater_string(), Max, prefixsel(), and var_eq_const().

Referenced by patternsel_common().

1210 {
1212  FmgrInfo opproc;
1213  Const *greaterstrcon;
1214  Selectivity eq_sel;
1215 
1216  /* Estimate the selectivity of "x >= prefix" */
1217  fmgr_info(get_opcode(geopr), &opproc);
1218 
1219  prefixsel = ineq_histogram_selectivity(root, vardata,
1220  geopr, &opproc, true, true,
1221  collation,
1222  prefixcon->constvalue,
1223  prefixcon->consttype);
1224 
1225  if (prefixsel < 0.0)
1226  {
1227  /* No histogram is present ... return a suitable default estimate */
1228  return DEFAULT_MATCH_SEL;
1229  }
1230 
1231  /*
1232  * If we can create a string larger than the prefix, say "x < greaterstr".
1233  */
1234  fmgr_info(get_opcode(ltopr), &opproc);
1235  greaterstrcon = make_greater_string(prefixcon, &opproc, collation);
1236  if (greaterstrcon)
1237  {
1238  Selectivity topsel;
1239 
1240  topsel = ineq_histogram_selectivity(root, vardata,
1241  ltopr, &opproc, false, false,
1242  collation,
1243  greaterstrcon->constvalue,
1244  greaterstrcon->consttype);
1245 
1246  /* ineq_histogram_selectivity worked before, it shouldn't fail now */
1247  Assert(topsel >= 0.0);
1248 
1249  /*
1250  * Merge the two selectivities in the same way as for a range query
1251  * (see clauselist_selectivity()). Note that we don't need to worry
1252  * about double-exclusion of nulls, since ineq_histogram_selectivity
1253  * doesn't count those anyway.
1254  */
1255  prefixsel = topsel + prefixsel - 1.0;
1256  }
1257 
1258  /*
1259  * If the prefix is long then the two bounding values might be too close
1260  * together for the histogram to distinguish them usefully, resulting in a
1261  * zero estimate (plus or minus roundoff error). To avoid returning a
1262  * ridiculously small estimate, compute the estimated selectivity for
1263  * "variable = 'foo'", and clamp to that. (Obviously, the resultant
1264  * estimate should be at least that.)
1265  *
1266  * We apply this even if we couldn't make a greater string. That case
1267  * suggests that the prefix is near the maximum possible, and thus
1268  * probably off the end of the histogram, and thus we probably got a very
1269  * small estimate from the >= condition; so we still need to clamp.
1270  */
1271  eq_sel = var_eq_const(vardata, eqopr, collation, prefixcon->constvalue,
1272  false, true, false);
1273 
1274  prefixsel = Max(prefixsel, eq_sel);
1275 
1276  return prefixsel;
1277 }
Datum constvalue
Definition: primnodes.h:214
Definition: fmgr.h:56
double Selectivity
Definition: nodes.h:662
Oid consttype
Definition: primnodes.h:210
void fmgr_info(Oid functionId, FmgrInfo *finfo)
Definition: fmgr.c:126
#define DEFAULT_MATCH_SEL
Definition: selfuncs.h:43
static Const * make_greater_string(const Const *str_const, FmgrInfo *ltproc, Oid collation)
RegProcedure get_opcode(Oid opno)
Definition: lsyscache.c:1202
#define Max(x, y)
Definition: c.h:921
#define Assert(condition)
Definition: c.h:745
double var_eq_const(VariableStatData *vardata, Oid operator, Oid collation, Datum constval, bool constisnull, bool varonleft, bool negate)
Definition: selfuncs.c:292
double ineq_histogram_selectivity(PlannerInfo *root, VariableStatData *vardata, Oid opoid, FmgrInfo *opproc, bool isgt, bool iseq, Oid collation, Datum constval, Oid consttype)
Definition: selfuncs.c:1038
Datum prefixsel(PG_FUNCTION_ARGS)
Definition: like_support.c:794

◆ prefixjoinsel()

Datum prefixjoinsel ( PG_FUNCTION_ARGS  )

Definition at line 886 of file like_support.c.

References Pattern_Type_Prefix, patternjoinsel(), and PG_RETURN_FLOAT8.

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

◆ prefixsel()

Datum prefixsel ( PG_FUNCTION_ARGS  )

Definition at line 794 of file like_support.c.

References Pattern_Type_Prefix, patternsel(), and PG_RETURN_FLOAT8.

Referenced by patternsel_common(), and prefix_selectivity().

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

◆ 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 1074 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().

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

◆ regex_selectivity()

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

Definition at line 1426 of file like_support.c.

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

Referenced by regex_fixed_prefix().

1428 {
1429  Selectivity sel;
1430 
1431  /* If patt doesn't end with $, consider it to have a trailing wildcard */
1432  if (pattlen > 0 && patt[pattlen - 1] == '$' &&
1433  (pattlen == 1 || patt[pattlen - 2] != '\\'))
1434  {
1435  /* has trailing $ */
1436  sel = regex_selectivity_sub(patt, pattlen - 1, case_insensitive);
1437  }
1438  else
1439  {
1440  /* no trailing $ */
1441  sel = regex_selectivity_sub(patt, pattlen, case_insensitive);
1442  sel *= FULL_WILDCARD_SEL;
1443  }
1444 
1445  /* If there's a fixed prefix, discount its selectivity */
1446  if (fixed_prefix_len > 0)
1447  sel /= pow(FIXED_CHAR_SEL, fixed_prefix_len);
1448 
1449  /* Make sure result stays in range */
1450  CLAMP_PROBABILITY(sel);
1451  return sel;
1452 }
static Selectivity regex_selectivity_sub(const char *patt, int pattlen, bool case_insensitive)
#define FULL_WILDCARD_SEL
double Selectivity
Definition: nodes.h:662
#define CLAMP_PROBABILITY(p)
Definition: selfuncs.h:60
#define FIXED_CHAR_SEL

◆ regex_selectivity_sub()

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

Definition at line 1334 of file like_support.c.

References ANY_CHAR_SEL, CHAR_RANGE_SEL, FIXED_CHAR_SEL, and PARTIAL_WILDCARD_SEL.

Referenced by regex_selectivity().

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

References Pattern_Type_Regex, patternjoinsel(), and PG_RETURN_FLOAT8.

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

◆ regexeqsel()

Datum regexeqsel ( PG_FUNCTION_ARGS  )

Definition at line 767 of file like_support.c.

References Pattern_Type_Regex, patternsel(), and PG_RETURN_FLOAT8.

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

◆ regexnejoinsel()

Datum regexnejoinsel ( PG_FUNCTION_ARGS  )

Definition at line 904 of file like_support.c.

References Pattern_Type_Regex, patternjoinsel(), and PG_RETURN_FLOAT8.

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

◆ regexnesel()

Datum regexnesel ( PG_FUNCTION_ARGS  )

Definition at line 813 of file like_support.c.

References Pattern_Type_Regex, patternsel(), and PG_RETURN_FLOAT8.

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

◆ string_to_bytea_const()

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

Definition at line 1751 of file like_support.c.

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

Referenced by like_fixed_prefix(), and make_greater_string().

1752 {
1753  bytea *bstr = palloc(VARHDRSZ + str_len);
1754  Datum conval;
1755 
1756  memcpy(VARDATA(bstr), str, str_len);
1757  SET_VARSIZE(bstr, VARHDRSZ + str_len);
1758  conval = PointerGetDatum(bstr);
1759 
1760  return makeConst(BYTEAOID, -1, InvalidOid, -1, conval, false, false);
1761 }
#define VARDATA(PTR)
Definition: postgres.h:302
#define PointerGetDatum(X)
Definition: postgres.h:556
#define VARHDRSZ
Definition: c.h:568
Const * makeConst(Oid consttype, int32 consttypmod, Oid constcollid, int constlen, Datum constvalue, bool constisnull, bool constbyval)
Definition: makefuncs.c:299
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:562
#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 1708 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().

1709 {
1710  Datum conval = string_to_datum(str, datatype);
1711  Oid collation;
1712  int constlen;
1713 
1714  /*
1715  * We only need to support a few datatypes here, so hard-wire properties
1716  * instead of incurring the expense of catalog lookups.
1717  */
1718  switch (datatype)
1719  {
1720  case TEXTOID:
1721  case VARCHAROID:
1722  case BPCHAROID:
1723  collation = DEFAULT_COLLATION_OID;
1724  constlen = -1;
1725  break;
1726 
1727  case NAMEOID:
1728  collation = C_COLLATION_OID;
1729  constlen = NAMEDATALEN;
1730  break;
1731 
1732  case BYTEAOID:
1733  collation = InvalidOid;
1734  constlen = -1;
1735  break;
1736 
1737  default:
1738  elog(ERROR, "unexpected datatype in string_to_const: %u",
1739  datatype);
1740  return NULL;
1741  }
1742 
1743  return makeConst(datatype, -1, collation, constlen,
1744  conval, false, false);
1745 }
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:299
#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:214

◆ string_to_datum()

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

Definition at line 1688 of file like_support.c.

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

Referenced by string_to_const().

1689 {
1690  Assert(str != NULL);
1691 
1692  /*
1693  * We cheat a little by assuming that CStringGetTextDatum() will do for
1694  * bpchar and varchar constants too...
1695  */
1696  if (datatype == NAMEOID)
1698  else if (datatype == BYTEAOID)
1700  else
1701  return CStringGetTextDatum(str);
1702 }
Datum namein(PG_FUNCTION_ARGS)
Definition: name.c:48
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:624
Datum byteain(PG_FUNCTION_ARGS)
Definition: varlena.c:278
#define CStringGetDatum(X)
Definition: postgres.h:578
#define Assert(condition)
Definition: c.h:745
#define CStringGetTextDatum(s)
Definition: builtins.h:86

◆ texticlike_support()

Datum texticlike_support ( PG_FUNCTION_ARGS  )

Definition at line 123 of file like_support.c.

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

124 {
125  Node *rawreq = (Node *) PG_GETARG_POINTER(0);
126 
128 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:360
Definition: nodes.h:529
static Node * like_regex_support(Node *rawreq, Pattern_Type ptype)
Definition: like_support.c:148
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:276

◆ texticregexeq_support()

Datum texticregexeq_support ( PG_FUNCTION_ARGS  )

Definition at line 139 of file like_support.c.

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

140 {
141  Node *rawreq = (Node *) PG_GETARG_POINTER(0);
142 
144 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:360
Definition: nodes.h:529
static Node * like_regex_support(Node *rawreq, Pattern_Type ptype)
Definition: like_support.c:148
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:276

◆ textlike_support()

Datum textlike_support ( PG_FUNCTION_ARGS  )

Definition at line 115 of file like_support.c.

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

116 {
117  Node *rawreq = (Node *) PG_GETARG_POINTER(0);
118 
120 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:360
Definition: nodes.h:529
static Node * like_regex_support(Node *rawreq, Pattern_Type ptype)
Definition: like_support.c:148
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:276

◆ textregexeq_support()

Datum textregexeq_support ( PG_FUNCTION_ARGS  )

Definition at line 131 of file like_support.c.

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

132 {
133  Node *rawreq = (Node *) PG_GETARG_POINTER(0);
134 
136 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:360
Definition: nodes.h:529
static Node * like_regex_support(Node *rawreq, Pattern_Type ptype)
Definition: like_support.c:148
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:276