mirror of
https://github.com/postgres/postgres.git
synced 2025-05-03 22:24:49 +03:00
Clean up loose end in LIKE optimization fix: parser's code would generate
<= and >= indexquals from a LIKE even if the index in question didn't support those operators. (As, for example, a hash index does not.)
This commit is contained in:
parent
2784a5aedf
commit
5f68d5c38f
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/indxpath.c,v 1.73 1999/11/22 17:56:07 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/indxpath.c,v 1.74 1999/12/31 03:41:03 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -44,21 +44,27 @@ typedef enum {
|
|||||||
Prefix_None, Prefix_Partial, Prefix_Exact
|
Prefix_None, Prefix_Partial, Prefix_Exact
|
||||||
} Prefix_Status;
|
} Prefix_Status;
|
||||||
|
|
||||||
static void match_index_orclauses(RelOptInfo *rel, RelOptInfo *index, int indexkey,
|
static void match_index_orclauses(RelOptInfo *rel, RelOptInfo *index,
|
||||||
int xclass, List *restrictinfo_list);
|
int indexkey, Oid opclass,
|
||||||
static List *match_index_orclause(RelOptInfo *rel, RelOptInfo *index, int indexkey,
|
List *restrictinfo_list);
|
||||||
int xclass, List *or_clauses, List *other_matching_indices);
|
static List *match_index_orclause(RelOptInfo *rel, RelOptInfo *index,
|
||||||
|
int indexkey, Oid opclass,
|
||||||
|
List *or_clauses,
|
||||||
|
List *other_matching_indices);
|
||||||
static bool match_or_subclause_to_indexkey(RelOptInfo *rel, RelOptInfo *index,
|
static bool match_or_subclause_to_indexkey(RelOptInfo *rel, RelOptInfo *index,
|
||||||
int indexkey, int xclass,
|
int indexkey, Oid opclass,
|
||||||
Expr *clause);
|
Expr *clause);
|
||||||
static List *group_clauses_by_indexkey(RelOptInfo *rel, RelOptInfo *index,
|
static List *group_clauses_by_indexkey(RelOptInfo *rel, RelOptInfo *index,
|
||||||
int *indexkeys, Oid *classes, List *restrictinfo_list);
|
int *indexkeys, Oid *classes,
|
||||||
|
List *restrictinfo_list);
|
||||||
static List *group_clauses_by_ikey_for_joins(RelOptInfo *rel, RelOptInfo *index,
|
static List *group_clauses_by_ikey_for_joins(RelOptInfo *rel, RelOptInfo *index,
|
||||||
int *indexkeys, Oid *classes, List *join_cinfo_list, List *restr_cinfo_list);
|
int *indexkeys, Oid *classes,
|
||||||
|
List *join_cinfo_list,
|
||||||
|
List *restr_cinfo_list);
|
||||||
static bool match_clause_to_indexkey(RelOptInfo *rel, RelOptInfo *index,
|
static bool match_clause_to_indexkey(RelOptInfo *rel, RelOptInfo *index,
|
||||||
int indexkey, int xclass,
|
int indexkey, Oid opclass,
|
||||||
Expr *clause, bool join);
|
Expr *clause, bool join);
|
||||||
static bool indexable_operator(Expr *clause, int xclass, Oid relam,
|
static bool indexable_operator(Expr *clause, Oid opclass, Oid relam,
|
||||||
bool indexkey_on_left);
|
bool indexkey_on_left);
|
||||||
static bool pred_test(List *predicate_list, List *restrictinfo_list,
|
static bool pred_test(List *predicate_list, List *restrictinfo_list,
|
||||||
List *joininfo_list);
|
List *joininfo_list);
|
||||||
@ -77,13 +83,16 @@ static bool useful_for_ordering(Query *root, RelOptInfo *rel,
|
|||||||
RelOptInfo *index);
|
RelOptInfo *index);
|
||||||
static bool match_index_to_operand(int indexkey, Var *operand,
|
static bool match_index_to_operand(int indexkey, Var *operand,
|
||||||
RelOptInfo *rel, RelOptInfo *index);
|
RelOptInfo *rel, RelOptInfo *index);
|
||||||
static bool function_index_operand(Expr *funcOpnd, RelOptInfo *rel, RelOptInfo *index);
|
static bool function_index_operand(Expr *funcOpnd, RelOptInfo *rel,
|
||||||
static bool match_special_index_operator(Expr *clause, bool indexkey_on_left);
|
RelOptInfo *index);
|
||||||
|
static bool match_special_index_operator(Expr *clause, Oid opclass, Oid relam,
|
||||||
|
bool indexkey_on_left);
|
||||||
static Prefix_Status like_fixed_prefix(char *patt, char **prefix);
|
static Prefix_Status like_fixed_prefix(char *patt, char **prefix);
|
||||||
static Prefix_Status regex_fixed_prefix(char *patt, bool case_insensitive,
|
static Prefix_Status regex_fixed_prefix(char *patt, bool case_insensitive,
|
||||||
char **prefix);
|
char **prefix);
|
||||||
static List *prefix_quals(Var *leftop, Oid expr_op,
|
static List *prefix_quals(Var *leftop, Oid expr_op,
|
||||||
char *prefix, Prefix_Status pstatus);
|
char *prefix, Prefix_Status pstatus);
|
||||||
|
static Oid find_operator(const char * opname, Oid datatype);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -255,7 +264,7 @@ static void
|
|||||||
match_index_orclauses(RelOptInfo *rel,
|
match_index_orclauses(RelOptInfo *rel,
|
||||||
RelOptInfo *index,
|
RelOptInfo *index,
|
||||||
int indexkey,
|
int indexkey,
|
||||||
int xclass,
|
Oid opclass,
|
||||||
List *restrictinfo_list)
|
List *restrictinfo_list)
|
||||||
{
|
{
|
||||||
List *i;
|
List *i;
|
||||||
@ -272,7 +281,7 @@ match_index_orclauses(RelOptInfo *rel,
|
|||||||
*/
|
*/
|
||||||
restrictinfo->subclauseindices =
|
restrictinfo->subclauseindices =
|
||||||
match_index_orclause(rel, index,
|
match_index_orclause(rel, index,
|
||||||
indexkey, xclass,
|
indexkey, opclass,
|
||||||
restrictinfo->clause->args,
|
restrictinfo->clause->args,
|
||||||
restrictinfo->subclauseindices);
|
restrictinfo->subclauseindices);
|
||||||
}
|
}
|
||||||
@ -304,7 +313,7 @@ static List *
|
|||||||
match_index_orclause(RelOptInfo *rel,
|
match_index_orclause(RelOptInfo *rel,
|
||||||
RelOptInfo *index,
|
RelOptInfo *index,
|
||||||
int indexkey,
|
int indexkey,
|
||||||
int xclass,
|
Oid opclass,
|
||||||
List *or_clauses,
|
List *or_clauses,
|
||||||
List *other_matching_indices)
|
List *other_matching_indices)
|
||||||
{
|
{
|
||||||
@ -330,7 +339,7 @@ match_index_orclause(RelOptInfo *rel,
|
|||||||
{
|
{
|
||||||
Expr *clause = lfirst(clist);
|
Expr *clause = lfirst(clist);
|
||||||
|
|
||||||
if (match_or_subclause_to_indexkey(rel, index, indexkey, xclass,
|
if (match_or_subclause_to_indexkey(rel, index, indexkey, opclass,
|
||||||
clause))
|
clause))
|
||||||
{
|
{
|
||||||
/* OK to add this index to sublist for this subclause */
|
/* OK to add this index to sublist for this subclause */
|
||||||
@ -355,7 +364,7 @@ static bool
|
|||||||
match_or_subclause_to_indexkey(RelOptInfo *rel,
|
match_or_subclause_to_indexkey(RelOptInfo *rel,
|
||||||
RelOptInfo *index,
|
RelOptInfo *index,
|
||||||
int indexkey,
|
int indexkey,
|
||||||
int xclass,
|
Oid opclass,
|
||||||
Expr *clause)
|
Expr *clause)
|
||||||
{
|
{
|
||||||
if (and_clause((Node *) clause))
|
if (and_clause((Node *) clause))
|
||||||
@ -364,14 +373,14 @@ match_or_subclause_to_indexkey(RelOptInfo *rel,
|
|||||||
|
|
||||||
foreach(item, clause->args)
|
foreach(item, clause->args)
|
||||||
{
|
{
|
||||||
if (! match_clause_to_indexkey(rel, index, indexkey, xclass,
|
if (! match_clause_to_indexkey(rel, index, indexkey, opclass,
|
||||||
lfirst(item), false))
|
lfirst(item), false))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return match_clause_to_indexkey(rel, index, indexkey, xclass,
|
return match_clause_to_indexkey(rel, index, indexkey, opclass,
|
||||||
clause, false);
|
clause, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -588,7 +597,7 @@ group_clauses_by_ikey_for_joins(RelOptInfo *rel,
|
|||||||
* 'rel' is the relation of interest.
|
* 'rel' is the relation of interest.
|
||||||
* 'index' is an index on 'rel'.
|
* 'index' is an index on 'rel'.
|
||||||
* 'indexkey' is a key of 'index'.
|
* 'indexkey' is a key of 'index'.
|
||||||
* 'xclass' is the corresponding operator class.
|
* 'opclass' is the corresponding operator class.
|
||||||
* 'clause' is the clause to be tested.
|
* 'clause' is the clause to be tested.
|
||||||
* 'join' is true if we are considering this clause for joins.
|
* 'join' is true if we are considering this clause for joins.
|
||||||
*
|
*
|
||||||
@ -601,7 +610,7 @@ static bool
|
|||||||
match_clause_to_indexkey(RelOptInfo *rel,
|
match_clause_to_indexkey(RelOptInfo *rel,
|
||||||
RelOptInfo *index,
|
RelOptInfo *index,
|
||||||
int indexkey,
|
int indexkey,
|
||||||
int xclass,
|
Oid opclass,
|
||||||
Expr *clause,
|
Expr *clause,
|
||||||
bool join)
|
bool join)
|
||||||
{
|
{
|
||||||
@ -627,26 +636,28 @@ match_clause_to_indexkey(RelOptInfo *rel,
|
|||||||
if ((IsA(rightop, Const) || IsA(rightop, Param)) &&
|
if ((IsA(rightop, Const) || IsA(rightop, Param)) &&
|
||||||
match_index_to_operand(indexkey, leftop, rel, index))
|
match_index_to_operand(indexkey, leftop, rel, index))
|
||||||
{
|
{
|
||||||
if (indexable_operator(clause, xclass, index->relam, true))
|
if (indexable_operator(clause, opclass, index->relam, true))
|
||||||
return true;
|
return true;
|
||||||
/*
|
/*
|
||||||
* If we didn't find a member of the index's opclass,
|
* If we didn't find a member of the index's opclass,
|
||||||
* see whether it is a "special" indexable operator.
|
* see whether it is a "special" indexable operator.
|
||||||
*/
|
*/
|
||||||
if (match_special_index_operator(clause, true))
|
if (match_special_index_operator(clause, opclass, index->relam,
|
||||||
|
true))
|
||||||
return true;
|
return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if ((IsA(leftop, Const) || IsA(leftop, Param)) &&
|
if ((IsA(leftop, Const) || IsA(leftop, Param)) &&
|
||||||
match_index_to_operand(indexkey, rightop, rel, index))
|
match_index_to_operand(indexkey, rightop, rel, index))
|
||||||
{
|
{
|
||||||
if (indexable_operator(clause, xclass, index->relam, false))
|
if (indexable_operator(clause, opclass, index->relam, false))
|
||||||
return true;
|
return true;
|
||||||
/*
|
/*
|
||||||
* If we didn't find a member of the index's opclass,
|
* If we didn't find a member of the index's opclass,
|
||||||
* see whether it is a "special" indexable operator.
|
* see whether it is a "special" indexable operator.
|
||||||
*/
|
*/
|
||||||
if (match_special_index_operator(clause, false))
|
if (match_special_index_operator(clause, opclass, index->relam,
|
||||||
|
false))
|
||||||
return true;
|
return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -666,7 +677,7 @@ match_clause_to_indexkey(RelOptInfo *rel,
|
|||||||
isIndexable = ! intMember(lfirsti(rel->relids), othervarnos);
|
isIndexable = ! intMember(lfirsti(rel->relids), othervarnos);
|
||||||
freeList(othervarnos);
|
freeList(othervarnos);
|
||||||
if (isIndexable &&
|
if (isIndexable &&
|
||||||
indexable_operator(clause, xclass, index->relam, true))
|
indexable_operator(clause, opclass, index->relam, true))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if (match_index_to_operand(indexkey, rightop, rel, index))
|
else if (match_index_to_operand(indexkey, rightop, rel, index))
|
||||||
@ -677,7 +688,7 @@ match_clause_to_indexkey(RelOptInfo *rel,
|
|||||||
isIndexable = ! intMember(lfirsti(rel->relids), othervarnos);
|
isIndexable = ! intMember(lfirsti(rel->relids), othervarnos);
|
||||||
freeList(othervarnos);
|
freeList(othervarnos);
|
||||||
if (isIndexable &&
|
if (isIndexable &&
|
||||||
indexable_operator(clause, xclass, index->relam, false))
|
indexable_operator(clause, opclass, index->relam, false))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -706,7 +717,7 @@ match_clause_to_indexkey(RelOptInfo *rel,
|
|||||||
* a tad ugly...
|
* a tad ugly...
|
||||||
*/
|
*/
|
||||||
static bool
|
static bool
|
||||||
indexable_operator(Expr *clause, int xclass, Oid relam,
|
indexable_operator(Expr *clause, Oid opclass, Oid relam,
|
||||||
bool indexkey_on_left)
|
bool indexkey_on_left)
|
||||||
{
|
{
|
||||||
Oid expr_op = ((Oper *) clause->oper)->opno;
|
Oid expr_op = ((Oper *) clause->oper)->opno;
|
||||||
@ -723,7 +734,7 @@ indexable_operator(Expr *clause, int xclass, Oid relam,
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
/* Done if the (commuted) operator is a member of the index's AM */
|
/* Done if the (commuted) operator is a member of the index's AM */
|
||||||
if (op_class(commuted_op, xclass, relam))
|
if (op_class(commuted_op, opclass, relam))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -766,7 +777,7 @@ indexable_operator(Expr *clause, int xclass, Oid relam,
|
|||||||
if (commuted_op == InvalidOid)
|
if (commuted_op == InvalidOid)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (op_class(commuted_op, xclass, relam))
|
if (op_class(commuted_op, opclass, relam))
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* Success! Change the opclause to use the
|
* Success! Change the opclause to use the
|
||||||
@ -1561,7 +1572,8 @@ function_index_operand(Expr *funcOpnd, RelOptInfo *rel, RelOptInfo *index)
|
|||||||
* Return 'true' if we can do something with it anyway.
|
* Return 'true' if we can do something with it anyway.
|
||||||
*/
|
*/
|
||||||
static bool
|
static bool
|
||||||
match_special_index_operator(Expr *clause, bool indexkey_on_left)
|
match_special_index_operator(Expr *clause, Oid opclass, Oid relam,
|
||||||
|
bool indexkey_on_left)
|
||||||
{
|
{
|
||||||
bool isIndexable = false;
|
bool isIndexable = false;
|
||||||
Var *leftop,
|
Var *leftop,
|
||||||
@ -1625,6 +1637,51 @@ match_special_index_operator(Expr *clause, bool indexkey_on_left)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* done if the expression doesn't look indexable */
|
||||||
|
if (! isIndexable)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Must also check that index's opclass supports the operators we will
|
||||||
|
* want to apply. (A hash index, for example, will not support ">=".)
|
||||||
|
* We cheat a little by not checking for availability of "=" ... any
|
||||||
|
* index type should support "=", methinks.
|
||||||
|
*/
|
||||||
|
switch (expr_op)
|
||||||
|
{
|
||||||
|
case OID_TEXT_LIKE_OP:
|
||||||
|
case OID_TEXT_REGEXEQ_OP:
|
||||||
|
case OID_TEXT_ICREGEXEQ_OP:
|
||||||
|
if (! op_class(find_operator(">=", TEXTOID), opclass, relam) ||
|
||||||
|
! op_class(find_operator("<=", TEXTOID), opclass, relam))
|
||||||
|
isIndexable = false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case OID_BPCHAR_LIKE_OP:
|
||||||
|
case OID_BPCHAR_REGEXEQ_OP:
|
||||||
|
case OID_BPCHAR_ICREGEXEQ_OP:
|
||||||
|
if (! op_class(find_operator(">=", BPCHAROID), opclass, relam) ||
|
||||||
|
! op_class(find_operator("<=", BPCHAROID), opclass, relam))
|
||||||
|
isIndexable = false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case OID_VARCHAR_LIKE_OP:
|
||||||
|
case OID_VARCHAR_REGEXEQ_OP:
|
||||||
|
case OID_VARCHAR_ICREGEXEQ_OP:
|
||||||
|
if (! op_class(find_operator(">=", VARCHAROID), opclass, relam) ||
|
||||||
|
! op_class(find_operator("<=", VARCHAROID), opclass, relam))
|
||||||
|
isIndexable = false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case OID_NAME_LIKE_OP:
|
||||||
|
case OID_NAME_REGEXEQ_OP:
|
||||||
|
case OID_NAME_ICREGEXEQ_OP:
|
||||||
|
if (! op_class(find_operator(">=", NAMEOID), opclass, relam) ||
|
||||||
|
! op_class(find_operator("<=", NAMEOID), opclass, relam))
|
||||||
|
isIndexable = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
return isIndexable;
|
return isIndexable;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1848,7 +1905,7 @@ prefix_quals(Var *leftop, Oid expr_op,
|
|||||||
{
|
{
|
||||||
List *result;
|
List *result;
|
||||||
Oid datatype;
|
Oid datatype;
|
||||||
HeapTuple optup;
|
Oid oproid;
|
||||||
void *conval;
|
void *conval;
|
||||||
Const *con;
|
Const *con;
|
||||||
Oper *op;
|
Oper *op;
|
||||||
@ -1893,12 +1950,8 @@ prefix_quals(Var *leftop, Oid expr_op,
|
|||||||
*/
|
*/
|
||||||
if (pstatus == Prefix_Exact)
|
if (pstatus == Prefix_Exact)
|
||||||
{
|
{
|
||||||
optup = SearchSysCacheTuple(OPERNAME,
|
oproid = find_operator("=", datatype);
|
||||||
PointerGetDatum("="),
|
if (oproid == InvalidOid)
|
||||||
ObjectIdGetDatum(datatype),
|
|
||||||
ObjectIdGetDatum(datatype),
|
|
||||||
CharGetDatum('b'));
|
|
||||||
if (!HeapTupleIsValid(optup))
|
|
||||||
elog(ERROR, "prefix_quals: no = operator for type %u", datatype);
|
elog(ERROR, "prefix_quals: no = operator for type %u", datatype);
|
||||||
/* Note: we cheat a little by assuming that textin() will do for
|
/* Note: we cheat a little by assuming that textin() will do for
|
||||||
* bpchar and varchar constants too...
|
* bpchar and varchar constants too...
|
||||||
@ -1908,7 +1961,7 @@ prefix_quals(Var *leftop, Oid expr_op,
|
|||||||
con = makeConst(datatype, ((datatype == NAMEOID) ? NAMEDATALEN : -1),
|
con = makeConst(datatype, ((datatype == NAMEOID) ? NAMEDATALEN : -1),
|
||||||
PointerGetDatum(conval),
|
PointerGetDatum(conval),
|
||||||
false, false, false, false);
|
false, false, false, false);
|
||||||
op = makeOper(optup->t_data->t_oid, InvalidOid, BOOLOID, 0, NULL);
|
op = makeOper(oproid, InvalidOid, BOOLOID, 0, NULL);
|
||||||
expr = make_opclause(op, leftop, (Var *) con);
|
expr = make_opclause(op, leftop, (Var *) con);
|
||||||
result = lcons(expr, NIL);
|
result = lcons(expr, NIL);
|
||||||
return result;
|
return result;
|
||||||
@ -1919,19 +1972,15 @@ prefix_quals(Var *leftop, Oid expr_op,
|
|||||||
*
|
*
|
||||||
* We can always say "x >= prefix".
|
* We can always say "x >= prefix".
|
||||||
*/
|
*/
|
||||||
optup = SearchSysCacheTuple(OPERNAME,
|
oproid = find_operator(">=", datatype);
|
||||||
PointerGetDatum(">="),
|
if (oproid == InvalidOid)
|
||||||
ObjectIdGetDatum(datatype),
|
|
||||||
ObjectIdGetDatum(datatype),
|
|
||||||
CharGetDatum('b'));
|
|
||||||
if (!HeapTupleIsValid(optup))
|
|
||||||
elog(ERROR, "prefix_quals: no >= operator for type %u", datatype);
|
elog(ERROR, "prefix_quals: no >= operator for type %u", datatype);
|
||||||
conval = (datatype == NAMEOID) ?
|
conval = (datatype == NAMEOID) ?
|
||||||
(void*) namein(prefix) : (void*) textin(prefix);
|
(void*) namein(prefix) : (void*) textin(prefix);
|
||||||
con = makeConst(datatype, ((datatype == NAMEOID) ? NAMEDATALEN : -1),
|
con = makeConst(datatype, ((datatype == NAMEOID) ? NAMEDATALEN : -1),
|
||||||
PointerGetDatum(conval),
|
PointerGetDatum(conval),
|
||||||
false, false, false, false);
|
false, false, false, false);
|
||||||
op = makeOper(optup->t_data->t_oid, InvalidOid, BOOLOID, 0, NULL);
|
op = makeOper(oproid, InvalidOid, BOOLOID, 0, NULL);
|
||||||
expr = make_opclause(op, leftop, (Var *) con);
|
expr = make_opclause(op, leftop, (Var *) con);
|
||||||
result = lcons(expr, NIL);
|
result = lcons(expr, NIL);
|
||||||
|
|
||||||
@ -1947,22 +1996,34 @@ prefix_quals(Var *leftop, Oid expr_op,
|
|||||||
prefix[prefixlen] = '\377';
|
prefix[prefixlen] = '\377';
|
||||||
prefix[prefixlen+1] = '\0';
|
prefix[prefixlen+1] = '\0';
|
||||||
|
|
||||||
optup = SearchSysCacheTuple(OPERNAME,
|
oproid = find_operator("<=", datatype);
|
||||||
PointerGetDatum("<="),
|
if (oproid == InvalidOid)
|
||||||
ObjectIdGetDatum(datatype),
|
|
||||||
ObjectIdGetDatum(datatype),
|
|
||||||
CharGetDatum('b'));
|
|
||||||
if (!HeapTupleIsValid(optup))
|
|
||||||
elog(ERROR, "prefix_quals: no <= operator for type %u", datatype);
|
elog(ERROR, "prefix_quals: no <= operator for type %u", datatype);
|
||||||
conval = (datatype == NAMEOID) ?
|
conval = (datatype == NAMEOID) ?
|
||||||
(void*) namein(prefix) : (void*) textin(prefix);
|
(void*) namein(prefix) : (void*) textin(prefix);
|
||||||
con = makeConst(datatype, ((datatype == NAMEOID) ? NAMEDATALEN : -1),
|
con = makeConst(datatype, ((datatype == NAMEOID) ? NAMEDATALEN : -1),
|
||||||
PointerGetDatum(conval),
|
PointerGetDatum(conval),
|
||||||
false, false, false, false);
|
false, false, false, false);
|
||||||
op = makeOper(optup->t_data->t_oid, InvalidOid, BOOLOID, 0, NULL);
|
op = makeOper(oproid, InvalidOid, BOOLOID, 0, NULL);
|
||||||
expr = make_opclause(op, leftop, (Var *) con);
|
expr = make_opclause(op, leftop, (Var *) con);
|
||||||
result = lappend(result, expr);
|
result = lappend(result, expr);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* See if there is a binary op of the given name for the given datatype */
|
||||||
|
static Oid
|
||||||
|
find_operator(const char * opname, Oid datatype)
|
||||||
|
{
|
||||||
|
HeapTuple optup;
|
||||||
|
|
||||||
|
optup = SearchSysCacheTuple(OPERNAME,
|
||||||
|
PointerGetDatum(opname),
|
||||||
|
ObjectIdGetDatum(datatype),
|
||||||
|
ObjectIdGetDatum(datatype),
|
||||||
|
CharGetDatum('b'));
|
||||||
|
if (!HeapTupleIsValid(optup))
|
||||||
|
return InvalidOid;
|
||||||
|
return optup->t_data->t_oid;
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user