Operators live in namespaces. CREATE/DROP/COMMENT ON OPERATOR take
qualified operator names directly, for example CREATE OPERATOR myschema.+ ( ... ). To qualify an operator name in an expression you need to write OPERATOR(myschema.+) (thanks to Peter for suggesting an escape hatch). I also took advantage of having to reformat pg_operator to fix something that'd been bugging me for a while: mergejoinable operators should have explicit links to the associated cross-data-type comparison operators, rather than hardwiring an assumption that they are named < and >.
This commit is contained in:
parent
4da51bfd6d
commit
6cef5d2549
@ -1,6 +1,6 @@
|
|||||||
<!--
|
<!--
|
||||||
Documentation of the system catalogs, directed toward PostgreSQL developers
|
Documentation of the system catalogs, directed toward PostgreSQL developers
|
||||||
$Header: /cvsroot/pgsql/doc/src/sgml/catalogs.sgml,v 2.41 2002/04/11 19:59:54 tgl Exp $
|
$Header: /cvsroot/pgsql/doc/src/sgml/catalogs.sgml,v 2.42 2002/04/16 23:08:09 tgl Exp $
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<chapter id="catalogs">
|
<chapter id="catalogs">
|
||||||
@ -1482,6 +1482,15 @@
|
|||||||
<entry>Name of the operator</entry>
|
<entry>Name of the operator</entry>
|
||||||
</row>
|
</row>
|
||||||
|
|
||||||
|
<row>
|
||||||
|
<entry>oprnamespace</entry>
|
||||||
|
<entry><type>oid</type></entry>
|
||||||
|
<entry>pg_namespace.oid</entry>
|
||||||
|
<entry>
|
||||||
|
The OID of the namespace that contains this operator
|
||||||
|
</entry>
|
||||||
|
</row>
|
||||||
|
|
||||||
<row>
|
<row>
|
||||||
<entry>oprowner</entry>
|
<entry>oprowner</entry>
|
||||||
<entry><type>int4</type></entry>
|
<entry><type>int4</type></entry>
|
||||||
@ -1493,7 +1502,8 @@
|
|||||||
<entry>oprprec</entry>
|
<entry>oprprec</entry>
|
||||||
<entry><type>int2</type></entry>
|
<entry><type>int2</type></entry>
|
||||||
<entry></entry>
|
<entry></entry>
|
||||||
<entry>unused</entry>
|
<entry>precedence (currently unused, as precedences are hard-wired
|
||||||
|
in the grammar)</entry>
|
||||||
</row>
|
</row>
|
||||||
|
|
||||||
<row>
|
<row>
|
||||||
@ -1510,7 +1520,8 @@
|
|||||||
<entry>oprisleft</entry>
|
<entry>oprisleft</entry>
|
||||||
<entry><type>bool</type></entry>
|
<entry><type>bool</type></entry>
|
||||||
<entry></entry>
|
<entry></entry>
|
||||||
<entry>unused</entry>
|
<entry>left-associativity (currently unused, as this is hard-wired
|
||||||
|
in the grammar)</entry>
|
||||||
</row>
|
</row>
|
||||||
|
|
||||||
<row>
|
<row>
|
||||||
@ -1561,7 +1572,7 @@
|
|||||||
<entry>pg_operator.oid</entry>
|
<entry>pg_operator.oid</entry>
|
||||||
<entry>
|
<entry>
|
||||||
If this operator supports merge joins, the operator that sorts
|
If this operator supports merge joins, the operator that sorts
|
||||||
the type of the left-hand operand
|
the type of the left-hand operand (<literal>L<L</>)
|
||||||
</entry>
|
</entry>
|
||||||
</row>
|
</row>
|
||||||
|
|
||||||
@ -1571,28 +1582,48 @@
|
|||||||
<entry>pg_operator.oid</entry>
|
<entry>pg_operator.oid</entry>
|
||||||
<entry>
|
<entry>
|
||||||
If this operator supports merge joins, the operator that sorts
|
If this operator supports merge joins, the operator that sorts
|
||||||
the type of the right-hand operand
|
the type of the right-hand operand (<literal>R<R</>)
|
||||||
|
</entry>
|
||||||
|
</row>
|
||||||
|
|
||||||
|
<row>
|
||||||
|
<entry>oprltcmpop</entry>
|
||||||
|
<entry><type>oid</type></entry>
|
||||||
|
<entry>pg_operator.oid</entry>
|
||||||
|
<entry>
|
||||||
|
If this operator supports merge joins, the less-than operator that
|
||||||
|
compares the left and right operand types (<literal>L<R</>)
|
||||||
|
</entry>
|
||||||
|
</row>
|
||||||
|
|
||||||
|
<row>
|
||||||
|
<entry>oprgtcmpop</entry>
|
||||||
|
<entry><type>oid</type></entry>
|
||||||
|
<entry>pg_operator.oid</entry>
|
||||||
|
<entry>
|
||||||
|
If this operator supports merge joins, the greater-than operator that
|
||||||
|
compares the left and right operand types (<literal>L>R</>)
|
||||||
</entry>
|
</entry>
|
||||||
</row>
|
</row>
|
||||||
|
|
||||||
<row>
|
<row>
|
||||||
<entry>oprcode</entry>
|
<entry>oprcode</entry>
|
||||||
<entry><type>regproc</type></entry>
|
<entry><type>regproc</type></entry>
|
||||||
<entry></entry>
|
<entry>pg_proc.oid</entry>
|
||||||
<entry>Function that implements this operator</entry>
|
<entry>Function that implements this operator</entry>
|
||||||
</row>
|
</row>
|
||||||
|
|
||||||
<row>
|
<row>
|
||||||
<entry>oprrest</entry>
|
<entry>oprrest</entry>
|
||||||
<entry><type>regproc</type></entry>
|
<entry><type>regproc</type></entry>
|
||||||
<entry></entry>
|
<entry>pg_proc.oid</entry>
|
||||||
<entry>Restriction selectivity estimation function for this operator</entry>
|
<entry>Restriction selectivity estimation function for this operator</entry>
|
||||||
</row>
|
</row>
|
||||||
|
|
||||||
<row>
|
<row>
|
||||||
<entry>oprjoin</entry>
|
<entry>oprjoin</entry>
|
||||||
<entry><type>regproc</type></entry>
|
<entry><type>regproc</type></entry>
|
||||||
<entry></entry>
|
<entry>pg_proc.oid</entry>
|
||||||
<entry>Join selectivity estimation function for this operator</entry>
|
<entry>Join selectivity estimation function for this operator</entry>
|
||||||
</row>
|
</row>
|
||||||
</tbody>
|
</tbody>
|
||||||
@ -2498,28 +2529,28 @@
|
|||||||
<row>
|
<row>
|
||||||
<entry>typinput</entry>
|
<entry>typinput</entry>
|
||||||
<entry><type>regproc</type></entry>
|
<entry><type>regproc</type></entry>
|
||||||
<entry></entry>
|
<entry>pg_proc.oid</entry>
|
||||||
<entry>Input function</entry>
|
<entry>Input function</entry>
|
||||||
</row>
|
</row>
|
||||||
|
|
||||||
<row>
|
<row>
|
||||||
<entry>typoutput</entry>
|
<entry>typoutput</entry>
|
||||||
<entry><type>regproc</type></entry>
|
<entry><type>regproc</type></entry>
|
||||||
<entry></entry>
|
<entry>pg_proc.oid</entry>
|
||||||
<entry>Output function</entry>
|
<entry>Output function</entry>
|
||||||
</row>
|
</row>
|
||||||
|
|
||||||
<row>
|
<row>
|
||||||
<entry>typreceive</entry>
|
<entry>typreceive</entry>
|
||||||
<entry><type>regproc</type></entry>
|
<entry><type>regproc</type></entry>
|
||||||
<entry></entry>
|
<entry>pg_proc.oid</entry>
|
||||||
<entry>unused</entry>
|
<entry>unused</entry>
|
||||||
</row>
|
</row>
|
||||||
|
|
||||||
<row>
|
<row>
|
||||||
<entry>typsend</entry>
|
<entry>typsend</entry>
|
||||||
<entry><type>regproc</type></entry>
|
<entry><type>regproc</type></entry>
|
||||||
<entry></entry>
|
<entry>pg_proc.oid</entry>
|
||||||
<entry>unused</entry>
|
<entry>unused</entry>
|
||||||
</row>
|
</row>
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<!--
|
<!--
|
||||||
$Header: /cvsroot/pgsql/doc/src/sgml/ref/create_operator.sgml,v 1.25 2002/03/22 19:20:39 petere Exp $
|
$Header: /cvsroot/pgsql/doc/src/sgml/ref/create_operator.sgml,v 1.26 2002/04/16 23:08:10 tgl Exp $
|
||||||
PostgreSQL documentation
|
PostgreSQL documentation
|
||||||
-->
|
-->
|
||||||
|
|
||||||
@ -28,7 +28,9 @@ CREATE OPERATOR <replaceable>name</replaceable> ( PROCEDURE = <replaceable class
|
|||||||
] [, RIGHTARG = <replaceable class="parameter">righttype</replaceable> ]
|
] [, RIGHTARG = <replaceable class="parameter">righttype</replaceable> ]
|
||||||
[, COMMUTATOR = <replaceable class="parameter">com_op</replaceable> ] [, NEGATOR = <replaceable class="parameter">neg_op</replaceable> ]
|
[, COMMUTATOR = <replaceable class="parameter">com_op</replaceable> ] [, NEGATOR = <replaceable class="parameter">neg_op</replaceable> ]
|
||||||
[, RESTRICT = <replaceable class="parameter">res_proc</replaceable> ] [, JOIN = <replaceable class="parameter">join_proc</replaceable> ]
|
[, RESTRICT = <replaceable class="parameter">res_proc</replaceable> ] [, JOIN = <replaceable class="parameter">join_proc</replaceable> ]
|
||||||
[, HASHES ] [, SORT1 = <replaceable class="parameter">left_sort_op</replaceable> ] [, SORT2 = <replaceable class="parameter">right_sort_op</replaceable> ] )
|
[, HASHES ] [, MERGES ]
|
||||||
|
[, SORT1 = <replaceable class="parameter">left_sort_op</replaceable> ] [, SORT2 = <replaceable class="parameter">right_sort_op</replaceable> ]
|
||||||
|
[, LTCMP = <replaceable class="parameter">less_than_op</replaceable> ] [, GTCMP = <replaceable class="parameter">greater_than_op</replaceable> ] )
|
||||||
</synopsis>
|
</synopsis>
|
||||||
|
|
||||||
<refsect2 id="R2-SQL-CREATEOPERATOR-1">
|
<refsect2 id="R2-SQL-CREATEOPERATOR-1">
|
||||||
@ -115,11 +117,19 @@ CREATE OPERATOR <replaceable>name</replaceable> ( PROCEDURE = <replaceable class
|
|||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>MERGES</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Indicates this operator can support a merge join.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><replaceable class="parameter">left_sort_op</replaceable></term>
|
<term><replaceable class="parameter">left_sort_op</replaceable></term>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
If this operator can support a merge join, the
|
If this operator can support a merge join, the less-than
|
||||||
operator that sorts the left-hand data type of this operator.
|
operator that sorts the left-hand data type of this operator.
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
@ -128,11 +138,29 @@ CREATE OPERATOR <replaceable>name</replaceable> ( PROCEDURE = <replaceable class
|
|||||||
<term><replaceable class="parameter">right_sort_op</replaceable></term>
|
<term><replaceable class="parameter">right_sort_op</replaceable></term>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
If this operator can support a merge join, the
|
If this operator can support a merge join, the less-than
|
||||||
operator that sorts the right-hand data type of this operator.
|
operator that sorts the right-hand data type of this operator.
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term><replaceable class="parameter">less_than_op</replaceable></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
If this operator can support a merge join, the less-than
|
||||||
|
operator that compares the input data types of this operator.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term><replaceable class="parameter">greater_than_op</replaceable></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
If this operator can support a merge join, the greater-than
|
||||||
|
operator that compares the input data types of this operator.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
</variablelist>
|
</variablelist>
|
||||||
</para>
|
</para>
|
||||||
</refsect2>
|
</refsect2>
|
||||||
@ -295,30 +323,39 @@ MYBOXES.description !== box '((0,0), (1,1))'
|
|||||||
it also works to just have both operators refer to each other.)
|
it also works to just have both operators refer to each other.)
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
The HASHES, SORT1, and SORT2 options are present to support the
|
The HASHES, MERGES, SORT1, SORT2, LTCMP, and GTCMP options are present to
|
||||||
query optimizer in performing joins.
|
support the query optimizer in performing joins.
|
||||||
<productname>PostgreSQL</productname> can always
|
<productname>PostgreSQL</productname> can always evaluate a join (i.e.,
|
||||||
evaluate a join (i.e., processing a clause with two tuple
|
processing a clause with two tuple variables separated by an operator that
|
||||||
variables separated by an operator that returns a <type>boolean</type>)
|
returns a <type>boolean</type>) by iterative substitution [WONG76]. In
|
||||||
by iterative substitution [WONG76].
|
addition, <productname>PostgreSQL</productname> can use a hash-join
|
||||||
In addition, <productname>PostgreSQL</productname>
|
algorithm along the lines of [SHAP86]; however, it must know whether this
|
||||||
can use a hash-join algorithm along
|
strategy is applicable. The current hash-join algorithm is only correct
|
||||||
the lines of [SHAP86]; however, it must know whether this
|
for operators that represent equality tests; furthermore, equality of the
|
||||||
strategy is applicable. The current hash-join algorithm
|
data type must mean bitwise equality of the representation of the type.
|
||||||
is only correct for operators that represent equality tests;
|
(For example, a data type that contains unused bits that don't matter for
|
||||||
furthermore, equality of the data type must mean bitwise equality
|
equality tests could not be hash-joined.) The HASHES flag indicates to the
|
||||||
of the representation of the type. (For example, a data type that
|
query optimizer that a hash join may safely be used with this
|
||||||
contains unused bits that don't matter for equality tests could
|
operator.
|
||||||
not be hash-joined.)
|
</para>
|
||||||
The HASHES flag indicates to the query optimizer that a hash join
|
|
||||||
may safely be used with this operator.</para>
|
|
||||||
<para>
|
<para>
|
||||||
Similarly, the two sort operators indicate to the query
|
Similarly, the MERGES flag indicates whether merge-sort is a usable join
|
||||||
optimizer whether merge-sort is a usable join strategy and
|
strategy for this operator. A merge join requires that the two input
|
||||||
which operators should be used to sort the two operand
|
datatypes have consistent orderings, and that the mergejoin operator
|
||||||
classes. Sort operators should only be provided for an equality
|
behave like equality with respect to that ordering. For example, it is
|
||||||
operator, and they should refer to less-than operators for the
|
possible to merge-join equality between an integer and a float variable by
|
||||||
left and right side data types respectively.
|
sorting both inputs in ordinary
|
||||||
|
numeric order. Execution of a merge join requires that the system be
|
||||||
|
able to identify four operators related to the mergejoin equality operator:
|
||||||
|
less-than comparison for the left input datatype,
|
||||||
|
less-than comparison for the right input datatype,
|
||||||
|
less-than comparison between the two datatypes, and
|
||||||
|
greater-than comparison between the two datatypes. It is possible to
|
||||||
|
specify these by name, as the SORT1, SORT2, LTCMP, and GTCMP options
|
||||||
|
respectively. The system will fill in the default names <literal><</>,
|
||||||
|
<literal><</>, <literal><</>, <literal>></> respectively if
|
||||||
|
any of these are omitted when MERGES is specified. Also, MERGES will
|
||||||
|
be assumed to be implied if any of these four operator options appear.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
If other join strategies are found to be practical,
|
If other join strategies are found to be practical,
|
||||||
@ -408,8 +445,10 @@ CREATE OPERATOR === (
|
|||||||
RESTRICT = area_restriction_procedure,
|
RESTRICT = area_restriction_procedure,
|
||||||
JOIN = area_join_procedure,
|
JOIN = area_join_procedure,
|
||||||
HASHES,
|
HASHES,
|
||||||
SORT1 = <<<,
|
SORT1 = <<<,
|
||||||
SORT2 = <<<
|
SORT2 = <<<
|
||||||
|
-- Since sort operators were given, MERGES is implied.
|
||||||
|
-- LTCMP and GTCMP are assumed to be < and > respectively
|
||||||
);
|
);
|
||||||
</programlisting>
|
</programlisting>
|
||||||
</refsect1>
|
</refsect1>
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/catalog/indexing.c,v 1.88 2002/04/11 19:59:57 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/catalog/indexing.c,v 1.89 2002/04/16 23:08:10 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -62,7 +62,7 @@ char *Name_pg_namespace_indices[Num_pg_namespace_indices] =
|
|||||||
char *Name_pg_opclass_indices[Num_pg_opclass_indices] =
|
char *Name_pg_opclass_indices[Num_pg_opclass_indices] =
|
||||||
{OpclassAmNameIndex, OpclassOidIndex};
|
{OpclassAmNameIndex, OpclassOidIndex};
|
||||||
char *Name_pg_operator_indices[Num_pg_operator_indices] =
|
char *Name_pg_operator_indices[Num_pg_operator_indices] =
|
||||||
{OperatorOidIndex, OperatorNameIndex};
|
{OperatorOidIndex, OperatorNameNspIndex};
|
||||||
char *Name_pg_proc_indices[Num_pg_proc_indices] =
|
char *Name_pg_proc_indices[Num_pg_proc_indices] =
|
||||||
{ProcedureOidIndex, ProcedureNameNspIndex};
|
{ProcedureOidIndex, ProcedureNameNspIndex};
|
||||||
char *Name_pg_relcheck_indices[Num_pg_relcheck_indices] =
|
char *Name_pg_relcheck_indices[Num_pg_relcheck_indices] =
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/catalog/namespace.c,v 1.9 2002/04/15 22:33:21 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/catalog/namespace.c,v 1.10 2002/04/16 23:08:10 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -27,6 +27,7 @@
|
|||||||
#include "catalog/namespace.h"
|
#include "catalog/namespace.h"
|
||||||
#include "catalog/pg_inherits.h"
|
#include "catalog/pg_inherits.h"
|
||||||
#include "catalog/pg_namespace.h"
|
#include "catalog/pg_namespace.h"
|
||||||
|
#include "catalog/pg_operator.h"
|
||||||
#include "catalog/pg_proc.h"
|
#include "catalog/pg_proc.h"
|
||||||
#include "catalog/pg_shadow.h"
|
#include "catalog/pg_shadow.h"
|
||||||
#include "lib/stringinfo.h"
|
#include "lib/stringinfo.h"
|
||||||
@ -478,6 +479,179 @@ FuncnameGetCandidates(List *names, int nargs)
|
|||||||
return resultList;
|
return resultList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* OpernameGetCandidates
|
||||||
|
* Given a possibly-qualified operator name and operator kind,
|
||||||
|
* retrieve a list of the possible matches.
|
||||||
|
*
|
||||||
|
* We search a single namespace if the operator name is qualified, else
|
||||||
|
* all namespaces in the search path. The return list will never contain
|
||||||
|
* multiple entries with identical argument types --- in the multiple-
|
||||||
|
* namespace case, we arrange for entries in earlier namespaces to mask
|
||||||
|
* identical entries in later namespaces.
|
||||||
|
*
|
||||||
|
* The returned items always have two args[] entries --- one or the other
|
||||||
|
* will be InvalidOid for a prefix or postfix oprkind.
|
||||||
|
*/
|
||||||
|
FuncCandidateList
|
||||||
|
OpernameGetCandidates(List *names, char oprkind)
|
||||||
|
{
|
||||||
|
FuncCandidateList resultList = NULL;
|
||||||
|
char *catalogname;
|
||||||
|
char *schemaname = NULL;
|
||||||
|
char *opername = NULL;
|
||||||
|
Oid namespaceId;
|
||||||
|
CatCList *catlist;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* deconstruct the name list */
|
||||||
|
switch (length(names))
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
opername = strVal(lfirst(names));
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
schemaname = strVal(lfirst(names));
|
||||||
|
opername = strVal(lsecond(names));
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
catalogname = strVal(lfirst(names));
|
||||||
|
schemaname = strVal(lsecond(names));
|
||||||
|
opername = strVal(lfirst(lnext(lnext(names))));
|
||||||
|
/*
|
||||||
|
* We check the catalog name and then ignore it.
|
||||||
|
*/
|
||||||
|
if (strcmp(catalogname, DatabaseName) != 0)
|
||||||
|
elog(ERROR, "Cross-database references are not implemented");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
elog(ERROR, "Improper qualified name (too many dotted names)");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (schemaname)
|
||||||
|
{
|
||||||
|
/* use exact schema given */
|
||||||
|
namespaceId = GetSysCacheOid(NAMESPACENAME,
|
||||||
|
CStringGetDatum(schemaname),
|
||||||
|
0, 0, 0);
|
||||||
|
if (!OidIsValid(namespaceId))
|
||||||
|
elog(ERROR, "Namespace \"%s\" does not exist",
|
||||||
|
schemaname);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* flag to indicate we need namespace search */
|
||||||
|
namespaceId = InvalidOid;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Search syscache by name only */
|
||||||
|
catlist = SearchSysCacheList(OPERNAMENSP, 1,
|
||||||
|
CStringGetDatum(opername),
|
||||||
|
0, 0, 0);
|
||||||
|
|
||||||
|
for (i = 0; i < catlist->n_members; i++)
|
||||||
|
{
|
||||||
|
HeapTuple opertup = &catlist->members[i]->tuple;
|
||||||
|
Form_pg_operator operform = (Form_pg_operator) GETSTRUCT(opertup);
|
||||||
|
int pathpos = 0;
|
||||||
|
FuncCandidateList newResult;
|
||||||
|
|
||||||
|
/* Ignore operators of wrong kind */
|
||||||
|
if (operform->oprkind != oprkind)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (OidIsValid(namespaceId))
|
||||||
|
{
|
||||||
|
/* Consider only opers in specified namespace */
|
||||||
|
if (operform->oprnamespace != namespaceId)
|
||||||
|
continue;
|
||||||
|
/* No need to check args, they must all be different */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Consider only opers that are in the search path */
|
||||||
|
if (pathContainsSystemNamespace ||
|
||||||
|
!IsSystemNamespace(operform->oprnamespace))
|
||||||
|
{
|
||||||
|
List *nsp;
|
||||||
|
|
||||||
|
foreach(nsp, namespaceSearchPath)
|
||||||
|
{
|
||||||
|
pathpos++;
|
||||||
|
if (operform->oprnamespace == (Oid) lfirsti(nsp))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (nsp == NIL)
|
||||||
|
continue; /* oper is not in search path */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Okay, it's in the search path, but does it have the same
|
||||||
|
* arguments as something we already accepted? If so, keep
|
||||||
|
* only the one that appears earlier in the search path.
|
||||||
|
*
|
||||||
|
* If we have an ordered list from SearchSysCacheList (the
|
||||||
|
* normal case), then any conflicting oper must immediately
|
||||||
|
* adjoin this one in the list, so we only need to look at
|
||||||
|
* the newest result item. If we have an unordered list,
|
||||||
|
* we have to scan the whole result list.
|
||||||
|
*/
|
||||||
|
if (resultList)
|
||||||
|
{
|
||||||
|
FuncCandidateList prevResult;
|
||||||
|
|
||||||
|
if (catlist->ordered)
|
||||||
|
{
|
||||||
|
if (operform->oprleft == resultList->args[0] &&
|
||||||
|
operform->oprright == resultList->args[1])
|
||||||
|
prevResult = resultList;
|
||||||
|
else
|
||||||
|
prevResult = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (prevResult = resultList;
|
||||||
|
prevResult;
|
||||||
|
prevResult = prevResult->next)
|
||||||
|
{
|
||||||
|
if (operform->oprleft == prevResult->args[0] &&
|
||||||
|
operform->oprright == prevResult->args[1])
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (prevResult)
|
||||||
|
{
|
||||||
|
/* We have a match with a previous result */
|
||||||
|
Assert(pathpos != prevResult->pathpos);
|
||||||
|
if (pathpos > prevResult->pathpos)
|
||||||
|
continue; /* keep previous result */
|
||||||
|
/* replace previous result */
|
||||||
|
prevResult->pathpos = pathpos;
|
||||||
|
prevResult->oid = opertup->t_data->t_oid;
|
||||||
|
continue; /* args are same, of course */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Okay to add it to result list
|
||||||
|
*/
|
||||||
|
newResult = (FuncCandidateList)
|
||||||
|
palloc(sizeof(struct _FuncCandidateList) + sizeof(Oid));
|
||||||
|
newResult->pathpos = pathpos;
|
||||||
|
newResult->oid = opertup->t_data->t_oid;
|
||||||
|
newResult->args[0] = operform->oprleft;
|
||||||
|
newResult->args[1] = operform->oprright;
|
||||||
|
newResult->next = resultList;
|
||||||
|
resultList = newResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReleaseSysCacheList(catlist);
|
||||||
|
|
||||||
|
return resultList;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* QualifiedNameGetCreationNamespace
|
* QualifiedNameGetCreationNamespace
|
||||||
* Given a possibly-qualified name for an object (in List-of-Values
|
* Given a possibly-qualified name for an object (in List-of-Values
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/commands/analyze.c,v 1.31 2002/04/12 20:38:20 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/commands/analyze.c,v 1.32 2002/04/16 23:08:10 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -398,7 +398,7 @@ examine_attribute(Relation onerel, int attnum)
|
|||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
/* If column has no "=" operator, we can't do much of anything */
|
/* If column has no "=" operator, we can't do much of anything */
|
||||||
func_operator = compatible_oper("=",
|
func_operator = compatible_oper(makeList1(makeString("=")),
|
||||||
attr->atttypid,
|
attr->atttypid,
|
||||||
attr->atttypid,
|
attr->atttypid,
|
||||||
true);
|
true);
|
||||||
@ -436,7 +436,7 @@ examine_attribute(Relation onerel, int attnum)
|
|||||||
stats->eqfunc = eqfunc;
|
stats->eqfunc = eqfunc;
|
||||||
|
|
||||||
/* Is there a "<" operator with suitable semantics? */
|
/* Is there a "<" operator with suitable semantics? */
|
||||||
func_operator = compatible_oper("<",
|
func_operator = compatible_oper(makeList1(makeString("<")),
|
||||||
attr->atttypid,
|
attr->atttypid,
|
||||||
attr->atttypid,
|
attr->atttypid,
|
||||||
true);
|
true);
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* Copyright (c) 1999-2001, PostgreSQL Global Development Group
|
* Copyright (c) 1999-2001, PostgreSQL Global Development Group
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/commands/comment.c,v 1.40 2002/04/11 19:59:57 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/commands/comment.c,v 1.41 2002/04/16 23:08:10 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -28,6 +28,7 @@
|
|||||||
#include "commands/comment.h"
|
#include "commands/comment.h"
|
||||||
#include "miscadmin.h"
|
#include "miscadmin.h"
|
||||||
#include "parser/parse_func.h"
|
#include "parser/parse_func.h"
|
||||||
|
#include "parser/parse_oper.h"
|
||||||
#include "parser/parse_type.h"
|
#include "parser/parse_type.h"
|
||||||
#include "parser/parse.h"
|
#include "parser/parse.h"
|
||||||
#include "utils/acl.h"
|
#include "utils/acl.h"
|
||||||
@ -53,7 +54,7 @@ static void CommentRule(List *qualname, char *comment);
|
|||||||
static void CommentType(List *typename, char *comment);
|
static void CommentType(List *typename, char *comment);
|
||||||
static void CommentAggregate(List *aggregate, List *arguments, char *comment);
|
static void CommentAggregate(List *aggregate, List *arguments, char *comment);
|
||||||
static void CommentProc(List *function, List *arguments, char *comment);
|
static void CommentProc(List *function, List *arguments, char *comment);
|
||||||
static void CommentOperator(List *qualname, List *arguments, char *comment);
|
static void CommentOperator(List *opername, List *arguments, char *comment);
|
||||||
static void CommentTrigger(List *qualname, char *comment);
|
static void CommentTrigger(List *qualname, char *comment);
|
||||||
|
|
||||||
|
|
||||||
@ -643,63 +644,29 @@ CommentProc(List *function, List *arguments, char *comment)
|
|||||||
* to be visible for both operator and function.
|
* to be visible for both operator and function.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
CommentOperator(List *qualname, List *arguments, char *comment)
|
CommentOperator(List *opername, List *arguments, char *comment)
|
||||||
{
|
{
|
||||||
char *opername = strVal(lfirst(qualname)); /* XXX */
|
|
||||||
TypeName *typenode1 = (TypeName *) lfirst(arguments);
|
TypeName *typenode1 = (TypeName *) lfirst(arguments);
|
||||||
TypeName *typenode2 = (TypeName *) lsecond(arguments);
|
TypeName *typenode2 = (TypeName *) lsecond(arguments);
|
||||||
char oprtype = 0;
|
Oid oid;
|
||||||
Form_pg_operator data;
|
|
||||||
HeapTuple optuple;
|
|
||||||
Oid oid,
|
|
||||||
leftoid = InvalidOid,
|
|
||||||
rightoid = InvalidOid;
|
|
||||||
|
|
||||||
/* Attempt to fetch the left type oid, if specified */
|
/* Look up the operator */
|
||||||
if (typenode1 != NULL)
|
|
||||||
leftoid = typenameTypeId(typenode1);
|
|
||||||
|
|
||||||
/* Attempt to fetch the right type oid, if specified */
|
oid = LookupOperNameTypeNames(opername, typenode1, typenode2,
|
||||||
if (typenode2 != NULL)
|
"CommentOperator");
|
||||||
rightoid = typenameTypeId(typenode2);
|
|
||||||
|
|
||||||
/* Determine operator type */
|
|
||||||
|
|
||||||
if (OidIsValid(leftoid) && (OidIsValid(rightoid)))
|
|
||||||
oprtype = 'b';
|
|
||||||
else if (OidIsValid(leftoid))
|
|
||||||
oprtype = 'r';
|
|
||||||
else if (OidIsValid(rightoid))
|
|
||||||
oprtype = 'l';
|
|
||||||
else
|
|
||||||
elog(ERROR, "operator '%s' is of an illegal type'", opername);
|
|
||||||
|
|
||||||
/* Attempt to fetch the operator oid */
|
|
||||||
|
|
||||||
optuple = SearchSysCache(OPERNAME,
|
|
||||||
PointerGetDatum(opername),
|
|
||||||
ObjectIdGetDatum(leftoid),
|
|
||||||
ObjectIdGetDatum(rightoid),
|
|
||||||
CharGetDatum(oprtype));
|
|
||||||
if (!HeapTupleIsValid(optuple))
|
|
||||||
elog(ERROR, "operator '%s' does not exist", opername);
|
|
||||||
|
|
||||||
oid = optuple->t_data->t_oid;
|
|
||||||
|
|
||||||
/* Valid user's ability to comment on this operator */
|
/* Valid user's ability to comment on this operator */
|
||||||
|
|
||||||
if (!pg_oper_ownercheck(oid, GetUserId()))
|
if (!pg_oper_ownercheck(oid, GetUserId()))
|
||||||
elog(ERROR, "you are not permitted to comment on operator '%s'",
|
elog(ERROR, "you are not permitted to comment on operator '%s'",
|
||||||
opername);
|
NameListToString(opername));
|
||||||
|
|
||||||
/* Get the procedure associated with the operator */
|
/* Get the procedure associated with the operator */
|
||||||
|
|
||||||
data = (Form_pg_operator) GETSTRUCT(optuple);
|
oid = get_opcode(oid);
|
||||||
oid = data->oprcode;
|
|
||||||
if (oid == InvalidOid)
|
if (oid == InvalidOid)
|
||||||
elog(ERROR, "operator '%s' does not have an underlying function", opername);
|
elog(ERROR, "operator '%s' does not have an underlying function",
|
||||||
|
NameListToString(opername));
|
||||||
ReleaseSysCache(optuple);
|
|
||||||
|
|
||||||
/* Call CreateComments() to create/drop the comments */
|
/* Call CreateComments() to create/drop the comments */
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/commands/operatorcmds.c,v 1.1 2002/04/15 05:22:03 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/commands/operatorcmds.c,v 1.2 2002/04/16 23:08:10 tgl Exp $
|
||||||
*
|
*
|
||||||
* DESCRIPTION
|
* DESCRIPTION
|
||||||
* The "DefineFoo" routines take the parse tree and pick out the
|
* The "DefineFoo" routines take the parse tree and pick out the
|
||||||
@ -41,6 +41,7 @@
|
|||||||
#include "commands/comment.h"
|
#include "commands/comment.h"
|
||||||
#include "commands/defrem.h"
|
#include "commands/defrem.h"
|
||||||
#include "miscadmin.h"
|
#include "miscadmin.h"
|
||||||
|
#include "parser/parse_oper.h"
|
||||||
#include "parser/parse_type.h"
|
#include "parser/parse_type.h"
|
||||||
#include "utils/acl.h"
|
#include "utils/acl.h"
|
||||||
#include "utils/syscache.h"
|
#include "utils/syscache.h"
|
||||||
@ -59,23 +60,26 @@ DefineOperator(List *names, List *parameters)
|
|||||||
{
|
{
|
||||||
char *oprName;
|
char *oprName;
|
||||||
Oid oprNamespace;
|
Oid oprNamespace;
|
||||||
uint16 precedence = 0; /* operator precedence */
|
uint16 precedence = 0; /* operator precedence */
|
||||||
bool canHash = false; /* operator hashes */
|
bool canHash = false; /* operator hashes */
|
||||||
|
bool canMerge = false; /* operator merges */
|
||||||
bool isLeftAssociative = true; /* operator is left
|
bool isLeftAssociative = true; /* operator is left
|
||||||
* associative */
|
* associative */
|
||||||
char *functionName = NULL; /* function for operator */
|
List *functionName = NIL; /* function for operator */
|
||||||
TypeName *typeName1 = NULL; /* first type name */
|
TypeName *typeName1 = NULL; /* first type name */
|
||||||
TypeName *typeName2 = NULL; /* second type name */
|
TypeName *typeName2 = NULL; /* second type name */
|
||||||
Oid typeId1 = InvalidOid; /* types converted to OID */
|
Oid typeId1 = InvalidOid; /* types converted to OID */
|
||||||
Oid typeId2 = InvalidOid;
|
Oid typeId2 = InvalidOid;
|
||||||
char *commutatorName = NULL; /* optional commutator operator
|
List *commutatorName = NIL; /* optional commutator operator
|
||||||
* name */
|
* name */
|
||||||
char *negatorName = NULL; /* optional negator operator name */
|
List *negatorName = NIL; /* optional negator operator name */
|
||||||
char *restrictionName = NULL; /* optional restrict. sel.
|
List *restrictionName = NIL; /* optional restrict. sel.
|
||||||
* procedure */
|
* procedure */
|
||||||
char *joinName = NULL; /* optional join sel. procedure name */
|
List *joinName = NIL; /* optional join sel. procedure */
|
||||||
char *sortName1 = NULL; /* optional first sort operator */
|
List *leftSortName = NIL; /* optional left sort operator */
|
||||||
char *sortName2 = NULL; /* optional second sort operator */
|
List *rightSortName = NIL; /* optional right sort operator */
|
||||||
|
List *ltCompareName = NIL; /* optional < compare operator */
|
||||||
|
List *gtCompareName = NIL; /* optional > compare operator */
|
||||||
List *pl;
|
List *pl;
|
||||||
|
|
||||||
/* Convert list of names to a name and namespace */
|
/* Convert list of names to a name and namespace */
|
||||||
@ -101,7 +105,7 @@ DefineOperator(List *names, List *parameters)
|
|||||||
elog(ERROR, "setof type not implemented for rightarg");
|
elog(ERROR, "setof type not implemented for rightarg");
|
||||||
}
|
}
|
||||||
else if (strcasecmp(defel->defname, "procedure") == 0)
|
else if (strcasecmp(defel->defname, "procedure") == 0)
|
||||||
functionName = defGetString(defel);
|
functionName = defGetQualifiedName(defel);
|
||||||
else if (strcasecmp(defel->defname, "precedence") == 0)
|
else if (strcasecmp(defel->defname, "precedence") == 0)
|
||||||
{
|
{
|
||||||
/* NOT IMPLEMENTED (never worked in v4.2) */
|
/* NOT IMPLEMENTED (never worked in v4.2) */
|
||||||
@ -113,19 +117,25 @@ DefineOperator(List *names, List *parameters)
|
|||||||
elog(NOTICE, "CREATE OPERATOR: associativity not implemented");
|
elog(NOTICE, "CREATE OPERATOR: associativity not implemented");
|
||||||
}
|
}
|
||||||
else if (strcasecmp(defel->defname, "commutator") == 0)
|
else if (strcasecmp(defel->defname, "commutator") == 0)
|
||||||
commutatorName = defGetString(defel);
|
commutatorName = defGetQualifiedName(defel);
|
||||||
else if (strcasecmp(defel->defname, "negator") == 0)
|
else if (strcasecmp(defel->defname, "negator") == 0)
|
||||||
negatorName = defGetString(defel);
|
negatorName = defGetQualifiedName(defel);
|
||||||
else if (strcasecmp(defel->defname, "restrict") == 0)
|
else if (strcasecmp(defel->defname, "restrict") == 0)
|
||||||
restrictionName = defGetString(defel);
|
restrictionName = defGetQualifiedName(defel);
|
||||||
else if (strcasecmp(defel->defname, "join") == 0)
|
else if (strcasecmp(defel->defname, "join") == 0)
|
||||||
joinName = defGetString(defel);
|
joinName = defGetQualifiedName(defel);
|
||||||
else if (strcasecmp(defel->defname, "hashes") == 0)
|
else if (strcasecmp(defel->defname, "hashes") == 0)
|
||||||
canHash = TRUE;
|
canHash = TRUE;
|
||||||
|
else if (strcasecmp(defel->defname, "merges") == 0)
|
||||||
|
canMerge = TRUE;
|
||||||
else if (strcasecmp(defel->defname, "sort1") == 0)
|
else if (strcasecmp(defel->defname, "sort1") == 0)
|
||||||
sortName1 = defGetString(defel);
|
leftSortName = defGetQualifiedName(defel);
|
||||||
else if (strcasecmp(defel->defname, "sort2") == 0)
|
else if (strcasecmp(defel->defname, "sort2") == 0)
|
||||||
sortName2 = defGetString(defel);
|
rightSortName = defGetQualifiedName(defel);
|
||||||
|
else if (strcasecmp(defel->defname, "ltcmp") == 0)
|
||||||
|
ltCompareName = defGetQualifiedName(defel);
|
||||||
|
else if (strcasecmp(defel->defname, "gtcmp") == 0)
|
||||||
|
gtCompareName = defGetQualifiedName(defel);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
elog(WARNING, "DefineOperator: attribute \"%s\" not recognized",
|
elog(WARNING, "DefineOperator: attribute \"%s\" not recognized",
|
||||||
@ -136,7 +146,7 @@ DefineOperator(List *names, List *parameters)
|
|||||||
/*
|
/*
|
||||||
* make sure we have our required definitions
|
* make sure we have our required definitions
|
||||||
*/
|
*/
|
||||||
if (functionName == NULL)
|
if (functionName == NIL)
|
||||||
elog(ERROR, "Define: \"procedure\" unspecified");
|
elog(ERROR, "Define: \"procedure\" unspecified");
|
||||||
|
|
||||||
/* Transform type names to type OIDs */
|
/* Transform type names to type OIDs */
|
||||||
@ -145,10 +155,31 @@ DefineOperator(List *names, List *parameters)
|
|||||||
if (typeName2)
|
if (typeName2)
|
||||||
typeId2 = typenameTypeId(typeName2);
|
typeId2 = typenameTypeId(typeName2);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If any of the mergejoin support operators were given, then canMerge
|
||||||
|
* is implicit. If canMerge is specified or implicit, fill in default
|
||||||
|
* operator names for any missing mergejoin support operators.
|
||||||
|
*/
|
||||||
|
if (leftSortName || rightSortName || ltCompareName || gtCompareName)
|
||||||
|
canMerge = true;
|
||||||
|
|
||||||
|
if (canMerge)
|
||||||
|
{
|
||||||
|
if (!leftSortName)
|
||||||
|
leftSortName = makeList1(makeString("<"));
|
||||||
|
if (!rightSortName)
|
||||||
|
rightSortName = makeList1(makeString("<"));
|
||||||
|
if (!ltCompareName)
|
||||||
|
ltCompareName = makeList1(makeString("<"));
|
||||||
|
if (!gtCompareName)
|
||||||
|
gtCompareName = makeList1(makeString(">"));
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* now have OperatorCreate do all the work..
|
* now have OperatorCreate do all the work..
|
||||||
*/
|
*/
|
||||||
OperatorCreate(oprName, /* operator name */
|
OperatorCreate(oprName, /* operator name */
|
||||||
|
oprNamespace, /* namespace */
|
||||||
typeId1, /* left type id */
|
typeId1, /* left type id */
|
||||||
typeId2, /* right type id */
|
typeId2, /* right type id */
|
||||||
functionName, /* function for operator */
|
functionName, /* function for operator */
|
||||||
@ -161,9 +192,10 @@ DefineOperator(List *names, List *parameters)
|
|||||||
* procedure */
|
* procedure */
|
||||||
joinName, /* optional join sel. procedure name */
|
joinName, /* optional join sel. procedure name */
|
||||||
canHash, /* operator hashes */
|
canHash, /* operator hashes */
|
||||||
sortName1, /* optional first sort operator */
|
leftSortName, /* optional left sort operator */
|
||||||
sortName2); /* optional second sort operator */
|
rightSortName, /* optional right sort operator */
|
||||||
|
ltCompareName, /* optional < comparison op */
|
||||||
|
gtCompareName); /* optional < comparison op */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -178,70 +210,36 @@ DefineOperator(List *names, List *parameters)
|
|||||||
* ...
|
* ...
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
RemoveOperator(char *operatorName, /* operator name */
|
RemoveOperator(List *operatorName, /* operator name */
|
||||||
TypeName *typeName1, /* left argument type name */
|
TypeName *typeName1, /* left argument type name */
|
||||||
TypeName *typeName2) /* right argument type name */
|
TypeName *typeName2) /* right argument type name */
|
||||||
{
|
{
|
||||||
|
Oid operOid;
|
||||||
Relation relation;
|
Relation relation;
|
||||||
HeapTuple tup;
|
HeapTuple tup;
|
||||||
Oid typeId1 = InvalidOid;
|
|
||||||
Oid typeId2 = InvalidOid;
|
|
||||||
char oprtype;
|
|
||||||
|
|
||||||
if (typeName1)
|
operOid = LookupOperNameTypeNames(operatorName, typeName1, typeName2,
|
||||||
typeId1 = typenameTypeId(typeName1);
|
"RemoveOperator");
|
||||||
|
|
||||||
if (typeName2)
|
|
||||||
typeId2 = typenameTypeId(typeName2);
|
|
||||||
|
|
||||||
if (OidIsValid(typeId1) && OidIsValid(typeId2))
|
|
||||||
oprtype = 'b';
|
|
||||||
else if (OidIsValid(typeId1))
|
|
||||||
oprtype = 'r';
|
|
||||||
else
|
|
||||||
oprtype = 'l';
|
|
||||||
|
|
||||||
relation = heap_openr(OperatorRelationName, RowExclusiveLock);
|
relation = heap_openr(OperatorRelationName, RowExclusiveLock);
|
||||||
|
|
||||||
tup = SearchSysCacheCopy(OPERNAME,
|
tup = SearchSysCacheCopy(OPEROID,
|
||||||
PointerGetDatum(operatorName),
|
ObjectIdGetDatum(operOid),
|
||||||
ObjectIdGetDatum(typeId1),
|
0, 0, 0);
|
||||||
ObjectIdGetDatum(typeId2),
|
|
||||||
CharGetDatum(oprtype));
|
|
||||||
|
|
||||||
if (HeapTupleIsValid(tup))
|
if (!HeapTupleIsValid(tup)) /* should not happen */
|
||||||
{
|
elog(ERROR, "RemoveOperator: failed to find tuple for operator '%s'",
|
||||||
if (!pg_oper_ownercheck(tup->t_data->t_oid, GetUserId()))
|
NameListToString(operatorName));
|
||||||
elog(ERROR, "RemoveOperator: operator '%s': permission denied",
|
|
||||||
operatorName);
|
|
||||||
|
|
||||||
/* Delete any comments associated with this operator */
|
if (!pg_oper_ownercheck(operOid, GetUserId()))
|
||||||
DeleteComments(tup->t_data->t_oid, RelationGetRelid(relation));
|
elog(ERROR, "RemoveOperator: operator '%s': permission denied",
|
||||||
|
NameListToString(operatorName));
|
||||||
|
|
||||||
|
/* Delete any comments associated with this operator */
|
||||||
|
DeleteComments(operOid, RelationGetRelid(relation));
|
||||||
|
|
||||||
|
simple_heap_delete(relation, &tup->t_self);
|
||||||
|
|
||||||
simple_heap_delete(relation, &tup->t_self);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (OidIsValid(typeId1) && OidIsValid(typeId2))
|
|
||||||
{
|
|
||||||
elog(ERROR, "RemoveOperator: binary operator '%s' taking '%s' and '%s' does not exist",
|
|
||||||
operatorName,
|
|
||||||
TypeNameToString(typeName1),
|
|
||||||
TypeNameToString(typeName2));
|
|
||||||
}
|
|
||||||
else if (OidIsValid(typeId1))
|
|
||||||
{
|
|
||||||
elog(ERROR, "RemoveOperator: right unary operator '%s' taking '%s' does not exist",
|
|
||||||
operatorName,
|
|
||||||
TypeNameToString(typeName1));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
elog(ERROR, "RemoveOperator: left unary operator '%s' taking '%s' does not exist",
|
|
||||||
operatorName,
|
|
||||||
TypeNameToString(typeName2));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
heap_freetuple(tup);
|
heap_freetuple(tup);
|
||||||
heap_close(relation, RowExclusiveLock);
|
heap_close(relation, RowExclusiveLock);
|
||||||
}
|
}
|
||||||
|
@ -46,7 +46,7 @@
|
|||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/executor/nodeAgg.c,v 1.81 2002/04/11 19:59:58 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/executor/nodeAgg.c,v 1.82 2002/04/16 23:08:10 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -925,7 +925,8 @@ ExecInitAgg(Agg *node, EState *estate, Plan *parent)
|
|||||||
&peraggstate->inputtypeLen,
|
&peraggstate->inputtypeLen,
|
||||||
&peraggstate->inputtypeByVal);
|
&peraggstate->inputtypeByVal);
|
||||||
|
|
||||||
eq_function = compatible_oper_funcid("=", inputType, inputType,
|
eq_function = compatible_oper_funcid(makeList1(makeString("=")),
|
||||||
|
inputType, inputType,
|
||||||
true);
|
true);
|
||||||
if (!OidIsValid(eq_function))
|
if (!OidIsValid(eq_function))
|
||||||
elog(ERROR, "Unable to identify an equality operator for type '%s'",
|
elog(ERROR, "Unable to identify an equality operator for type '%s'",
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
* locate group boundaries.
|
* locate group boundaries.
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/executor/nodeGroup.c,v 1.44 2001/10/25 05:49:28 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/backend/executor/nodeGroup.c,v 1.45 2002/04/16 23:08:10 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -490,7 +490,8 @@ execTuplesMatchPrepare(TupleDesc tupdesc,
|
|||||||
Oid typid = tupdesc->attrs[att - 1]->atttypid;
|
Oid typid = tupdesc->attrs[att - 1]->atttypid;
|
||||||
Oid eq_function;
|
Oid eq_function;
|
||||||
|
|
||||||
eq_function = compatible_oper_funcid("=", typid, typid, true);
|
eq_function = compatible_oper_funcid(makeList1(makeString("=")),
|
||||||
|
typid, typid, true);
|
||||||
if (!OidIsValid(eq_function))
|
if (!OidIsValid(eq_function))
|
||||||
elog(ERROR, "Unable to identify an equality operator for type '%s'",
|
elog(ERROR, "Unable to identify an equality operator for type '%s'",
|
||||||
typeidTypeName(typid));
|
typeidTypeName(typid));
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.177 2002/04/11 19:59:59 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.178 2002/04/16 23:08:10 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -1526,8 +1526,7 @@ _copyAExpr(A_Expr *from)
|
|||||||
A_Expr *newnode = makeNode(A_Expr);
|
A_Expr *newnode = makeNode(A_Expr);
|
||||||
|
|
||||||
newnode->oper = from->oper;
|
newnode->oper = from->oper;
|
||||||
if (from->opname)
|
Node_Copy(from, newnode, name);
|
||||||
newnode->opname = pstrdup(from->opname);
|
|
||||||
Node_Copy(from, newnode, lexpr);
|
Node_Copy(from, newnode, lexpr);
|
||||||
Node_Copy(from, newnode, rexpr);
|
Node_Copy(from, newnode, rexpr);
|
||||||
|
|
||||||
@ -1648,8 +1647,7 @@ _copySortGroupBy(SortGroupBy *from)
|
|||||||
{
|
{
|
||||||
SortGroupBy *newnode = makeNode(SortGroupBy);
|
SortGroupBy *newnode = makeNode(SortGroupBy);
|
||||||
|
|
||||||
if (from->useOp)
|
Node_Copy(from, newnode, useOp);
|
||||||
newnode->useOp = pstrdup(from->useOp);
|
|
||||||
Node_Copy(from, newnode, node);
|
Node_Copy(from, newnode, node);
|
||||||
|
|
||||||
return newnode;
|
return newnode;
|
||||||
@ -2128,7 +2126,7 @@ _copyRemoveOperStmt(RemoveOperStmt *from)
|
|||||||
{
|
{
|
||||||
RemoveOperStmt *newnode = makeNode(RemoveOperStmt);
|
RemoveOperStmt *newnode = makeNode(RemoveOperStmt);
|
||||||
|
|
||||||
newnode->opname = pstrdup(from->opname);
|
Node_Copy(from, newnode, opname);
|
||||||
Node_Copy(from, newnode, args);
|
Node_Copy(from, newnode, args);
|
||||||
|
|
||||||
return newnode;
|
return newnode;
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.125 2002/04/11 19:59:59 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.126 2002/04/16 23:08:10 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -969,7 +969,7 @@ _equalRemoveFuncStmt(RemoveFuncStmt *a, RemoveFuncStmt *b)
|
|||||||
static bool
|
static bool
|
||||||
_equalRemoveOperStmt(RemoveOperStmt *a, RemoveOperStmt *b)
|
_equalRemoveOperStmt(RemoveOperStmt *a, RemoveOperStmt *b)
|
||||||
{
|
{
|
||||||
if (!equalstr(a->opname, b->opname))
|
if (!equal(a->opname, b->opname))
|
||||||
return false;
|
return false;
|
||||||
if (!equal(a->args, b->args))
|
if (!equal(a->args, b->args))
|
||||||
return false;
|
return false;
|
||||||
@ -1400,7 +1400,7 @@ _equalAExpr(A_Expr *a, A_Expr *b)
|
|||||||
{
|
{
|
||||||
if (a->oper != b->oper)
|
if (a->oper != b->oper)
|
||||||
return false;
|
return false;
|
||||||
if (!equalstr(a->opname, b->opname))
|
if (!equal(a->name, b->name))
|
||||||
return false;
|
return false;
|
||||||
if (!equal(a->lexpr, b->lexpr))
|
if (!equal(a->lexpr, b->lexpr))
|
||||||
return false;
|
return false;
|
||||||
@ -1520,7 +1520,7 @@ _equalTypeCast(TypeCast *a, TypeCast *b)
|
|||||||
static bool
|
static bool
|
||||||
_equalSortGroupBy(SortGroupBy *a, SortGroupBy *b)
|
_equalSortGroupBy(SortGroupBy *a, SortGroupBy *b)
|
||||||
{
|
{
|
||||||
if (!equalstr(a->useOp, b->useOp))
|
if (!equal(a->useOp, b->useOp))
|
||||||
return false;
|
return false;
|
||||||
if (!equal(a->node, b->node))
|
if (!equal(a->node, b->node))
|
||||||
return false;
|
return false;
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/nodes/makefuncs.c,v 1.30 2002/03/29 19:06:09 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/nodes/makefuncs.c,v 1.31 2002/04/16 23:08:10 tgl Exp $
|
||||||
*/
|
*/
|
||||||
#include "postgres.h"
|
#include "postgres.h"
|
||||||
|
|
||||||
@ -16,6 +16,39 @@
|
|||||||
#include "utils/lsyscache.h"
|
#include "utils/lsyscache.h"
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* makeA_Expr -
|
||||||
|
* makes an A_Expr node
|
||||||
|
*/
|
||||||
|
A_Expr *
|
||||||
|
makeA_Expr(int oper, List *name, Node *lexpr, Node *rexpr)
|
||||||
|
{
|
||||||
|
A_Expr *a = makeNode(A_Expr);
|
||||||
|
|
||||||
|
a->oper = oper;
|
||||||
|
a->name = name;
|
||||||
|
a->lexpr = lexpr;
|
||||||
|
a->rexpr = rexpr;
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* makeSimpleA_Expr -
|
||||||
|
* As above, given a simple (unqualified) operator name
|
||||||
|
*/
|
||||||
|
A_Expr *
|
||||||
|
makeSimpleA_Expr(int oper, const char *name,
|
||||||
|
Node *lexpr, Node *rexpr)
|
||||||
|
{
|
||||||
|
A_Expr *a = makeNode(A_Expr);
|
||||||
|
|
||||||
|
a->oper = oper;
|
||||||
|
a->name = makeList1(makeString((char *) name));
|
||||||
|
a->lexpr = lexpr;
|
||||||
|
a->rexpr = rexpr;
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* makeOper -
|
* makeOper -
|
||||||
* creates an Oper node
|
* creates an Oper node
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.154 2002/04/11 19:59:59 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.155 2002/04/16 23:08:10 tgl Exp $
|
||||||
*
|
*
|
||||||
* NOTES
|
* NOTES
|
||||||
* Every (plan) node in POSTGRES has an associated "out" routine which
|
* Every (plan) node in POSTGRES has an associated "out" routine which
|
||||||
@ -1285,7 +1285,7 @@ _outAExpr(StringInfo str, A_Expr *node)
|
|||||||
appendStringInfo(str, "NOT ");
|
appendStringInfo(str, "NOT ");
|
||||||
break;
|
break;
|
||||||
case OP:
|
case OP:
|
||||||
_outToken(str, node->opname);
|
_outNode(str, node->name);
|
||||||
appendStringInfo(str, " ");
|
appendStringInfo(str, " ");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/indxpath.c,v 1.115 2002/04/05 00:31:26 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/indxpath.c,v 1.116 2002/04/16 23:08:10 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -21,6 +21,7 @@
|
|||||||
#include "access/nbtree.h"
|
#include "access/nbtree.h"
|
||||||
#include "catalog/catname.h"
|
#include "catalog/catname.h"
|
||||||
#include "catalog/pg_amop.h"
|
#include "catalog/pg_amop.h"
|
||||||
|
#include "catalog/pg_namespace.h"
|
||||||
#include "catalog/pg_operator.h"
|
#include "catalog/pg_operator.h"
|
||||||
#include "executor/executor.h"
|
#include "executor/executor.h"
|
||||||
#include "nodes/makefuncs.h"
|
#include "nodes/makefuncs.h"
|
||||||
@ -911,7 +912,8 @@ indexable_operator(Expr *clause, Oid opclass, bool indexkey_on_left)
|
|||||||
* operator, but in practice that seems pretty unlikely for
|
* operator, but in practice that seems pretty unlikely for
|
||||||
* binary-compatible types.)
|
* binary-compatible types.)
|
||||||
*/
|
*/
|
||||||
new_op = compatible_oper_opid(opname, indexkeytype, indexkeytype, true);
|
new_op = compatible_oper_opid(makeList1(makeString(opname)),
|
||||||
|
indexkeytype, indexkeytype, true);
|
||||||
|
|
||||||
if (OidIsValid(new_op))
|
if (OidIsValid(new_op))
|
||||||
{
|
{
|
||||||
@ -2143,14 +2145,15 @@ network_prefix_quals(Var *leftop, Oid expr_op, Datum rightop)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* See if there is a binary op of the given name for the given datatype */
|
/* See if there is a binary op of the given name for the given datatype */
|
||||||
|
/* NB: we assume that only built-in system operators are searched for */
|
||||||
static Oid
|
static Oid
|
||||||
find_operator(const char *opname, Oid datatype)
|
find_operator(const char *opname, Oid datatype)
|
||||||
{
|
{
|
||||||
return GetSysCacheOid(OPERNAME,
|
return GetSysCacheOid(OPERNAMENSP,
|
||||||
PointerGetDatum(opname),
|
PointerGetDatum(opname),
|
||||||
ObjectIdGetDatum(datatype),
|
ObjectIdGetDatum(datatype),
|
||||||
ObjectIdGetDatum(datatype),
|
ObjectIdGetDatum(datatype),
|
||||||
CharGetDatum('b'));
|
ObjectIdGetDatum(PG_CATALOG_NAMESPACE));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/initsplan.c,v 1.67 2002/03/12 00:51:45 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/initsplan.c,v 1.68 2002/04/16 23:08:10 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -740,7 +740,8 @@ process_implied_equality(Query *root, Node *item1, Node *item2,
|
|||||||
*/
|
*/
|
||||||
ltype = exprType(item1);
|
ltype = exprType(item1);
|
||||||
rtype = exprType(item2);
|
rtype = exprType(item2);
|
||||||
eq_operator = compatible_oper("=", ltype, rtype, true);
|
eq_operator = compatible_oper(makeList1(makeString("=")),
|
||||||
|
ltype, rtype, true);
|
||||||
if (!HeapTupleIsValid(eq_operator))
|
if (!HeapTupleIsValid(eq_operator))
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/subselect.c,v 1.50 2001/11/30 19:24:15 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/subselect.c,v 1.51 2002/04/16 23:08:11 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -284,9 +284,9 @@ make_subplan(SubLink *slink)
|
|||||||
* Note: we use make_operand in case runtime type conversion
|
* Note: we use make_operand in case runtime type conversion
|
||||||
* function calls must be inserted for this operator!
|
* function calls must be inserted for this operator!
|
||||||
*/
|
*/
|
||||||
left = make_operand("", lefthand,
|
left = make_operand(lefthand,
|
||||||
exprType(lefthand), opform->oprleft);
|
exprType(lefthand), opform->oprleft);
|
||||||
right = make_operand("", (Node *) prm,
|
right = make_operand((Node *) prm,
|
||||||
prm->paramtype, opform->oprright);
|
prm->paramtype, opform->oprright);
|
||||||
ReleaseSysCache(tup);
|
ReleaseSysCache(tup);
|
||||||
|
|
||||||
@ -433,9 +433,9 @@ make_subplan(SubLink *slink)
|
|||||||
* Note: we use make_operand in case runtime type conversion
|
* Note: we use make_operand in case runtime type conversion
|
||||||
* function calls must be inserted for this operator!
|
* function calls must be inserted for this operator!
|
||||||
*/
|
*/
|
||||||
left = make_operand("", lefthand,
|
left = make_operand(lefthand,
|
||||||
exprType(lefthand), opform->oprleft);
|
exprType(lefthand), opform->oprleft);
|
||||||
right = make_operand("", (Node *) con,
|
right = make_operand((Node *) con,
|
||||||
con->consttype, opform->oprright);
|
con->consttype, opform->oprright);
|
||||||
ReleaseSysCache(tup);
|
ReleaseSysCache(tup);
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.229 2002/04/12 19:11:49 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.230 2002/04/16 23:08:11 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -1460,11 +1460,13 @@ transformFKConstraints(ParseState *pstate, CreateStmtContext *cxt)
|
|||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* fktypoid[i] is the foreign key table's i'th element's type
|
* fktypoid[i] is the foreign key table's i'th element's type
|
||||||
* oid pktypoid[i] is the primary key table's i'th element's
|
* pktypoid[i] is the primary key table's i'th element's type
|
||||||
* type oid We let oper() do our work for us, including
|
*
|
||||||
* elog(ERROR) if the types don't compare with =
|
* We let oper() do our work for us, including elog(ERROR) if
|
||||||
|
* the types don't compare with =
|
||||||
*/
|
*/
|
||||||
Operator o = oper("=", fktypoid[i], pktypoid[i], false);
|
Operator o = oper(makeList1(makeString("=")),
|
||||||
|
fktypoid[i], pktypoid[i], false);
|
||||||
|
|
||||||
ReleaseSysCache(o);
|
ReleaseSysCache(o);
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.301 2002/04/09 20:35:51 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.302 2002/04/16 23:08:11 tgl Exp $
|
||||||
*
|
*
|
||||||
* HISTORY
|
* HISTORY
|
||||||
* AUTHOR DATE MAJOR EVENT
|
* AUTHOR DATE MAJOR EVENT
|
||||||
@ -82,11 +82,10 @@ static int pfunc_num_args;
|
|||||||
*/
|
*/
|
||||||
/*#define __YYSCLASS*/
|
/*#define __YYSCLASS*/
|
||||||
|
|
||||||
static Node *makeA_Expr(int oper, char *opname, Node *lexpr, Node *rexpr);
|
|
||||||
static Node *makeTypeCast(Node *arg, TypeName *typename);
|
static Node *makeTypeCast(Node *arg, TypeName *typename);
|
||||||
static Node *makeStringConst(char *str, TypeName *typename);
|
static Node *makeStringConst(char *str, TypeName *typename);
|
||||||
static Node *makeFloatConst(char *str);
|
static Node *makeFloatConst(char *str);
|
||||||
static Node *makeRowExpr(char *opr, List *largs, List *rargs);
|
static Node *makeRowExpr(List *opr, List *largs, List *rargs);
|
||||||
static SelectStmt *findLeftmostSelect(SelectStmt *node);
|
static SelectStmt *findLeftmostSelect(SelectStmt *node);
|
||||||
static void insertSelectOptions(SelectStmt *stmt,
|
static void insertSelectOptions(SelectStmt *stmt,
|
||||||
List *sortClause, List *forUpdate,
|
List *sortClause, List *forUpdate,
|
||||||
@ -177,13 +176,13 @@ static bool set_name_needs_quotes(const char *name);
|
|||||||
database_name, access_method_clause, access_method, attr_name,
|
database_name, access_method_clause, access_method, attr_name,
|
||||||
class, index_name, name, function_name, file_name
|
class, index_name, name, function_name, file_name
|
||||||
|
|
||||||
%type <list> func_name, handler_name
|
%type <list> func_name, handler_name, qual_Op, qual_all_Op, OptUseOp
|
||||||
|
|
||||||
%type <range> qualified_name, OptConstrFromTable
|
%type <range> qualified_name, OptConstrFromTable
|
||||||
|
|
||||||
%type <str> opt_id,
|
%type <str> opt_id,
|
||||||
all_Op, MathOp, opt_name,
|
all_Op, MathOp, opt_name,
|
||||||
OptUseOp, opt_class, SpecialRuleRelation
|
opt_class, SpecialRuleRelation
|
||||||
|
|
||||||
%type <str> opt_level, opt_encoding
|
%type <str> opt_level, opt_encoding
|
||||||
%type <node> grantee
|
%type <node> grantee
|
||||||
@ -202,7 +201,7 @@ static bool set_name_needs_quotes(const char *name);
|
|||||||
opt_column_list, columnList, opt_name_list,
|
opt_column_list, columnList, opt_name_list,
|
||||||
sort_clause, sortby_list, index_params, index_list, name_list,
|
sort_clause, sortby_list, index_params, index_list, name_list,
|
||||||
from_clause, from_list, opt_array_bounds, qualified_name_list,
|
from_clause, from_list, opt_array_bounds, qualified_name_list,
|
||||||
any_name, any_name_list, expr_list, dotted_name, attrs,
|
any_name, any_name_list, any_operator, expr_list, dotted_name, attrs,
|
||||||
target_list, update_target_list, insert_column_list,
|
target_list, update_target_list, insert_column_list,
|
||||||
insert_target_list,
|
insert_target_list,
|
||||||
def_list, opt_indirection, group_clause, TriggerFuncArgs,
|
def_list, opt_indirection, group_clause, TriggerFuncArgs,
|
||||||
@ -404,7 +403,7 @@ static bool set_name_needs_quotes(const char *name);
|
|||||||
%nonassoc BETWEEN
|
%nonassoc BETWEEN
|
||||||
%nonassoc IN
|
%nonassoc IN
|
||||||
%left POSTFIXOP /* dummy for postfix Op rules */
|
%left POSTFIXOP /* dummy for postfix Op rules */
|
||||||
%left Op /* multi-character ops and user-defined operators */
|
%left Op OPERATOR /* multi-character ops and user-defined operators */
|
||||||
%nonassoc NOTNULL
|
%nonassoc NOTNULL
|
||||||
%nonassoc ISNULL
|
%nonassoc ISNULL
|
||||||
%nonassoc IS NULL_P TRUE_P FALSE_P UNKNOWN /* sets precedence for IS NULL, etc */
|
%nonassoc IS NULL_P TRUE_P FALSE_P UNKNOWN /* sets precedence for IS NULL, etc */
|
||||||
@ -2086,11 +2085,11 @@ DefineStmt: CREATE AGGREGATE func_name definition
|
|||||||
n->definition = $4;
|
n->definition = $4;
|
||||||
$$ = (Node *)n;
|
$$ = (Node *)n;
|
||||||
}
|
}
|
||||||
| CREATE OPERATOR all_Op definition
|
| CREATE OPERATOR any_operator definition
|
||||||
{
|
{
|
||||||
DefineStmt *n = makeNode(DefineStmt);
|
DefineStmt *n = makeNode(DefineStmt);
|
||||||
n->defType = OPERATOR;
|
n->defType = OPERATOR;
|
||||||
n->defnames = makeList1(makeString($3)); /* XXX */
|
n->defnames = $3;
|
||||||
n->definition = $4;
|
n->definition = $4;
|
||||||
$$ = (Node *)n;
|
$$ = (Node *)n;
|
||||||
}
|
}
|
||||||
@ -2227,11 +2226,11 @@ CommentStmt: COMMENT ON comment_type any_name IS comment_text
|
|||||||
n->comment = $7;
|
n->comment = $7;
|
||||||
$$ = (Node *) n;
|
$$ = (Node *) n;
|
||||||
}
|
}
|
||||||
| COMMENT ON OPERATOR all_Op '(' oper_argtypes ')' IS comment_text
|
| COMMENT ON OPERATOR any_operator '(' oper_argtypes ')' IS comment_text
|
||||||
{
|
{
|
||||||
CommentStmt *n = makeNode(CommentStmt);
|
CommentStmt *n = makeNode(CommentStmt);
|
||||||
n->objtype = OPERATOR;
|
n->objtype = OPERATOR;
|
||||||
n->objname = makeList1(makeString($4)); /* XXX */
|
n->objname = $4;
|
||||||
n->objargs = $6;
|
n->objargs = $6;
|
||||||
n->comment = $9;
|
n->comment = $9;
|
||||||
$$ = (Node *) n;
|
$$ = (Node *) n;
|
||||||
@ -2812,7 +2811,7 @@ aggr_argtype: Typename { $$ = $1; }
|
|||||||
| '*' { $$ = NULL; }
|
| '*' { $$ = NULL; }
|
||||||
;
|
;
|
||||||
|
|
||||||
RemoveOperStmt: DROP OPERATOR all_Op '(' oper_argtypes ')'
|
RemoveOperStmt: DROP OPERATOR any_operator '(' oper_argtypes ')'
|
||||||
{
|
{
|
||||||
RemoveOperStmt *n = makeNode(RemoveOperStmt);
|
RemoveOperStmt *n = makeNode(RemoveOperStmt);
|
||||||
n->opname = $3;
|
n->opname = $3;
|
||||||
@ -2833,6 +2832,12 @@ oper_argtypes: Typename
|
|||||||
{ $$ = makeList2($1, NULL); }
|
{ $$ = makeList2($1, NULL); }
|
||||||
;
|
;
|
||||||
|
|
||||||
|
any_operator: all_Op
|
||||||
|
{ $$ = makeList1(makeString($1)); }
|
||||||
|
| ColId '.' any_operator
|
||||||
|
{ $$ = lcons(makeString($1), $3); }
|
||||||
|
;
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
*
|
*
|
||||||
@ -3831,10 +3836,14 @@ sortby: a_expr OptUseOp
|
|||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
OptUseOp: USING all_Op { $$ = $2; }
|
OptUseOp: USING qual_all_Op
|
||||||
| ASC { $$ = "<"; }
|
{ $$ = $2; }
|
||||||
| DESC { $$ = ">"; }
|
| ASC
|
||||||
| /*EMPTY*/ { $$ = "<"; /*default*/ }
|
{ $$ = makeList1(makeString("<")); }
|
||||||
|
| DESC
|
||||||
|
{ $$ = makeList1(makeString(">")); }
|
||||||
|
| /*EMPTY*/
|
||||||
|
{ $$ = makeList1(makeString("<")); /*default*/ }
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
||||||
@ -4593,7 +4602,7 @@ row_expr: '(' row_descriptor ')' IN select_with_parens
|
|||||||
{
|
{
|
||||||
SubLink *n = makeNode(SubLink);
|
SubLink *n = makeNode(SubLink);
|
||||||
n->lefthand = $2;
|
n->lefthand = $2;
|
||||||
n->oper = (List *) makeA_Expr(OP, "=", NULL, NULL);
|
n->oper = (List *) makeSimpleA_Expr(OP, "=", NULL, NULL);
|
||||||
n->useor = FALSE;
|
n->useor = FALSE;
|
||||||
n->subLinkType = ANY_SUBLINK;
|
n->subLinkType = ANY_SUBLINK;
|
||||||
n->subselect = $5;
|
n->subselect = $5;
|
||||||
@ -4603,18 +4612,18 @@ row_expr: '(' row_descriptor ')' IN select_with_parens
|
|||||||
{
|
{
|
||||||
SubLink *n = makeNode(SubLink);
|
SubLink *n = makeNode(SubLink);
|
||||||
n->lefthand = $2;
|
n->lefthand = $2;
|
||||||
n->oper = (List *) makeA_Expr(OP, "<>", NULL, NULL);
|
n->oper = (List *) makeSimpleA_Expr(OP, "<>", NULL, NULL);
|
||||||
n->useor = TRUE;
|
n->useor = TRUE;
|
||||||
n->subLinkType = ALL_SUBLINK;
|
n->subLinkType = ALL_SUBLINK;
|
||||||
n->subselect = $6;
|
n->subselect = $6;
|
||||||
$$ = (Node *)n;
|
$$ = (Node *)n;
|
||||||
}
|
}
|
||||||
| '(' row_descriptor ')' all_Op sub_type select_with_parens
|
| '(' row_descriptor ')' qual_all_Op sub_type select_with_parens %prec Op
|
||||||
{
|
{
|
||||||
SubLink *n = makeNode(SubLink);
|
SubLink *n = makeNode(SubLink);
|
||||||
n->lefthand = $2;
|
n->lefthand = $2;
|
||||||
n->oper = (List *) makeA_Expr(OP, $4, NULL, NULL);
|
n->oper = (List *) makeA_Expr(OP, $4, NULL, NULL);
|
||||||
if (strcmp($4, "<>") == 0)
|
if (strcmp(strVal(llast($4)), "<>") == 0)
|
||||||
n->useor = TRUE;
|
n->useor = TRUE;
|
||||||
else
|
else
|
||||||
n->useor = FALSE;
|
n->useor = FALSE;
|
||||||
@ -4622,12 +4631,12 @@ row_expr: '(' row_descriptor ')' IN select_with_parens
|
|||||||
n->subselect = $6;
|
n->subselect = $6;
|
||||||
$$ = (Node *)n;
|
$$ = (Node *)n;
|
||||||
}
|
}
|
||||||
| '(' row_descriptor ')' all_Op select_with_parens
|
| '(' row_descriptor ')' qual_all_Op select_with_parens %prec Op
|
||||||
{
|
{
|
||||||
SubLink *n = makeNode(SubLink);
|
SubLink *n = makeNode(SubLink);
|
||||||
n->lefthand = $2;
|
n->lefthand = $2;
|
||||||
n->oper = (List *) makeA_Expr(OP, $4, NULL, NULL);
|
n->oper = (List *) makeA_Expr(OP, $4, NULL, NULL);
|
||||||
if (strcmp($4, "<>") == 0)
|
if (strcmp(strVal(llast($4)), "<>") == 0)
|
||||||
n->useor = TRUE;
|
n->useor = TRUE;
|
||||||
else
|
else
|
||||||
n->useor = FALSE;
|
n->useor = FALSE;
|
||||||
@ -4635,7 +4644,7 @@ row_expr: '(' row_descriptor ')' IN select_with_parens
|
|||||||
n->subselect = $5;
|
n->subselect = $5;
|
||||||
$$ = (Node *)n;
|
$$ = (Node *)n;
|
||||||
}
|
}
|
||||||
| '(' row_descriptor ')' all_Op '(' row_descriptor ')'
|
| '(' row_descriptor ')' qual_all_Op '(' row_descriptor ')' %prec Op
|
||||||
{
|
{
|
||||||
$$ = makeRowExpr($4, $2, $6);
|
$$ = makeRowExpr($4, $2, $6);
|
||||||
}
|
}
|
||||||
@ -4696,6 +4705,18 @@ MathOp: '+' { $$ = "+"; }
|
|||||||
| '=' { $$ = "="; }
|
| '=' { $$ = "="; }
|
||||||
;
|
;
|
||||||
|
|
||||||
|
qual_Op: Op
|
||||||
|
{ $$ = makeList1(makeString($1)); }
|
||||||
|
| OPERATOR '(' any_operator ')'
|
||||||
|
{ $$ = $3; }
|
||||||
|
;
|
||||||
|
|
||||||
|
qual_all_Op: all_Op
|
||||||
|
{ $$ = makeList1(makeString($1)); }
|
||||||
|
| OPERATOR '(' any_operator ')'
|
||||||
|
{ $$ = $3; }
|
||||||
|
;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* General expressions
|
* General expressions
|
||||||
* This is the heart of the expression syntax.
|
* This is the heart of the expression syntax.
|
||||||
@ -4735,52 +4756,52 @@ a_expr: c_expr
|
|||||||
* also to b_expr and to the MathOp list above.
|
* also to b_expr and to the MathOp list above.
|
||||||
*/
|
*/
|
||||||
| '+' a_expr %prec UMINUS
|
| '+' a_expr %prec UMINUS
|
||||||
{ $$ = makeA_Expr(OP, "+", NULL, $2); }
|
{ $$ = (Node *) makeSimpleA_Expr(OP, "+", NULL, $2); }
|
||||||
| '-' a_expr %prec UMINUS
|
| '-' a_expr %prec UMINUS
|
||||||
{ $$ = doNegate($2); }
|
{ $$ = doNegate($2); }
|
||||||
| '%' a_expr
|
| '%' a_expr
|
||||||
{ $$ = makeA_Expr(OP, "%", NULL, $2); }
|
{ $$ = (Node *) makeSimpleA_Expr(OP, "%", NULL, $2); }
|
||||||
| '^' a_expr
|
| '^' a_expr
|
||||||
{ $$ = makeA_Expr(OP, "^", NULL, $2); }
|
{ $$ = (Node *) makeSimpleA_Expr(OP, "^", NULL, $2); }
|
||||||
| a_expr '%'
|
| a_expr '%'
|
||||||
{ $$ = makeA_Expr(OP, "%", $1, NULL); }
|
{ $$ = (Node *) makeSimpleA_Expr(OP, "%", $1, NULL); }
|
||||||
| a_expr '^'
|
| a_expr '^'
|
||||||
{ $$ = makeA_Expr(OP, "^", $1, NULL); }
|
{ $$ = (Node *) makeSimpleA_Expr(OP, "^", $1, NULL); }
|
||||||
| a_expr '+' a_expr
|
| a_expr '+' a_expr
|
||||||
{ $$ = makeA_Expr(OP, "+", $1, $3); }
|
{ $$ = (Node *) makeSimpleA_Expr(OP, "+", $1, $3); }
|
||||||
| a_expr '-' a_expr
|
| a_expr '-' a_expr
|
||||||
{ $$ = makeA_Expr(OP, "-", $1, $3); }
|
{ $$ = (Node *) makeSimpleA_Expr(OP, "-", $1, $3); }
|
||||||
| a_expr '*' a_expr
|
| a_expr '*' a_expr
|
||||||
{ $$ = makeA_Expr(OP, "*", $1, $3); }
|
{ $$ = (Node *) makeSimpleA_Expr(OP, "*", $1, $3); }
|
||||||
| a_expr '/' a_expr
|
| a_expr '/' a_expr
|
||||||
{ $$ = makeA_Expr(OP, "/", $1, $3); }
|
{ $$ = (Node *) makeSimpleA_Expr(OP, "/", $1, $3); }
|
||||||
| a_expr '%' a_expr
|
| a_expr '%' a_expr
|
||||||
{ $$ = makeA_Expr(OP, "%", $1, $3); }
|
{ $$ = (Node *) makeSimpleA_Expr(OP, "%", $1, $3); }
|
||||||
| a_expr '^' a_expr
|
| a_expr '^' a_expr
|
||||||
{ $$ = makeA_Expr(OP, "^", $1, $3); }
|
{ $$ = (Node *) makeSimpleA_Expr(OP, "^", $1, $3); }
|
||||||
| a_expr '<' a_expr
|
| a_expr '<' a_expr
|
||||||
{ $$ = makeA_Expr(OP, "<", $1, $3); }
|
{ $$ = (Node *) makeSimpleA_Expr(OP, "<", $1, $3); }
|
||||||
| a_expr '>' a_expr
|
| a_expr '>' a_expr
|
||||||
{ $$ = makeA_Expr(OP, ">", $1, $3); }
|
{ $$ = (Node *) makeSimpleA_Expr(OP, ">", $1, $3); }
|
||||||
| a_expr '=' a_expr
|
| a_expr '=' a_expr
|
||||||
{ $$ = makeA_Expr(OP, "=", $1, $3); }
|
{ $$ = (Node *) makeSimpleA_Expr(OP, "=", $1, $3); }
|
||||||
|
|
||||||
| a_expr Op a_expr
|
| a_expr qual_Op a_expr %prec Op
|
||||||
{ $$ = makeA_Expr(OP, $2, $1, $3); }
|
{ $$ = (Node *) makeA_Expr(OP, $2, $1, $3); }
|
||||||
| Op a_expr
|
| qual_Op a_expr %prec Op
|
||||||
{ $$ = makeA_Expr(OP, $1, NULL, $2); }
|
{ $$ = (Node *) makeA_Expr(OP, $1, NULL, $2); }
|
||||||
| a_expr Op %prec POSTFIXOP
|
| a_expr qual_Op %prec POSTFIXOP
|
||||||
{ $$ = makeA_Expr(OP, $2, $1, NULL); }
|
{ $$ = (Node *) makeA_Expr(OP, $2, $1, NULL); }
|
||||||
|
|
||||||
| a_expr AND a_expr
|
| a_expr AND a_expr
|
||||||
{ $$ = makeA_Expr(AND, NULL, $1, $3); }
|
{ $$ = (Node *) makeA_Expr(AND, NIL, $1, $3); }
|
||||||
| a_expr OR a_expr
|
| a_expr OR a_expr
|
||||||
{ $$ = makeA_Expr(OR, NULL, $1, $3); }
|
{ $$ = (Node *) makeA_Expr(OR, NIL, $1, $3); }
|
||||||
| NOT a_expr
|
| NOT a_expr
|
||||||
{ $$ = makeA_Expr(NOT, NULL, NULL, $2); }
|
{ $$ = (Node *) makeA_Expr(NOT, NIL, NULL, $2); }
|
||||||
|
|
||||||
| a_expr LIKE a_expr
|
| a_expr LIKE a_expr
|
||||||
{ $$ = makeA_Expr(OP, "~~", $1, $3); }
|
{ $$ = (Node *) makeSimpleA_Expr(OP, "~~", $1, $3); }
|
||||||
| a_expr LIKE a_expr ESCAPE a_expr
|
| a_expr LIKE a_expr ESCAPE a_expr
|
||||||
{
|
{
|
||||||
FuncCall *n = makeNode(FuncCall);
|
FuncCall *n = makeNode(FuncCall);
|
||||||
@ -4788,10 +4809,10 @@ a_expr: c_expr
|
|||||||
n->args = makeList2($3, $5);
|
n->args = makeList2($3, $5);
|
||||||
n->agg_star = FALSE;
|
n->agg_star = FALSE;
|
||||||
n->agg_distinct = FALSE;
|
n->agg_distinct = FALSE;
|
||||||
$$ = makeA_Expr(OP, "~~", $1, (Node *) n);
|
$$ = (Node *) makeSimpleA_Expr(OP, "~~", $1, (Node *) n);
|
||||||
}
|
}
|
||||||
| a_expr NOT LIKE a_expr
|
| a_expr NOT LIKE a_expr
|
||||||
{ $$ = makeA_Expr(OP, "!~~", $1, $4); }
|
{ $$ = (Node *) makeSimpleA_Expr(OP, "!~~", $1, $4); }
|
||||||
| a_expr NOT LIKE a_expr ESCAPE a_expr
|
| a_expr NOT LIKE a_expr ESCAPE a_expr
|
||||||
{
|
{
|
||||||
FuncCall *n = makeNode(FuncCall);
|
FuncCall *n = makeNode(FuncCall);
|
||||||
@ -4799,10 +4820,10 @@ a_expr: c_expr
|
|||||||
n->args = makeList2($4, $6);
|
n->args = makeList2($4, $6);
|
||||||
n->agg_star = FALSE;
|
n->agg_star = FALSE;
|
||||||
n->agg_distinct = FALSE;
|
n->agg_distinct = FALSE;
|
||||||
$$ = makeA_Expr(OP, "!~~", $1, (Node *) n);
|
$$ = (Node *) makeSimpleA_Expr(OP, "!~~", $1, (Node *) n);
|
||||||
}
|
}
|
||||||
| a_expr ILIKE a_expr
|
| a_expr ILIKE a_expr
|
||||||
{ $$ = makeA_Expr(OP, "~~*", $1, $3); }
|
{ $$ = (Node *) makeSimpleA_Expr(OP, "~~*", $1, $3); }
|
||||||
| a_expr ILIKE a_expr ESCAPE a_expr
|
| a_expr ILIKE a_expr ESCAPE a_expr
|
||||||
{
|
{
|
||||||
FuncCall *n = makeNode(FuncCall);
|
FuncCall *n = makeNode(FuncCall);
|
||||||
@ -4810,10 +4831,10 @@ a_expr: c_expr
|
|||||||
n->args = makeList2($3, $5);
|
n->args = makeList2($3, $5);
|
||||||
n->agg_star = FALSE;
|
n->agg_star = FALSE;
|
||||||
n->agg_distinct = FALSE;
|
n->agg_distinct = FALSE;
|
||||||
$$ = makeA_Expr(OP, "~~*", $1, (Node *) n);
|
$$ = (Node *) makeSimpleA_Expr(OP, "~~*", $1, (Node *) n);
|
||||||
}
|
}
|
||||||
| a_expr NOT ILIKE a_expr
|
| a_expr NOT ILIKE a_expr
|
||||||
{ $$ = makeA_Expr(OP, "!~~*", $1, $4); }
|
{ $$ = (Node *) makeSimpleA_Expr(OP, "!~~*", $1, $4); }
|
||||||
| a_expr NOT ILIKE a_expr ESCAPE a_expr
|
| a_expr NOT ILIKE a_expr ESCAPE a_expr
|
||||||
{
|
{
|
||||||
FuncCall *n = makeNode(FuncCall);
|
FuncCall *n = makeNode(FuncCall);
|
||||||
@ -4821,7 +4842,7 @@ a_expr: c_expr
|
|||||||
n->args = makeList2($4, $6);
|
n->args = makeList2($4, $6);
|
||||||
n->agg_star = FALSE;
|
n->agg_star = FALSE;
|
||||||
n->agg_distinct = FALSE;
|
n->agg_distinct = FALSE;
|
||||||
$$ = makeA_Expr(OP, "!~~*", $1, (Node *) n);
|
$$ = (Node *) makeSimpleA_Expr(OP, "!~~*", $1, (Node *) n);
|
||||||
}
|
}
|
||||||
/* NullTest clause
|
/* NullTest clause
|
||||||
* Define SQL92-style Null test clause.
|
* Define SQL92-style Null test clause.
|
||||||
@ -4915,15 +4936,15 @@ a_expr: c_expr
|
|||||||
}
|
}
|
||||||
| a_expr BETWEEN b_expr AND b_expr %prec BETWEEN
|
| a_expr BETWEEN b_expr AND b_expr %prec BETWEEN
|
||||||
{
|
{
|
||||||
$$ = makeA_Expr(AND, NULL,
|
$$ = (Node *) makeA_Expr(AND, NIL,
|
||||||
makeA_Expr(OP, ">=", $1, $3),
|
(Node *) makeSimpleA_Expr(OP, ">=", $1, $3),
|
||||||
makeA_Expr(OP, "<=", $1, $5));
|
(Node *) makeSimpleA_Expr(OP, "<=", $1, $5));
|
||||||
}
|
}
|
||||||
| a_expr NOT BETWEEN b_expr AND b_expr %prec BETWEEN
|
| a_expr NOT BETWEEN b_expr AND b_expr %prec BETWEEN
|
||||||
{
|
{
|
||||||
$$ = makeA_Expr(OR, NULL,
|
$$ = (Node *) makeA_Expr(OR, NIL,
|
||||||
makeA_Expr(OP, "<", $1, $4),
|
(Node *) makeSimpleA_Expr(OP, "<", $1, $4),
|
||||||
makeA_Expr(OP, ">", $1, $6));
|
(Node *) makeSimpleA_Expr(OP, ">", $1, $6));
|
||||||
}
|
}
|
||||||
| a_expr IN in_expr
|
| a_expr IN in_expr
|
||||||
{
|
{
|
||||||
@ -4932,7 +4953,8 @@ a_expr: c_expr
|
|||||||
{
|
{
|
||||||
SubLink *n = (SubLink *)$3;
|
SubLink *n = (SubLink *)$3;
|
||||||
n->lefthand = makeList1($1);
|
n->lefthand = makeList1($1);
|
||||||
n->oper = (List *) makeA_Expr(OP, "=", NULL, NULL);
|
n->oper = (List *) makeSimpleA_Expr(OP, "=",
|
||||||
|
NULL, NULL);
|
||||||
n->useor = FALSE;
|
n->useor = FALSE;
|
||||||
n->subLinkType = ANY_SUBLINK;
|
n->subLinkType = ANY_SUBLINK;
|
||||||
$$ = (Node *)n;
|
$$ = (Node *)n;
|
||||||
@ -4943,11 +4965,13 @@ a_expr: c_expr
|
|||||||
List *l;
|
List *l;
|
||||||
foreach(l, (List *) $3)
|
foreach(l, (List *) $3)
|
||||||
{
|
{
|
||||||
Node *cmp = makeA_Expr(OP, "=", $1, lfirst(l));
|
Node *cmp;
|
||||||
|
cmp = (Node *) makeSimpleA_Expr(OP, "=",
|
||||||
|
$1, lfirst(l));
|
||||||
if (n == NULL)
|
if (n == NULL)
|
||||||
n = cmp;
|
n = cmp;
|
||||||
else
|
else
|
||||||
n = makeA_Expr(OR, NULL, n, cmp);
|
n = (Node *) makeA_Expr(OR, NIL, n, cmp);
|
||||||
}
|
}
|
||||||
$$ = n;
|
$$ = n;
|
||||||
}
|
}
|
||||||
@ -4959,7 +4983,8 @@ a_expr: c_expr
|
|||||||
{
|
{
|
||||||
SubLink *n = (SubLink *)$4;
|
SubLink *n = (SubLink *)$4;
|
||||||
n->lefthand = makeList1($1);
|
n->lefthand = makeList1($1);
|
||||||
n->oper = (List *) makeA_Expr(OP, "<>", NULL, NULL);
|
n->oper = (List *) makeSimpleA_Expr(OP, "<>",
|
||||||
|
NULL, NULL);
|
||||||
n->useor = FALSE;
|
n->useor = FALSE;
|
||||||
n->subLinkType = ALL_SUBLINK;
|
n->subLinkType = ALL_SUBLINK;
|
||||||
$$ = (Node *)n;
|
$$ = (Node *)n;
|
||||||
@ -4970,16 +4995,18 @@ a_expr: c_expr
|
|||||||
List *l;
|
List *l;
|
||||||
foreach(l, (List *) $4)
|
foreach(l, (List *) $4)
|
||||||
{
|
{
|
||||||
Node *cmp = makeA_Expr(OP, "<>", $1, lfirst(l));
|
Node *cmp;
|
||||||
|
cmp = (Node *) makeSimpleA_Expr(OP, "<>",
|
||||||
|
$1, lfirst(l));
|
||||||
if (n == NULL)
|
if (n == NULL)
|
||||||
n = cmp;
|
n = cmp;
|
||||||
else
|
else
|
||||||
n = makeA_Expr(AND, NULL, n, cmp);
|
n = (Node *) makeA_Expr(AND, NIL, n, cmp);
|
||||||
}
|
}
|
||||||
$$ = n;
|
$$ = n;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
| a_expr all_Op sub_type select_with_parens %prec Op
|
| a_expr qual_all_Op sub_type select_with_parens %prec Op
|
||||||
{
|
{
|
||||||
SubLink *n = makeNode(SubLink);
|
SubLink *n = makeNode(SubLink);
|
||||||
n->lefthand = makeList1($1);
|
n->lefthand = makeList1($1);
|
||||||
@ -5007,42 +5034,42 @@ b_expr: c_expr
|
|||||||
| b_expr TYPECAST Typename
|
| b_expr TYPECAST Typename
|
||||||
{ $$ = makeTypeCast($1, $3); }
|
{ $$ = makeTypeCast($1, $3); }
|
||||||
| '+' b_expr %prec UMINUS
|
| '+' b_expr %prec UMINUS
|
||||||
{ $$ = makeA_Expr(OP, "+", NULL, $2); }
|
{ $$ = (Node *) makeSimpleA_Expr(OP, "+", NULL, $2); }
|
||||||
| '-' b_expr %prec UMINUS
|
| '-' b_expr %prec UMINUS
|
||||||
{ $$ = doNegate($2); }
|
{ $$ = doNegate($2); }
|
||||||
| '%' b_expr
|
| '%' b_expr
|
||||||
{ $$ = makeA_Expr(OP, "%", NULL, $2); }
|
{ $$ = (Node *) makeSimpleA_Expr(OP, "%", NULL, $2); }
|
||||||
| '^' b_expr
|
| '^' b_expr
|
||||||
{ $$ = makeA_Expr(OP, "^", NULL, $2); }
|
{ $$ = (Node *) makeSimpleA_Expr(OP, "^", NULL, $2); }
|
||||||
| b_expr '%'
|
| b_expr '%'
|
||||||
{ $$ = makeA_Expr(OP, "%", $1, NULL); }
|
{ $$ = (Node *) makeSimpleA_Expr(OP, "%", $1, NULL); }
|
||||||
| b_expr '^'
|
| b_expr '^'
|
||||||
{ $$ = makeA_Expr(OP, "^", $1, NULL); }
|
{ $$ = (Node *) makeSimpleA_Expr(OP, "^", $1, NULL); }
|
||||||
| b_expr '+' b_expr
|
| b_expr '+' b_expr
|
||||||
{ $$ = makeA_Expr(OP, "+", $1, $3); }
|
{ $$ = (Node *) makeSimpleA_Expr(OP, "+", $1, $3); }
|
||||||
| b_expr '-' b_expr
|
| b_expr '-' b_expr
|
||||||
{ $$ = makeA_Expr(OP, "-", $1, $3); }
|
{ $$ = (Node *) makeSimpleA_Expr(OP, "-", $1, $3); }
|
||||||
| b_expr '*' b_expr
|
| b_expr '*' b_expr
|
||||||
{ $$ = makeA_Expr(OP, "*", $1, $3); }
|
{ $$ = (Node *) makeSimpleA_Expr(OP, "*", $1, $3); }
|
||||||
| b_expr '/' b_expr
|
| b_expr '/' b_expr
|
||||||
{ $$ = makeA_Expr(OP, "/", $1, $3); }
|
{ $$ = (Node *) makeSimpleA_Expr(OP, "/", $1, $3); }
|
||||||
| b_expr '%' b_expr
|
| b_expr '%' b_expr
|
||||||
{ $$ = makeA_Expr(OP, "%", $1, $3); }
|
{ $$ = (Node *) makeSimpleA_Expr(OP, "%", $1, $3); }
|
||||||
| b_expr '^' b_expr
|
| b_expr '^' b_expr
|
||||||
{ $$ = makeA_Expr(OP, "^", $1, $3); }
|
{ $$ = (Node *) makeSimpleA_Expr(OP, "^", $1, $3); }
|
||||||
| b_expr '<' b_expr
|
| b_expr '<' b_expr
|
||||||
{ $$ = makeA_Expr(OP, "<", $1, $3); }
|
{ $$ = (Node *) makeSimpleA_Expr(OP, "<", $1, $3); }
|
||||||
| b_expr '>' b_expr
|
| b_expr '>' b_expr
|
||||||
{ $$ = makeA_Expr(OP, ">", $1, $3); }
|
{ $$ = (Node *) makeSimpleA_Expr(OP, ">", $1, $3); }
|
||||||
| b_expr '=' b_expr
|
| b_expr '=' b_expr
|
||||||
{ $$ = makeA_Expr(OP, "=", $1, $3); }
|
{ $$ = (Node *) makeSimpleA_Expr(OP, "=", $1, $3); }
|
||||||
|
|
||||||
| b_expr Op b_expr
|
| b_expr qual_Op b_expr %prec Op
|
||||||
{ $$ = makeA_Expr(OP, $2, $1, $3); }
|
{ $$ = (Node *) makeA_Expr(OP, $2, $1, $3); }
|
||||||
| Op b_expr
|
| qual_Op b_expr %prec Op
|
||||||
{ $$ = makeA_Expr(OP, $1, NULL, $2); }
|
{ $$ = (Node *) makeA_Expr(OP, $1, NULL, $2); }
|
||||||
| b_expr Op %prec POSTFIXOP
|
| b_expr qual_Op %prec POSTFIXOP
|
||||||
{ $$ = makeA_Expr(OP, $2, $1, NULL); }
|
{ $$ = (Node *) makeA_Expr(OP, $2, $1, NULL); }
|
||||||
;
|
;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -5539,12 +5566,9 @@ case_expr: CASE case_arg when_clause_list case_default END_TRANS
|
|||||||
{
|
{
|
||||||
CaseExpr *c = makeNode(CaseExpr);
|
CaseExpr *c = makeNode(CaseExpr);
|
||||||
CaseWhen *w = makeNode(CaseWhen);
|
CaseWhen *w = makeNode(CaseWhen);
|
||||||
/*
|
|
||||||
A_Const *n = makeNode(A_Const);
|
w->expr = (Node *) makeSimpleA_Expr(OP, "=", $3, $5);
|
||||||
n->val.type = T_Null;
|
/* w->result is left NULL */
|
||||||
w->result = (Node *)n;
|
|
||||||
*/
|
|
||||||
w->expr = makeA_Expr(OP, "=", $3, $5);
|
|
||||||
c->args = makeList1(w);
|
c->args = makeList1(w);
|
||||||
c->defresult = $3;
|
c->defresult = $3;
|
||||||
$$ = (Node *)c;
|
$$ = (Node *)c;
|
||||||
@ -6243,17 +6267,6 @@ SpecialRuleRelation: OLD
|
|||||||
|
|
||||||
%%
|
%%
|
||||||
|
|
||||||
static Node *
|
|
||||||
makeA_Expr(int oper, char *opname, Node *lexpr, Node *rexpr)
|
|
||||||
{
|
|
||||||
A_Expr *a = makeNode(A_Expr);
|
|
||||||
a->oper = oper;
|
|
||||||
a->opname = opname;
|
|
||||||
a->lexpr = lexpr;
|
|
||||||
a->rexpr = rexpr;
|
|
||||||
return (Node *)a;
|
|
||||||
}
|
|
||||||
|
|
||||||
static Node *
|
static Node *
|
||||||
makeTypeCast(Node *arg, TypeName *typename)
|
makeTypeCast(Node *arg, TypeName *typename)
|
||||||
{
|
{
|
||||||
@ -6308,41 +6321,49 @@ makeFloatConst(char *str)
|
|||||||
* - thomas 1997-12-22
|
* - thomas 1997-12-22
|
||||||
*/
|
*/
|
||||||
static Node *
|
static Node *
|
||||||
makeRowExpr(char *opr, List *largs, List *rargs)
|
makeRowExpr(List *opr, List *largs, List *rargs)
|
||||||
{
|
{
|
||||||
Node *expr = NULL;
|
Node *expr = NULL;
|
||||||
Node *larg, *rarg;
|
Node *larg, *rarg;
|
||||||
|
char *oprname;
|
||||||
|
|
||||||
if (length(largs) != length(rargs))
|
if (length(largs) != length(rargs))
|
||||||
elog(ERROR,"Unequal number of entries in row expression");
|
elog(ERROR, "Unequal number of entries in row expression");
|
||||||
|
|
||||||
if (lnext(largs) != NIL)
|
if (lnext(largs) != NIL)
|
||||||
expr = makeRowExpr(opr,lnext(largs),lnext(rargs));
|
expr = makeRowExpr(opr, lnext(largs), lnext(rargs));
|
||||||
|
|
||||||
larg = lfirst(largs);
|
larg = lfirst(largs);
|
||||||
rarg = lfirst(rargs);
|
rarg = lfirst(rargs);
|
||||||
|
|
||||||
if ((strcmp(opr, "=") == 0)
|
oprname = strVal(llast(opr));
|
||||||
|| (strcmp(opr, "<") == 0)
|
|
||||||
|| (strcmp(opr, "<=") == 0)
|
if ((strcmp(oprname, "=") == 0) ||
|
||||||
|| (strcmp(opr, ">") == 0)
|
(strcmp(oprname, "<") == 0) ||
|
||||||
|| (strcmp(opr, ">=") == 0))
|
(strcmp(oprname, "<=") == 0) ||
|
||||||
|
(strcmp(oprname, ">") == 0) ||
|
||||||
|
(strcmp(oprname, ">=") == 0))
|
||||||
{
|
{
|
||||||
if (expr == NULL)
|
if (expr == NULL)
|
||||||
expr = makeA_Expr(OP, opr, larg, rarg);
|
expr = (Node *) makeA_Expr(OP, opr, larg, rarg);
|
||||||
else
|
else
|
||||||
expr = makeA_Expr(AND, NULL, expr, makeA_Expr(OP, opr, larg, rarg));
|
expr = (Node *) makeA_Expr(AND, NIL, expr,
|
||||||
|
(Node *) makeA_Expr(OP, opr,
|
||||||
|
larg, rarg));
|
||||||
}
|
}
|
||||||
else if (strcmp(opr, "<>") == 0)
|
else if (strcmp(oprname, "<>") == 0)
|
||||||
{
|
{
|
||||||
if (expr == NULL)
|
if (expr == NULL)
|
||||||
expr = makeA_Expr(OP, opr, larg, rarg);
|
expr = (Node *) makeA_Expr(OP, opr, larg, rarg);
|
||||||
else
|
else
|
||||||
expr = makeA_Expr(OR, NULL, expr, makeA_Expr(OP, opr, larg, rarg));
|
expr = (Node *) makeA_Expr(OR, NIL, expr,
|
||||||
|
(Node *) makeA_Expr(OP, opr,
|
||||||
|
larg, rarg));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
elog(ERROR,"Operator '%s' not implemented for row expressions",opr);
|
elog(ERROR, "Operator '%s' not implemented for row expressions",
|
||||||
|
oprname);
|
||||||
}
|
}
|
||||||
|
|
||||||
return expr;
|
return expr;
|
||||||
@ -6557,7 +6578,7 @@ doNegate(Node *n)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return makeA_Expr(OP, "-", NULL, n);
|
return (Node *) makeSimpleA_Expr(OP, "-", NULL, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_clause.c,v 1.88 2002/04/15 06:05:49 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/parser/parse_clause.c,v 1.89 2002/04/16 23:08:11 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -54,7 +54,7 @@ static Node *transformFromClauseItem(ParseState *pstate, Node *n,
|
|||||||
static TargetEntry *findTargetlistEntry(ParseState *pstate, Node *node,
|
static TargetEntry *findTargetlistEntry(ParseState *pstate, Node *node,
|
||||||
List *tlist, int clause);
|
List *tlist, int clause);
|
||||||
static List *addTargetToSortList(TargetEntry *tle, List *sortlist,
|
static List *addTargetToSortList(TargetEntry *tle, List *sortlist,
|
||||||
List *targetlist, char *opname);
|
List *targetlist, List *opname);
|
||||||
static bool exprIsInSortList(Node *expr, List *sortList, List *targetList);
|
static bool exprIsInSortList(Node *expr, List *sortList, List *targetList);
|
||||||
|
|
||||||
|
|
||||||
@ -257,22 +257,15 @@ transformJoinUsingClause(ParseState *pstate, List *leftVars, List *rightVars)
|
|||||||
Node *rvar = (Node *) lfirst(rvars);
|
Node *rvar = (Node *) lfirst(rvars);
|
||||||
A_Expr *e;
|
A_Expr *e;
|
||||||
|
|
||||||
e = makeNode(A_Expr);
|
e = makeSimpleA_Expr(OP, "=", copyObject(lvar), copyObject(rvar));
|
||||||
e->oper = OP;
|
|
||||||
e->opname = "=";
|
|
||||||
e->lexpr = copyObject(lvar);
|
|
||||||
e->rexpr = copyObject(rvar);
|
|
||||||
|
|
||||||
if (result == NULL)
|
if (result == NULL)
|
||||||
result = (Node *) e;
|
result = (Node *) e;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
A_Expr *a = makeNode(A_Expr);
|
A_Expr *a;
|
||||||
|
|
||||||
a->oper = AND;
|
a = makeA_Expr(AND, NIL, result, (Node *) e);
|
||||||
a->opname = NULL;
|
|
||||||
a->lexpr = result;
|
|
||||||
a->rexpr = (Node *) e;
|
|
||||||
result = (Node *) a;
|
result = (Node *) a;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1117,7 +1110,7 @@ transformDistinctClause(ParseState *pstate, List *distinctlist,
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
*sortClause = addTargetToSortList(tle, *sortClause,
|
*sortClause = addTargetToSortList(tle, *sortClause,
|
||||||
targetlist, NULL);
|
targetlist, NIL);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Probably, the tle should always have been added at the
|
* Probably, the tle should always have been added at the
|
||||||
@ -1160,7 +1153,7 @@ addAllTargetsToSortList(List *sortlist, List *targetlist)
|
|||||||
TargetEntry *tle = (TargetEntry *) lfirst(i);
|
TargetEntry *tle = (TargetEntry *) lfirst(i);
|
||||||
|
|
||||||
if (!tle->resdom->resjunk)
|
if (!tle->resdom->resjunk)
|
||||||
sortlist = addTargetToSortList(tle, sortlist, targetlist, NULL);
|
sortlist = addTargetToSortList(tle, sortlist, targetlist, NIL);
|
||||||
}
|
}
|
||||||
return sortlist;
|
return sortlist;
|
||||||
}
|
}
|
||||||
@ -1169,13 +1162,13 @@ addAllTargetsToSortList(List *sortlist, List *targetlist)
|
|||||||
* addTargetToSortList
|
* addTargetToSortList
|
||||||
* If the given targetlist entry isn't already in the ORDER BY list,
|
* If the given targetlist entry isn't already in the ORDER BY list,
|
||||||
* add it to the end of the list, using the sortop with given name
|
* add it to the end of the list, using the sortop with given name
|
||||||
* or any available sort operator if opname == NULL.
|
* or any available sort operator if opname == NIL.
|
||||||
*
|
*
|
||||||
* Returns the updated ORDER BY list.
|
* Returns the updated ORDER BY list.
|
||||||
*/
|
*/
|
||||||
static List *
|
static List *
|
||||||
addTargetToSortList(TargetEntry *tle, List *sortlist, List *targetlist,
|
addTargetToSortList(TargetEntry *tle, List *sortlist, List *targetlist,
|
||||||
char *opname)
|
List *opname)
|
||||||
{
|
{
|
||||||
/* avoid making duplicate sortlist entries */
|
/* avoid making duplicate sortlist entries */
|
||||||
if (!exprIsInSortList(tle->expr, sortlist, targetlist))
|
if (!exprIsInSortList(tle->expr, sortlist, targetlist))
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.114 2002/04/11 20:00:00 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.115 2002/04/16 23:08:11 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -192,7 +192,8 @@ transformExpr(ParseState *pstate, Node *expr)
|
|||||||
* into IS NULL exprs.
|
* into IS NULL exprs.
|
||||||
*/
|
*/
|
||||||
if (Transform_null_equals &&
|
if (Transform_null_equals &&
|
||||||
strcmp(a->opname, "=") == 0 &&
|
length(a->name) == 1 &&
|
||||||
|
strcmp(strVal(lfirst(a->name)), "=") == 0 &&
|
||||||
(exprIsNullConstant(a->lexpr) ||
|
(exprIsNullConstant(a->lexpr) ||
|
||||||
exprIsNullConstant(a->rexpr)))
|
exprIsNullConstant(a->rexpr)))
|
||||||
{
|
{
|
||||||
@ -215,7 +216,7 @@ transformExpr(ParseState *pstate, Node *expr)
|
|||||||
Node *rexpr = transformExpr(pstate,
|
Node *rexpr = transformExpr(pstate,
|
||||||
a->rexpr);
|
a->rexpr);
|
||||||
|
|
||||||
result = (Node *) make_op(a->opname,
|
result = (Node *) make_op(a->name,
|
||||||
lexpr,
|
lexpr,
|
||||||
rexpr);
|
rexpr);
|
||||||
}
|
}
|
||||||
@ -366,21 +367,23 @@ transformExpr(ParseState *pstate, Node *expr)
|
|||||||
/* ALL, ANY, or MULTIEXPR: generate operator list */
|
/* ALL, ANY, or MULTIEXPR: generate operator list */
|
||||||
List *left_list = sublink->lefthand;
|
List *left_list = sublink->lefthand;
|
||||||
List *right_list = qtree->targetList;
|
List *right_list = qtree->targetList;
|
||||||
char *op;
|
List *op;
|
||||||
|
char *opname;
|
||||||
List *elist;
|
List *elist;
|
||||||
|
|
||||||
foreach(elist, left_list)
|
foreach(elist, left_list)
|
||||||
lfirst(elist) = transformExpr(pstate, lfirst(elist));
|
lfirst(elist) = transformExpr(pstate, lfirst(elist));
|
||||||
|
|
||||||
Assert(IsA(sublink->oper, A_Expr));
|
Assert(IsA(sublink->oper, A_Expr));
|
||||||
op = ((A_Expr *) sublink->oper)->opname;
|
op = ((A_Expr *) sublink->oper)->name;
|
||||||
|
opname = strVal(llast(op));
|
||||||
sublink->oper = NIL;
|
sublink->oper = NIL;
|
||||||
|
|
||||||
/* Combining operators other than =/<> is dubious... */
|
/* Combining operators other than =/<> is dubious... */
|
||||||
if (length(left_list) != 1 &&
|
if (length(left_list) != 1 &&
|
||||||
strcmp(op, "=") != 0 && strcmp(op, "<>") != 0)
|
strcmp(opname, "=") != 0 && strcmp(opname, "<>") != 0)
|
||||||
elog(ERROR, "Row comparison cannot use '%s'",
|
elog(ERROR, "Row comparison cannot use '%s'",
|
||||||
op);
|
opname);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Scan subquery's targetlist to find values that will
|
* Scan subquery's targetlist to find values that will
|
||||||
@ -420,7 +423,7 @@ transformExpr(ParseState *pstate, Node *expr)
|
|||||||
if (opform->oprresult != BOOLOID)
|
if (opform->oprresult != BOOLOID)
|
||||||
elog(ERROR, "'%s' result type of '%s' must return '%s'"
|
elog(ERROR, "'%s' result type of '%s' must return '%s'"
|
||||||
" to be used with quantified predicate subquery",
|
" to be used with quantified predicate subquery",
|
||||||
op, typeidTypeName(opform->oprresult),
|
opname, typeidTypeName(opform->oprresult),
|
||||||
typeidTypeName(BOOLOID));
|
typeidTypeName(BOOLOID));
|
||||||
|
|
||||||
newop = makeOper(oprid(optup), /* opno */
|
newop = makeOper(oprid(optup), /* opno */
|
||||||
@ -459,13 +462,8 @@ transformExpr(ParseState *pstate, Node *expr)
|
|||||||
if (c->arg != NULL)
|
if (c->arg != NULL)
|
||||||
{
|
{
|
||||||
/* shorthand form was specified, so expand... */
|
/* shorthand form was specified, so expand... */
|
||||||
A_Expr *a = makeNode(A_Expr);
|
warg = (Node *) makeSimpleA_Expr(OP, "=",
|
||||||
|
c->arg, warg);
|
||||||
a->oper = OP;
|
|
||||||
a->opname = "=";
|
|
||||||
a->lexpr = c->arg;
|
|
||||||
a->rexpr = warg;
|
|
||||||
warg = (Node *) a;
|
|
||||||
}
|
}
|
||||||
neww->expr = transformExpr(pstate, warg);
|
neww->expr = transformExpr(pstate, warg);
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_node.c,v 1.61 2002/04/11 20:00:01 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/parser/parse_node.c,v 1.62 2002/04/16 23:08:11 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -62,10 +62,7 @@ make_parsestate(ParseState *parentParseState)
|
|||||||
* Ensure argument type match by forcing conversion of constants.
|
* Ensure argument type match by forcing conversion of constants.
|
||||||
*/
|
*/
|
||||||
Node *
|
Node *
|
||||||
make_operand(char *opname,
|
make_operand(Node *tree, Oid orig_typeId, Oid target_typeId)
|
||||||
Node *tree,
|
|
||||||
Oid orig_typeId,
|
|
||||||
Oid target_typeId)
|
|
||||||
{
|
{
|
||||||
Node *result;
|
Node *result;
|
||||||
|
|
||||||
@ -95,7 +92,7 @@ make_operand(char *opname,
|
|||||||
* This is where some type conversion happens.
|
* This is where some type conversion happens.
|
||||||
*/
|
*/
|
||||||
Expr *
|
Expr *
|
||||||
make_op(char *opname, Node *ltree, Node *rtree)
|
make_op(List *opname, Node *ltree, Node *rtree)
|
||||||
{
|
{
|
||||||
Oid ltypeId,
|
Oid ltypeId,
|
||||||
rtypeId;
|
rtypeId;
|
||||||
@ -114,7 +111,7 @@ make_op(char *opname, Node *ltree, Node *rtree)
|
|||||||
{
|
{
|
||||||
tup = right_oper(opname, ltypeId);
|
tup = right_oper(opname, ltypeId);
|
||||||
opform = (Form_pg_operator) GETSTRUCT(tup);
|
opform = (Form_pg_operator) GETSTRUCT(tup);
|
||||||
left = make_operand(opname, ltree, ltypeId, opform->oprleft);
|
left = make_operand(ltree, ltypeId, opform->oprleft);
|
||||||
right = NULL;
|
right = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -123,7 +120,7 @@ make_op(char *opname, Node *ltree, Node *rtree)
|
|||||||
{
|
{
|
||||||
tup = left_oper(opname, rtypeId);
|
tup = left_oper(opname, rtypeId);
|
||||||
opform = (Form_pg_operator) GETSTRUCT(tup);
|
opform = (Form_pg_operator) GETSTRUCT(tup);
|
||||||
right = make_operand(opname, rtree, rtypeId, opform->oprright);
|
right = make_operand(rtree, rtypeId, opform->oprright);
|
||||||
left = NULL;
|
left = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -132,8 +129,8 @@ make_op(char *opname, Node *ltree, Node *rtree)
|
|||||||
{
|
{
|
||||||
tup = oper(opname, ltypeId, rtypeId, false);
|
tup = oper(opname, ltypeId, rtypeId, false);
|
||||||
opform = (Form_pg_operator) GETSTRUCT(tup);
|
opform = (Form_pg_operator) GETSTRUCT(tup);
|
||||||
left = make_operand(opname, ltree, ltypeId, opform->oprleft);
|
left = make_operand(ltree, ltypeId, opform->oprleft);
|
||||||
right = make_operand(opname, rtree, rtypeId, opform->oprright);
|
right = make_operand(rtree, rtypeId, opform->oprright);
|
||||||
}
|
}
|
||||||
|
|
||||||
newop = makeOper(oprid(tup), /* opno */
|
newop = makeOper(oprid(tup), /* opno */
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_oper.c,v 1.54 2002/04/11 20:00:02 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/parser/parse_oper.c,v 1.55 2002/04/16 23:08:11 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -19,6 +19,7 @@
|
|||||||
#include "access/heapam.h"
|
#include "access/heapam.h"
|
||||||
#include "catalog/catname.h"
|
#include "catalog/catname.h"
|
||||||
#include "catalog/indexing.h"
|
#include "catalog/indexing.h"
|
||||||
|
#include "catalog/namespace.h"
|
||||||
#include "catalog/pg_operator.h"
|
#include "catalog/pg_operator.h"
|
||||||
#include "parser/parse_coerce.h"
|
#include "parser/parse_coerce.h"
|
||||||
#include "parser/parse_func.h"
|
#include "parser/parse_func.h"
|
||||||
@ -28,17 +29,106 @@
|
|||||||
#include "utils/fmgroids.h"
|
#include "utils/fmgroids.h"
|
||||||
#include "utils/syscache.h"
|
#include "utils/syscache.h"
|
||||||
|
|
||||||
static Oid *oper_select_candidate(int nargs, Oid *input_typeids,
|
static Oid binary_oper_exact(Oid arg1, Oid arg2,
|
||||||
CandidateList candidates);
|
FuncCandidateList candidates);
|
||||||
static Operator oper_exact(char *op, Oid arg1, Oid arg2);
|
static Oid oper_select_candidate(int nargs, Oid *input_typeids,
|
||||||
static Operator oper_inexact(char *op, Oid arg1, Oid arg2);
|
FuncCandidateList candidates);
|
||||||
static int binary_oper_get_candidates(char *opname,
|
static void op_error(List *op, Oid arg1, Oid arg2);
|
||||||
CandidateList *candidates);
|
static void unary_op_error(List *op, Oid arg, bool is_left_op);
|
||||||
static int unary_oper_get_candidates(char *opname,
|
|
||||||
CandidateList *candidates,
|
|
||||||
char rightleft);
|
/*
|
||||||
static void op_error(char *op, Oid arg1, Oid arg2);
|
* LookupOperName
|
||||||
static void unary_op_error(char *op, Oid arg, bool is_left_op);
|
* Given a possibly-qualified operator name and exact input datatypes,
|
||||||
|
* look up the operator. Returns InvalidOid if no such operator.
|
||||||
|
*
|
||||||
|
* Pass oprleft = InvalidOid for a prefix op, oprright = InvalidOid for
|
||||||
|
* a postfix op.
|
||||||
|
*
|
||||||
|
* If the operator name is not schema-qualified, it is sought in the current
|
||||||
|
* namespace search path.
|
||||||
|
*/
|
||||||
|
Oid
|
||||||
|
LookupOperName(List *opername, Oid oprleft, Oid oprright)
|
||||||
|
{
|
||||||
|
FuncCandidateList clist;
|
||||||
|
char oprkind;
|
||||||
|
|
||||||
|
if (!OidIsValid(oprleft))
|
||||||
|
oprkind = 'l';
|
||||||
|
else if (!OidIsValid(oprright))
|
||||||
|
oprkind = 'r';
|
||||||
|
else
|
||||||
|
oprkind = 'b';
|
||||||
|
|
||||||
|
clist = OpernameGetCandidates(opername, oprkind);
|
||||||
|
|
||||||
|
while (clist)
|
||||||
|
{
|
||||||
|
if (clist->args[0] == oprleft && clist->args[1] == oprright)
|
||||||
|
return clist->oid;
|
||||||
|
clist = clist->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return InvalidOid;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* LookupOperNameTypeNames
|
||||||
|
* Like LookupOperName, but the argument types are specified by
|
||||||
|
* TypeName nodes. Also, if we fail to find the operator
|
||||||
|
* and caller is not NULL, then an error is reported.
|
||||||
|
*
|
||||||
|
* Pass oprleft = NULL for a prefix op, oprright = NULL for a postfix op.
|
||||||
|
*/
|
||||||
|
Oid
|
||||||
|
LookupOperNameTypeNames(List *opername, TypeName *oprleft,
|
||||||
|
TypeName *oprright, const char *caller)
|
||||||
|
{
|
||||||
|
Oid operoid;
|
||||||
|
Oid leftoid,
|
||||||
|
rightoid;
|
||||||
|
|
||||||
|
if (oprleft == NULL)
|
||||||
|
leftoid = InvalidOid;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
leftoid = LookupTypeName(oprleft);
|
||||||
|
if (!OidIsValid(leftoid))
|
||||||
|
elog(ERROR, "Type \"%s\" does not exist",
|
||||||
|
TypeNameToString(oprleft));
|
||||||
|
}
|
||||||
|
if (oprright == NULL)
|
||||||
|
rightoid = InvalidOid;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rightoid = LookupTypeName(oprright);
|
||||||
|
if (!OidIsValid(rightoid))
|
||||||
|
elog(ERROR, "Type \"%s\" does not exist",
|
||||||
|
TypeNameToString(oprright));
|
||||||
|
}
|
||||||
|
|
||||||
|
operoid = LookupOperName(opername, leftoid, rightoid);
|
||||||
|
|
||||||
|
if (!OidIsValid(operoid) && caller != NULL)
|
||||||
|
{
|
||||||
|
if (oprleft == NULL)
|
||||||
|
elog(ERROR, "%s: Prefix operator '%s' for type '%s' does not exist",
|
||||||
|
caller, NameListToString(opername),
|
||||||
|
TypeNameToString(oprright));
|
||||||
|
else if (oprright == NULL)
|
||||||
|
elog(ERROR, "%s: Postfix operator '%s' for type '%s' does not exist",
|
||||||
|
caller, NameListToString(opername),
|
||||||
|
TypeNameToString(oprleft));
|
||||||
|
else
|
||||||
|
elog(ERROR, "%s: Operator '%s' for types '%s' and '%s' does not exist",
|
||||||
|
caller, NameListToString(opername),
|
||||||
|
TypeNameToString(oprleft),
|
||||||
|
TypeNameToString(oprright));
|
||||||
|
}
|
||||||
|
|
||||||
|
return operoid;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Select an ordering operator for the given datatype */
|
/* Select an ordering operator for the given datatype */
|
||||||
@ -47,7 +137,8 @@ any_ordering_op(Oid argtype)
|
|||||||
{
|
{
|
||||||
Oid order_opid;
|
Oid order_opid;
|
||||||
|
|
||||||
order_opid = compatible_oper_opid("<", argtype, argtype, true);
|
order_opid = compatible_oper_opid(makeList1(makeString("<")),
|
||||||
|
argtype, argtype, true);
|
||||||
if (!OidIsValid(order_opid))
|
if (!OidIsValid(order_opid))
|
||||||
elog(ERROR, "Unable to identify an ordering operator '%s' for type '%s'"
|
elog(ERROR, "Unable to identify an ordering operator '%s' for type '%s'"
|
||||||
"\n\tUse an explicit ordering operator or modify the query",
|
"\n\tUse an explicit ordering operator or modify the query",
|
||||||
@ -72,116 +163,32 @@ oprfuncid(Operator op)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* binary_oper_get_candidates()
|
/* binary_oper_exact()
|
||||||
* given opname, find all possible input type pairs for which an operator
|
* Check for an "exact" match to the specified operand types.
|
||||||
* named opname exists.
|
*
|
||||||
* Build a list of the candidate input types.
|
* If one operand is an unknown literal, assume it should be taken to be
|
||||||
* Returns number of candidates found.
|
* the same type as the other operand for this purpose.
|
||||||
*/
|
*/
|
||||||
static int
|
static Oid
|
||||||
binary_oper_get_candidates(char *opname,
|
binary_oper_exact(Oid arg1, Oid arg2,
|
||||||
CandidateList *candidates)
|
FuncCandidateList candidates)
|
||||||
{
|
{
|
||||||
Relation pg_operator_desc;
|
/* Unspecified type for one of the arguments? then use the other */
|
||||||
SysScanDesc pg_operator_scan;
|
if ((arg1 == UNKNOWNOID) && (arg2 != InvalidOid))
|
||||||
HeapTuple tup;
|
arg1 = arg2;
|
||||||
int ncandidates = 0;
|
else if ((arg2 == UNKNOWNOID) && (arg1 != InvalidOid))
|
||||||
ScanKeyData opKey[1];
|
arg2 = arg1;
|
||||||
|
|
||||||
*candidates = NULL;
|
while (candidates != NULL)
|
||||||
|
|
||||||
ScanKeyEntryInitialize(&opKey[0], 0,
|
|
||||||
Anum_pg_operator_oprname,
|
|
||||||
F_NAMEEQ,
|
|
||||||
NameGetDatum(opname));
|
|
||||||
|
|
||||||
pg_operator_desc = heap_openr(OperatorRelationName, AccessShareLock);
|
|
||||||
pg_operator_scan = systable_beginscan(pg_operator_desc,
|
|
||||||
OperatorNameIndex, true,
|
|
||||||
SnapshotNow,
|
|
||||||
1, opKey);
|
|
||||||
|
|
||||||
while (HeapTupleIsValid(tup = systable_getnext(pg_operator_scan)))
|
|
||||||
{
|
{
|
||||||
Form_pg_operator oper = (Form_pg_operator) GETSTRUCT(tup);
|
if (arg1 == candidates->args[0] &&
|
||||||
|
arg2 == candidates->args[1])
|
||||||
if (oper->oprkind == 'b')
|
return candidates->oid;
|
||||||
{
|
candidates = candidates->next;
|
||||||
CandidateList current_candidate;
|
|
||||||
|
|
||||||
current_candidate = (CandidateList) palloc(sizeof(struct _CandidateList));
|
|
||||||
current_candidate->args = (Oid *) palloc(2 * sizeof(Oid));
|
|
||||||
|
|
||||||
current_candidate->args[0] = oper->oprleft;
|
|
||||||
current_candidate->args[1] = oper->oprright;
|
|
||||||
current_candidate->next = *candidates;
|
|
||||||
*candidates = current_candidate;
|
|
||||||
ncandidates++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
systable_endscan(pg_operator_scan);
|
return InvalidOid;
|
||||||
heap_close(pg_operator_desc, AccessShareLock);
|
}
|
||||||
|
|
||||||
return ncandidates;
|
|
||||||
} /* binary_oper_get_candidates() */
|
|
||||||
|
|
||||||
/* unary_oper_get_candidates()
|
|
||||||
* given opname, find all possible types for which
|
|
||||||
* a right/left unary operator named opname exists.
|
|
||||||
* Build a list of the candidate input types.
|
|
||||||
* Returns number of candidates found.
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
unary_oper_get_candidates(char *opname,
|
|
||||||
CandidateList *candidates,
|
|
||||||
char rightleft)
|
|
||||||
{
|
|
||||||
Relation pg_operator_desc;
|
|
||||||
SysScanDesc pg_operator_scan;
|
|
||||||
HeapTuple tup;
|
|
||||||
int ncandidates = 0;
|
|
||||||
ScanKeyData opKey[1];
|
|
||||||
|
|
||||||
*candidates = NULL;
|
|
||||||
|
|
||||||
ScanKeyEntryInitialize(&opKey[0], 0,
|
|
||||||
Anum_pg_operator_oprname,
|
|
||||||
F_NAMEEQ,
|
|
||||||
NameGetDatum(opname));
|
|
||||||
|
|
||||||
pg_operator_desc = heap_openr(OperatorRelationName, AccessShareLock);
|
|
||||||
pg_operator_scan = systable_beginscan(pg_operator_desc,
|
|
||||||
OperatorNameIndex, true,
|
|
||||||
SnapshotNow,
|
|
||||||
1, opKey);
|
|
||||||
|
|
||||||
while (HeapTupleIsValid(tup = systable_getnext(pg_operator_scan)))
|
|
||||||
{
|
|
||||||
Form_pg_operator oper = (Form_pg_operator) GETSTRUCT(tup);
|
|
||||||
|
|
||||||
if (oper->oprkind == rightleft)
|
|
||||||
{
|
|
||||||
CandidateList current_candidate;
|
|
||||||
|
|
||||||
current_candidate = (CandidateList) palloc(sizeof(struct _CandidateList));
|
|
||||||
current_candidate->args = (Oid *) palloc(sizeof(Oid));
|
|
||||||
|
|
||||||
if (rightleft == 'r')
|
|
||||||
current_candidate->args[0] = oper->oprleft;
|
|
||||||
else
|
|
||||||
current_candidate->args[0] = oper->oprright;
|
|
||||||
current_candidate->next = *candidates;
|
|
||||||
*candidates = current_candidate;
|
|
||||||
ncandidates++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
systable_endscan(pg_operator_scan);
|
|
||||||
heap_close(pg_operator_desc, AccessShareLock);
|
|
||||||
|
|
||||||
return ncandidates;
|
|
||||||
} /* unary_oper_get_candidates() */
|
|
||||||
|
|
||||||
|
|
||||||
/* oper_select_candidate()
|
/* oper_select_candidate()
|
||||||
@ -234,13 +241,13 @@ unary_oper_get_candidates(char *opname,
|
|||||||
* some sense. (see equivalentOpersAfterPromotion for details.)
|
* some sense. (see equivalentOpersAfterPromotion for details.)
|
||||||
* - ay 6/95
|
* - ay 6/95
|
||||||
*/
|
*/
|
||||||
static Oid *
|
static Oid
|
||||||
oper_select_candidate(int nargs,
|
oper_select_candidate(int nargs,
|
||||||
Oid *input_typeids,
|
Oid *input_typeids,
|
||||||
CandidateList candidates)
|
FuncCandidateList candidates)
|
||||||
{
|
{
|
||||||
CandidateList current_candidate;
|
FuncCandidateList current_candidate;
|
||||||
CandidateList last_candidate;
|
FuncCandidateList last_candidate;
|
||||||
Oid *current_typeids;
|
Oid *current_typeids;
|
||||||
Oid current_type;
|
Oid current_type;
|
||||||
int unknownOids;
|
int unknownOids;
|
||||||
@ -289,9 +296,9 @@ oper_select_candidate(int nargs,
|
|||||||
|
|
||||||
/* Done if no candidate or only one candidate survives */
|
/* Done if no candidate or only one candidate survives */
|
||||||
if (ncandidates == 0)
|
if (ncandidates == 0)
|
||||||
return NULL;
|
return InvalidOid;
|
||||||
if (ncandidates == 1)
|
if (ncandidates == 1)
|
||||||
return candidates->args;
|
return candidates->oid;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Run through all candidates and keep those with the most matches on
|
* Run through all candidates and keep those with the most matches on
|
||||||
@ -335,7 +342,7 @@ oper_select_candidate(int nargs,
|
|||||||
last_candidate->next = NULL;
|
last_candidate->next = NULL;
|
||||||
|
|
||||||
if (ncandidates == 1)
|
if (ncandidates == 1)
|
||||||
return candidates->args;
|
return candidates->oid;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Still too many candidates? Run through all candidates and keep
|
* Still too many candidates? Run through all candidates and keep
|
||||||
@ -382,7 +389,7 @@ oper_select_candidate(int nargs,
|
|||||||
last_candidate->next = NULL;
|
last_candidate->next = NULL;
|
||||||
|
|
||||||
if (ncandidates == 1)
|
if (ncandidates == 1)
|
||||||
return candidates->args;
|
return candidates->oid;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Still too many candidates? Now look for candidates which are
|
* Still too many candidates? Now look for candidates which are
|
||||||
@ -428,7 +435,7 @@ oper_select_candidate(int nargs,
|
|||||||
last_candidate->next = NULL;
|
last_candidate->next = NULL;
|
||||||
|
|
||||||
if (ncandidates == 1)
|
if (ncandidates == 1)
|
||||||
return candidates->args;
|
return candidates->oid;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Still too many candidates? Try assigning types for the unknown
|
* Still too many candidates? Try assigning types for the unknown
|
||||||
@ -467,7 +474,7 @@ oper_select_candidate(int nargs,
|
|||||||
nmatch++;
|
nmatch++;
|
||||||
}
|
}
|
||||||
if (nmatch == nargs)
|
if (nmatch == nargs)
|
||||||
return current_typeids;
|
return current_candidate->oid;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -602,87 +609,12 @@ oper_select_candidate(int nargs,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (ncandidates == 1)
|
if (ncandidates == 1)
|
||||||
return candidates->args;
|
return candidates->oid;
|
||||||
|
|
||||||
return NULL; /* failed to determine a unique candidate */
|
return InvalidOid; /* failed to determine a unique candidate */
|
||||||
} /* oper_select_candidate() */
|
} /* oper_select_candidate() */
|
||||||
|
|
||||||
|
|
||||||
/* oper_exact()
|
|
||||||
* Given operator, types of arg1 and arg2, return oper struct or NULL.
|
|
||||||
*
|
|
||||||
* NOTE: on success, the returned object is a syscache entry. The caller
|
|
||||||
* must ReleaseSysCache() the entry when done with it.
|
|
||||||
*/
|
|
||||||
static Operator
|
|
||||||
oper_exact(char *op, Oid arg1, Oid arg2)
|
|
||||||
{
|
|
||||||
HeapTuple tup;
|
|
||||||
|
|
||||||
/* Unspecified type for one of the arguments? then use the other */
|
|
||||||
if ((arg1 == UNKNOWNOID) && (arg2 != InvalidOid))
|
|
||||||
arg1 = arg2;
|
|
||||||
else if ((arg2 == UNKNOWNOID) && (arg1 != InvalidOid))
|
|
||||||
arg2 = arg1;
|
|
||||||
|
|
||||||
tup = SearchSysCache(OPERNAME,
|
|
||||||
PointerGetDatum(op),
|
|
||||||
ObjectIdGetDatum(arg1),
|
|
||||||
ObjectIdGetDatum(arg2),
|
|
||||||
CharGetDatum('b'));
|
|
||||||
|
|
||||||
return (Operator) tup;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* oper_inexact()
|
|
||||||
* Given operator, types of arg1 and arg2, return oper struct or NULL.
|
|
||||||
*
|
|
||||||
* NOTE: on success, the returned object is a syscache entry. The caller
|
|
||||||
* must ReleaseSysCache() the entry when done with it.
|
|
||||||
*/
|
|
||||||
static Operator
|
|
||||||
oper_inexact(char *op, Oid arg1, Oid arg2)
|
|
||||||
{
|
|
||||||
HeapTuple tup;
|
|
||||||
CandidateList candidates;
|
|
||||||
int ncandidates;
|
|
||||||
Oid *targetOids;
|
|
||||||
Oid inputOids[2];
|
|
||||||
|
|
||||||
/* Unspecified type for one of the arguments? then use the other */
|
|
||||||
if (arg2 == InvalidOid)
|
|
||||||
arg2 = arg1;
|
|
||||||
if (arg1 == InvalidOid)
|
|
||||||
arg1 = arg2;
|
|
||||||
|
|
||||||
ncandidates = binary_oper_get_candidates(op, &candidates);
|
|
||||||
|
|
||||||
/* No operators found? Then return null... */
|
|
||||||
if (ncandidates == 0)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Otherwise, check for compatible datatypes, and then try to resolve
|
|
||||||
* the conflict if more than one candidate remains.
|
|
||||||
*/
|
|
||||||
inputOids[0] = arg1;
|
|
||||||
inputOids[1] = arg2;
|
|
||||||
targetOids = oper_select_candidate(2, inputOids, candidates);
|
|
||||||
if (targetOids != NULL)
|
|
||||||
{
|
|
||||||
tup = SearchSysCache(OPERNAME,
|
|
||||||
PointerGetDatum(op),
|
|
||||||
ObjectIdGetDatum(targetOids[0]),
|
|
||||||
ObjectIdGetDatum(targetOids[1]),
|
|
||||||
CharGetDatum('b'));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
tup = NULL;
|
|
||||||
return (Operator) tup;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* oper() -- search for a binary operator
|
/* oper() -- search for a binary operator
|
||||||
* Given operator name, types of arg1 and arg2, return oper struct.
|
* Given operator name, types of arg1 and arg2, return oper struct.
|
||||||
*
|
*
|
||||||
@ -697,22 +629,48 @@ oper_inexact(char *op, Oid arg1, Oid arg2)
|
|||||||
* must ReleaseSysCache() the entry when done with it.
|
* must ReleaseSysCache() the entry when done with it.
|
||||||
*/
|
*/
|
||||||
Operator
|
Operator
|
||||||
oper(char *opname, Oid ltypeId, Oid rtypeId, bool noError)
|
oper(List *opname, Oid ltypeId, Oid rtypeId, bool noError)
|
||||||
{
|
{
|
||||||
HeapTuple tup;
|
FuncCandidateList clist;
|
||||||
|
Oid operOid;
|
||||||
|
Oid inputOids[2];
|
||||||
|
HeapTuple tup = NULL;
|
||||||
|
|
||||||
/* check for exact match on this operator... */
|
/* Get binary operators of given name */
|
||||||
if (HeapTupleIsValid(tup = oper_exact(opname, ltypeId, rtypeId)))
|
clist = OpernameGetCandidates(opname, 'b');
|
||||||
return (Operator) tup;
|
|
||||||
|
|
||||||
/* try to find a match on likely candidates... */
|
/* No operators found? Then fail... */
|
||||||
if (HeapTupleIsValid(tup = oper_inexact(opname, ltypeId, rtypeId)))
|
if (clist != NULL)
|
||||||
return (Operator) tup;
|
{
|
||||||
|
/*
|
||||||
|
* Check for an "exact" match.
|
||||||
|
*/
|
||||||
|
operOid = binary_oper_exact(ltypeId, rtypeId, clist);
|
||||||
|
if (!OidIsValid(operOid))
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Otherwise, search for the most suitable candidate.
|
||||||
|
*/
|
||||||
|
|
||||||
if (!noError)
|
/* Unspecified type for one of the arguments? then use the other */
|
||||||
|
if (rtypeId == InvalidOid)
|
||||||
|
rtypeId = ltypeId;
|
||||||
|
else if (ltypeId == InvalidOid)
|
||||||
|
ltypeId = rtypeId;
|
||||||
|
inputOids[0] = ltypeId;
|
||||||
|
inputOids[1] = rtypeId;
|
||||||
|
operOid = oper_select_candidate(2, inputOids, clist);
|
||||||
|
}
|
||||||
|
if (OidIsValid(operOid))
|
||||||
|
tup = SearchSysCache(OPEROID,
|
||||||
|
ObjectIdGetDatum(operOid),
|
||||||
|
0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!HeapTupleIsValid(tup) && !noError)
|
||||||
op_error(opname, ltypeId, rtypeId);
|
op_error(opname, ltypeId, rtypeId);
|
||||||
|
|
||||||
return (Operator) NULL;
|
return (Operator) tup;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* compatible_oper()
|
/* compatible_oper()
|
||||||
@ -723,7 +681,7 @@ oper(char *opname, Oid ltypeId, Oid rtypeId, bool noError)
|
|||||||
* are accepted). Otherwise, the semantics are the same.
|
* are accepted). Otherwise, the semantics are the same.
|
||||||
*/
|
*/
|
||||||
Operator
|
Operator
|
||||||
compatible_oper(char *op, Oid arg1, Oid arg2, bool noError)
|
compatible_oper(List *op, Oid arg1, Oid arg2, bool noError)
|
||||||
{
|
{
|
||||||
Operator optup;
|
Operator optup;
|
||||||
Form_pg_operator opform;
|
Form_pg_operator opform;
|
||||||
@ -755,7 +713,7 @@ compatible_oper(char *op, Oid arg1, Oid arg2, bool noError)
|
|||||||
* lookup fails and noError is true.
|
* lookup fails and noError is true.
|
||||||
*/
|
*/
|
||||||
Oid
|
Oid
|
||||||
compatible_oper_opid(char *op, Oid arg1, Oid arg2, bool noError)
|
compatible_oper_opid(List *op, Oid arg1, Oid arg2, bool noError)
|
||||||
{
|
{
|
||||||
Operator optup;
|
Operator optup;
|
||||||
Oid result;
|
Oid result;
|
||||||
@ -777,7 +735,7 @@ compatible_oper_opid(char *op, Oid arg1, Oid arg2, bool noError)
|
|||||||
* lookup fails and noError is true.
|
* lookup fails and noError is true.
|
||||||
*/
|
*/
|
||||||
Oid
|
Oid
|
||||||
compatible_oper_funcid(char *op, Oid arg1, Oid arg2, bool noError)
|
compatible_oper_funcid(List *op, Oid arg1, Oid arg2, bool noError)
|
||||||
{
|
{
|
||||||
Operator optup;
|
Operator optup;
|
||||||
Oid result;
|
Oid result;
|
||||||
@ -805,46 +763,50 @@ compatible_oper_funcid(char *op, Oid arg1, Oid arg2, bool noError)
|
|||||||
* must ReleaseSysCache() the entry when done with it.
|
* must ReleaseSysCache() the entry when done with it.
|
||||||
*/
|
*/
|
||||||
Operator
|
Operator
|
||||||
right_oper(char *op, Oid arg)
|
right_oper(List *op, Oid arg)
|
||||||
{
|
{
|
||||||
HeapTuple tup;
|
FuncCandidateList clist;
|
||||||
CandidateList candidates;
|
Oid operOid = InvalidOid;
|
||||||
int ncandidates;
|
HeapTuple tup = NULL;
|
||||||
Oid *targetOid;
|
|
||||||
|
|
||||||
/* Try for exact match */
|
/* Find candidates */
|
||||||
tup = SearchSysCache(OPERNAME,
|
clist = OpernameGetCandidates(op, 'r');
|
||||||
PointerGetDatum(op),
|
|
||||||
ObjectIdGetDatum(arg),
|
|
||||||
ObjectIdGetDatum(InvalidOid),
|
|
||||||
CharGetDatum('r'));
|
|
||||||
|
|
||||||
if (!HeapTupleIsValid(tup))
|
if (clist != NULL)
|
||||||
{
|
{
|
||||||
/* Try for inexact matches */
|
/*
|
||||||
ncandidates = unary_oper_get_candidates(op, &candidates, 'r');
|
* First, quickly check to see if there is an exactly matching
|
||||||
if (ncandidates == 0)
|
* operator (there can be only one such entry in the list).
|
||||||
unary_op_error(op, arg, FALSE);
|
*/
|
||||||
else
|
FuncCandidateList clisti;
|
||||||
|
|
||||||
|
for (clisti = clist; clisti != NULL; clisti = clisti->next)
|
||||||
|
{
|
||||||
|
if (arg == clisti->args[0])
|
||||||
|
{
|
||||||
|
operOid = clisti->oid;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!OidIsValid(operOid))
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* We must run oper_select_candidate even if only one
|
* We must run oper_select_candidate even if only one
|
||||||
* candidate, otherwise we may falsely return a
|
* candidate, otherwise we may falsely return a
|
||||||
* non-type-compatible operator.
|
* non-type-compatible operator.
|
||||||
*/
|
*/
|
||||||
targetOid = oper_select_candidate(1, &arg, candidates);
|
operOid = oper_select_candidate(1, &arg, clist);
|
||||||
if (targetOid != NULL)
|
|
||||||
tup = SearchSysCache(OPERNAME,
|
|
||||||
PointerGetDatum(op),
|
|
||||||
ObjectIdGetDatum(targetOid[0]),
|
|
||||||
ObjectIdGetDatum(InvalidOid),
|
|
||||||
CharGetDatum('r'));
|
|
||||||
}
|
}
|
||||||
|
if (OidIsValid(operOid))
|
||||||
if (!HeapTupleIsValid(tup))
|
tup = SearchSysCache(OPEROID,
|
||||||
unary_op_error(op, arg, FALSE);
|
ObjectIdGetDatum(operOid),
|
||||||
|
0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!HeapTupleIsValid(tup))
|
||||||
|
unary_op_error(op, arg, FALSE);
|
||||||
|
|
||||||
return (Operator) tup;
|
return (Operator) tup;
|
||||||
} /* right_oper() */
|
} /* right_oper() */
|
||||||
|
|
||||||
@ -861,46 +823,55 @@ right_oper(char *op, Oid arg)
|
|||||||
* must ReleaseSysCache() the entry when done with it.
|
* must ReleaseSysCache() the entry when done with it.
|
||||||
*/
|
*/
|
||||||
Operator
|
Operator
|
||||||
left_oper(char *op, Oid arg)
|
left_oper(List *op, Oid arg)
|
||||||
{
|
{
|
||||||
HeapTuple tup;
|
FuncCandidateList clist;
|
||||||
CandidateList candidates;
|
Oid operOid = InvalidOid;
|
||||||
int ncandidates;
|
HeapTuple tup = NULL;
|
||||||
Oid *targetOid;
|
|
||||||
|
|
||||||
/* Try for exact match */
|
/* Find candidates */
|
||||||
tup = SearchSysCache(OPERNAME,
|
clist = OpernameGetCandidates(op, 'l');
|
||||||
PointerGetDatum(op),
|
|
||||||
ObjectIdGetDatum(InvalidOid),
|
|
||||||
ObjectIdGetDatum(arg),
|
|
||||||
CharGetDatum('l'));
|
|
||||||
|
|
||||||
if (!HeapTupleIsValid(tup))
|
if (clist != NULL)
|
||||||
{
|
{
|
||||||
/* Try for inexact matches */
|
/*
|
||||||
ncandidates = unary_oper_get_candidates(op, &candidates, 'l');
|
* First, quickly check to see if there is an exactly matching
|
||||||
if (ncandidates == 0)
|
* operator (there can be only one such entry in the list).
|
||||||
unary_op_error(op, arg, TRUE);
|
*
|
||||||
else
|
* The returned list has args in the form (0, oprright). Move the
|
||||||
|
* useful data into args[0] to keep oper_select_candidate simple.
|
||||||
|
* XXX we are assuming here that we may scribble on the list!
|
||||||
|
*/
|
||||||
|
FuncCandidateList clisti;
|
||||||
|
|
||||||
|
for (clisti = clist; clisti != NULL; clisti = clisti->next)
|
||||||
|
{
|
||||||
|
clisti->args[0] = clisti->args[1];
|
||||||
|
if (arg == clisti->args[0])
|
||||||
|
{
|
||||||
|
operOid = clisti->oid;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!OidIsValid(operOid))
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* We must run oper_select_candidate even if only one
|
* We must run oper_select_candidate even if only one
|
||||||
* candidate, otherwise we may falsely return a
|
* candidate, otherwise we may falsely return a
|
||||||
* non-type-compatible operator.
|
* non-type-compatible operator.
|
||||||
*/
|
*/
|
||||||
targetOid = oper_select_candidate(1, &arg, candidates);
|
operOid = oper_select_candidate(1, &arg, clist);
|
||||||
if (targetOid != NULL)
|
|
||||||
tup = SearchSysCache(OPERNAME,
|
|
||||||
PointerGetDatum(op),
|
|
||||||
ObjectIdGetDatum(InvalidOid),
|
|
||||||
ObjectIdGetDatum(targetOid[0]),
|
|
||||||
CharGetDatum('l'));
|
|
||||||
}
|
}
|
||||||
|
if (OidIsValid(operOid))
|
||||||
if (!HeapTupleIsValid(tup))
|
tup = SearchSysCache(OPEROID,
|
||||||
unary_op_error(op, arg, TRUE);
|
ObjectIdGetDatum(operOid),
|
||||||
|
0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!HeapTupleIsValid(tup))
|
||||||
|
unary_op_error(op, arg, TRUE);
|
||||||
|
|
||||||
return (Operator) tup;
|
return (Operator) tup;
|
||||||
} /* left_oper() */
|
} /* left_oper() */
|
||||||
|
|
||||||
@ -910,19 +881,22 @@ left_oper(char *op, Oid arg)
|
|||||||
* is not found.
|
* is not found.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
op_error(char *op, Oid arg1, Oid arg2)
|
op_error(List *op, Oid arg1, Oid arg2)
|
||||||
{
|
{
|
||||||
if (!typeidIsValid(arg1))
|
if (!typeidIsValid(arg1))
|
||||||
elog(ERROR, "Left hand side of operator '%s' has an unknown type"
|
elog(ERROR, "Left hand side of operator '%s' has an unknown type"
|
||||||
"\n\tProbably a bad attribute name", op);
|
"\n\tProbably a bad attribute name",
|
||||||
|
NameListToString(op));
|
||||||
|
|
||||||
if (!typeidIsValid(arg2))
|
if (!typeidIsValid(arg2))
|
||||||
elog(ERROR, "Right hand side of operator %s has an unknown type"
|
elog(ERROR, "Right hand side of operator %s has an unknown type"
|
||||||
"\n\tProbably a bad attribute name", op);
|
"\n\tProbably a bad attribute name",
|
||||||
|
NameListToString(op));
|
||||||
|
|
||||||
elog(ERROR, "Unable to identify an operator '%s' for types '%s' and '%s'"
|
elog(ERROR, "Unable to identify an operator '%s' for types '%s' and '%s'"
|
||||||
"\n\tYou will have to retype this query using an explicit cast",
|
"\n\tYou will have to retype this query using an explicit cast",
|
||||||
op, format_type_be(arg1), format_type_be(arg2));
|
NameListToString(op),
|
||||||
|
format_type_be(arg1), format_type_be(arg2));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* unary_op_error()
|
/* unary_op_error()
|
||||||
@ -930,28 +904,28 @@ op_error(char *op, Oid arg1, Oid arg2)
|
|||||||
* is not found.
|
* is not found.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
unary_op_error(char *op, Oid arg, bool is_left_op)
|
unary_op_error(List *op, Oid arg, bool is_left_op)
|
||||||
{
|
{
|
||||||
if (!typeidIsValid(arg))
|
if (!typeidIsValid(arg))
|
||||||
{
|
{
|
||||||
if (is_left_op)
|
if (is_left_op)
|
||||||
elog(ERROR, "operand of prefix operator '%s' has an unknown type"
|
elog(ERROR, "operand of prefix operator '%s' has an unknown type"
|
||||||
"\n\t(probably an invalid column reference)",
|
"\n\t(probably an invalid column reference)",
|
||||||
op);
|
NameListToString(op));
|
||||||
else
|
else
|
||||||
elog(ERROR, "operand of postfix operator '%s' has an unknown type"
|
elog(ERROR, "operand of postfix operator '%s' has an unknown type"
|
||||||
"\n\t(probably an invalid column reference)",
|
"\n\t(probably an invalid column reference)",
|
||||||
op);
|
NameListToString(op));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (is_left_op)
|
if (is_left_op)
|
||||||
elog(ERROR, "Unable to identify a prefix operator '%s' for type '%s'"
|
elog(ERROR, "Unable to identify a prefix operator '%s' for type '%s'"
|
||||||
"\n\tYou may need to add parentheses or an explicit cast",
|
"\n\tYou may need to add parentheses or an explicit cast",
|
||||||
op, format_type_be(arg));
|
NameListToString(op), format_type_be(arg));
|
||||||
else
|
else
|
||||||
elog(ERROR, "Unable to identify a postfix operator '%s' for type '%s'"
|
elog(ERROR, "Unable to identify a postfix operator '%s' for type '%s'"
|
||||||
"\n\tYou may need to add parentheses or an explicit cast",
|
"\n\tYou may need to add parentheses or an explicit cast",
|
||||||
op, format_type_be(arg));
|
NameListToString(op), format_type_be(arg));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
* Portions Copyright (c) 2000-2001, PostgreSQL Global Development Group
|
* Portions Copyright (c) 2000-2001, PostgreSQL Global Development Group
|
||||||
* Copyright 1999 Jan Wieck
|
* Copyright 1999 Jan Wieck
|
||||||
*
|
*
|
||||||
* $Header: /cvsroot/pgsql/src/backend/utils/adt/ri_triggers.c,v 1.36 2002/04/02 01:03:07 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/utils/adt/ri_triggers.c,v 1.37 2002/04/16 23:08:11 tgl Exp $
|
||||||
*
|
*
|
||||||
* ----------
|
* ----------
|
||||||
*/
|
*/
|
||||||
@ -36,6 +36,7 @@
|
|||||||
#include "catalog/pg_operator.h"
|
#include "catalog/pg_operator.h"
|
||||||
#include "commands/trigger.h"
|
#include "commands/trigger.h"
|
||||||
#include "executor/spi_priv.h"
|
#include "executor/spi_priv.h"
|
||||||
|
#include "parser/parse_oper.h"
|
||||||
#include "utils/lsyscache.h"
|
#include "utils/lsyscache.h"
|
||||||
#include "miscadmin.h"
|
#include "miscadmin.h"
|
||||||
|
|
||||||
@ -3338,27 +3339,20 @@ ri_AttributesEqual(Oid typeid, Datum oldvalue, Datum newvalue)
|
|||||||
HASH_FIND, NULL);
|
HASH_FIND, NULL);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If not found, lookup the OPERNAME system cache for it to get the
|
* If not found, lookup the operator, then do the function manager
|
||||||
* func OID, then do the function manager lookup, and remember that
|
* lookup, and remember that info.
|
||||||
* info.
|
|
||||||
*/
|
*/
|
||||||
if (!entry)
|
if (!entry)
|
||||||
{
|
{
|
||||||
HeapTuple opr_tup;
|
|
||||||
Oid opr_proc;
|
Oid opr_proc;
|
||||||
FmgrInfo finfo;
|
FmgrInfo finfo;
|
||||||
|
|
||||||
opr_tup = SearchSysCache(OPERNAME,
|
opr_proc = compatible_oper_funcid(makeList1(makeString("=")),
|
||||||
PointerGetDatum("="),
|
typeid, typeid, true);
|
||||||
ObjectIdGetDatum(typeid),
|
if (!OidIsValid(opr_proc))
|
||||||
ObjectIdGetDatum(typeid),
|
|
||||||
CharGetDatum('b'));
|
|
||||||
if (!HeapTupleIsValid(opr_tup))
|
|
||||||
elog(ERROR,
|
elog(ERROR,
|
||||||
"ri_AttributesEqual(): cannot find '=' operator for type %u",
|
"ri_AttributesEqual(): cannot find '=' operator for type %u",
|
||||||
typeid);
|
typeid);
|
||||||
opr_proc = ((Form_pg_operator) GETSTRUCT(opr_tup))->oprcode;
|
|
||||||
ReleaseSysCache(opr_tup);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Since fmgr_info could fail, call it *before* creating the
|
* Since fmgr_info could fail, call it *before* creating the
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/utils/adt/selfuncs.c,v 1.107 2002/04/03 05:39:31 petere Exp $
|
* $Header: /cvsroot/pgsql/src/backend/utils/adt/selfuncs.c,v 1.108 2002/04/16 23:08:11 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -74,6 +74,7 @@
|
|||||||
|
|
||||||
#include "access/heapam.h"
|
#include "access/heapam.h"
|
||||||
#include "catalog/catname.h"
|
#include "catalog/catname.h"
|
||||||
|
#include "catalog/pg_namespace.h"
|
||||||
#include "catalog/pg_operator.h"
|
#include "catalog/pg_operator.h"
|
||||||
#include "catalog/pg_proc.h"
|
#include "catalog/pg_proc.h"
|
||||||
#include "catalog/pg_statistic.h"
|
#include "catalog/pg_statistic.h"
|
||||||
@ -3285,14 +3286,15 @@ string_lessthan(const char *str1, const char *str2, Oid datatype)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* See if there is a binary op of the given name for the given datatype */
|
/* See if there is a binary op of the given name for the given datatype */
|
||||||
|
/* NB: we assume that only built-in system operators are searched for */
|
||||||
static Oid
|
static Oid
|
||||||
find_operator(const char *opname, Oid datatype)
|
find_operator(const char *opname, Oid datatype)
|
||||||
{
|
{
|
||||||
return GetSysCacheOid(OPERNAME,
|
return GetSysCacheOid(OPERNAMENSP,
|
||||||
PointerGetDatum(opname),
|
PointerGetDatum(opname),
|
||||||
ObjectIdGetDatum(datatype),
|
ObjectIdGetDatum(datatype),
|
||||||
ObjectIdGetDatum(datatype),
|
ObjectIdGetDatum(datatype),
|
||||||
CharGetDatum('b'));
|
ObjectIdGetDatum(PG_CATALOG_NAMESPACE));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
47
src/backend/utils/cache/lsyscache.c
vendored
47
src/backend/utils/cache/lsyscache.c
vendored
@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/utils/cache/lsyscache.c,v 1.69 2002/04/05 00:31:30 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/utils/cache/lsyscache.c,v 1.70 2002/04/16 23:08:11 tgl Exp $
|
||||||
*
|
*
|
||||||
* NOTES
|
* NOTES
|
||||||
* Eventually, the index information should go through here, too.
|
* Eventually, the index information should go through here, too.
|
||||||
@ -378,10 +378,6 @@ op_mergejoinable(Oid opno, Oid ltype, Oid rtype, Oid *leftOp, Oid *rightOp)
|
|||||||
* ltype ">" rtype) for an operator previously determined to be
|
* ltype ">" rtype) for an operator previously determined to be
|
||||||
* mergejoinable. Optionally, fetches the regproc ids of these
|
* mergejoinable. Optionally, fetches the regproc ids of these
|
||||||
* operators, as well as their operator OIDs.
|
* operators, as well as their operator OIDs.
|
||||||
*
|
|
||||||
* Raises error if operators cannot be found. Assuming that the operator
|
|
||||||
* had indeed been marked mergejoinable, this indicates that whoever marked
|
|
||||||
* it so was mistaken.
|
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
op_mergejoin_crossops(Oid opno, Oid *ltop, Oid *gtop,
|
op_mergejoin_crossops(Oid opno, Oid *ltop, Oid *gtop,
|
||||||
@ -389,11 +385,9 @@ op_mergejoin_crossops(Oid opno, Oid *ltop, Oid *gtop,
|
|||||||
{
|
{
|
||||||
HeapTuple tp;
|
HeapTuple tp;
|
||||||
Form_pg_operator optup;
|
Form_pg_operator optup;
|
||||||
Oid oprleft,
|
|
||||||
oprright;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get the declared left and right operand types of the operator.
|
* Get the declared comparison operators of the operator.
|
||||||
*/
|
*/
|
||||||
tp = SearchSysCache(OPEROID,
|
tp = SearchSysCache(OPEROID,
|
||||||
ObjectIdGetDatum(opno),
|
ObjectIdGetDatum(opno),
|
||||||
@ -401,44 +395,23 @@ op_mergejoin_crossops(Oid opno, Oid *ltop, Oid *gtop,
|
|||||||
if (!HeapTupleIsValid(tp)) /* shouldn't happen */
|
if (!HeapTupleIsValid(tp)) /* shouldn't happen */
|
||||||
elog(ERROR, "op_mergejoin_crossops: operator %u not found", opno);
|
elog(ERROR, "op_mergejoin_crossops: operator %u not found", opno);
|
||||||
optup = (Form_pg_operator) GETSTRUCT(tp);
|
optup = (Form_pg_operator) GETSTRUCT(tp);
|
||||||
oprleft = optup->oprleft;
|
*ltop = optup->oprltcmpop;
|
||||||
oprright = optup->oprright;
|
*gtop = optup->oprgtcmpop;
|
||||||
ReleaseSysCache(tp);
|
ReleaseSysCache(tp);
|
||||||
|
|
||||||
/*
|
/* Check < op provided */
|
||||||
* Look up the "<" operator with the same input types. If there isn't
|
if (!OidIsValid(*ltop))
|
||||||
* one, whoever marked the "=" operator mergejoinable was a loser.
|
|
||||||
*/
|
|
||||||
tp = SearchSysCache(OPERNAME,
|
|
||||||
PointerGetDatum("<"),
|
|
||||||
ObjectIdGetDatum(oprleft),
|
|
||||||
ObjectIdGetDatum(oprright),
|
|
||||||
CharGetDatum('b'));
|
|
||||||
if (!HeapTupleIsValid(tp))
|
|
||||||
elog(ERROR, "op_mergejoin_crossops: mergejoin operator %u has no matching < operator",
|
elog(ERROR, "op_mergejoin_crossops: mergejoin operator %u has no matching < operator",
|
||||||
opno);
|
opno);
|
||||||
optup = (Form_pg_operator) GETSTRUCT(tp);
|
|
||||||
*ltop = tp->t_data->t_oid;
|
|
||||||
if (ltproc)
|
if (ltproc)
|
||||||
*ltproc = optup->oprcode;
|
*ltproc = get_opcode(*ltop);
|
||||||
ReleaseSysCache(tp);
|
|
||||||
|
|
||||||
/*
|
/* Check > op provided */
|
||||||
* And the same for the ">" operator.
|
if (!OidIsValid(*gtop))
|
||||||
*/
|
|
||||||
tp = SearchSysCache(OPERNAME,
|
|
||||||
PointerGetDatum(">"),
|
|
||||||
ObjectIdGetDatum(oprleft),
|
|
||||||
ObjectIdGetDatum(oprright),
|
|
||||||
CharGetDatum('b'));
|
|
||||||
if (!HeapTupleIsValid(tp))
|
|
||||||
elog(ERROR, "op_mergejoin_crossops: mergejoin operator %u has no matching > operator",
|
elog(ERROR, "op_mergejoin_crossops: mergejoin operator %u has no matching > operator",
|
||||||
opno);
|
opno);
|
||||||
optup = (Form_pg_operator) GETSTRUCT(tp);
|
|
||||||
*gtop = tp->t_data->t_oid;
|
|
||||||
if (gtproc)
|
if (gtproc)
|
||||||
*gtproc = optup->oprcode;
|
*gtproc = get_opcode(*gtop);
|
||||||
ReleaseSysCache(tp);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
8
src/backend/utils/cache/syscache.c
vendored
8
src/backend/utils/cache/syscache.c
vendored
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/utils/cache/syscache.c,v 1.76 2002/04/11 20:00:06 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/utils/cache/syscache.c,v 1.77 2002/04/16 23:08:11 tgl Exp $
|
||||||
*
|
*
|
||||||
* NOTES
|
* NOTES
|
||||||
* These routines allow the parser/planner/executor to perform
|
* These routines allow the parser/planner/executor to perform
|
||||||
@ -273,15 +273,15 @@ static const struct cachedesc cacheinfo[] = {
|
|||||||
0,
|
0,
|
||||||
0
|
0
|
||||||
}},
|
}},
|
||||||
{OperatorRelationName, /* OPERNAME */
|
{OperatorRelationName, /* OPERNAMENSP */
|
||||||
OperatorNameIndex,
|
OperatorNameNspIndex,
|
||||||
0,
|
0,
|
||||||
4,
|
4,
|
||||||
{
|
{
|
||||||
Anum_pg_operator_oprname,
|
Anum_pg_operator_oprname,
|
||||||
Anum_pg_operator_oprleft,
|
Anum_pg_operator_oprleft,
|
||||||
Anum_pg_operator_oprright,
|
Anum_pg_operator_oprright,
|
||||||
Anum_pg_operator_oprkind
|
Anum_pg_operator_oprnamespace
|
||||||
}},
|
}},
|
||||||
{OperatorRelationName, /* OPEROID */
|
{OperatorRelationName, /* OPEROID */
|
||||||
OperatorOidIndex,
|
OperatorOidIndex,
|
||||||
|
@ -37,7 +37,7 @@
|
|||||||
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $Id: catversion.h,v 1.115 2002/04/15 23:45:07 momjian Exp $
|
* $Id: catversion.h,v 1.116 2002/04/16 23:08:11 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -53,6 +53,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* yyyymmddN */
|
/* yyyymmddN */
|
||||||
#define CATALOG_VERSION_NO 200204151
|
#define CATALOG_VERSION_NO 200204161
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $Id: indexing.h,v 1.62 2002/04/11 20:00:10 tgl Exp $
|
* $Id: indexing.h,v 1.63 2002/04/16 23:08:11 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -74,7 +74,7 @@
|
|||||||
#define NamespaceOidIndex "pg_namespace_oid_index"
|
#define NamespaceOidIndex "pg_namespace_oid_index"
|
||||||
#define OpclassAmNameIndex "pg_opclass_am_name_index"
|
#define OpclassAmNameIndex "pg_opclass_am_name_index"
|
||||||
#define OpclassOidIndex "pg_opclass_oid_index"
|
#define OpclassOidIndex "pg_opclass_oid_index"
|
||||||
#define OperatorNameIndex "pg_operator_oprname_l_r_k_index"
|
#define OperatorNameNspIndex "pg_operator_oprname_l_r_n_index"
|
||||||
#define OperatorOidIndex "pg_operator_oid_index"
|
#define OperatorOidIndex "pg_operator_oid_index"
|
||||||
#define ProcedureNameNspIndex "pg_proc_proname_args_nsp_index"
|
#define ProcedureNameNspIndex "pg_proc_proname_args_nsp_index"
|
||||||
#define ProcedureOidIndex "pg_proc_oid_index"
|
#define ProcedureOidIndex "pg_proc_oid_index"
|
||||||
@ -172,7 +172,7 @@ DECLARE_UNIQUE_INDEX(pg_namespace_oid_index on pg_namespace using btree(oid oid_
|
|||||||
DECLARE_UNIQUE_INDEX(pg_opclass_am_name_index on pg_opclass using btree(opcamid oid_ops, opcname name_ops));
|
DECLARE_UNIQUE_INDEX(pg_opclass_am_name_index on pg_opclass using btree(opcamid oid_ops, opcname name_ops));
|
||||||
DECLARE_UNIQUE_INDEX(pg_opclass_oid_index on pg_opclass using btree(oid oid_ops));
|
DECLARE_UNIQUE_INDEX(pg_opclass_oid_index on pg_opclass using btree(oid oid_ops));
|
||||||
DECLARE_UNIQUE_INDEX(pg_operator_oid_index on pg_operator using btree(oid oid_ops));
|
DECLARE_UNIQUE_INDEX(pg_operator_oid_index on pg_operator using btree(oid oid_ops));
|
||||||
DECLARE_UNIQUE_INDEX(pg_operator_oprname_l_r_k_index on pg_operator using btree(oprname name_ops, oprleft oid_ops, oprright oid_ops, oprkind char_ops));
|
DECLARE_UNIQUE_INDEX(pg_operator_oprname_l_r_n_index on pg_operator using btree(oprname name_ops, oprleft oid_ops, oprright oid_ops, oprnamespace oid_ops));
|
||||||
DECLARE_UNIQUE_INDEX(pg_proc_oid_index on pg_proc using btree(oid oid_ops));
|
DECLARE_UNIQUE_INDEX(pg_proc_oid_index on pg_proc using btree(oid oid_ops));
|
||||||
DECLARE_UNIQUE_INDEX(pg_proc_proname_args_nsp_index on pg_proc using btree(proname name_ops, pronargs int2_ops, proargtypes oidvector_ops, pronamespace oid_ops));
|
DECLARE_UNIQUE_INDEX(pg_proc_proname_args_nsp_index on pg_proc using btree(proname name_ops, pronargs int2_ops, proargtypes oidvector_ops, pronamespace oid_ops));
|
||||||
/* This following index is not used for a cache and is not unique */
|
/* This following index is not used for a cache and is not unique */
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $Id: namespace.h,v 1.7 2002/04/09 20:35:54 tgl Exp $
|
* $Id: namespace.h,v 1.8 2002/04/16 23:08:11 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -43,6 +43,8 @@ extern Oid TypenameGetTypid(const char *typname);
|
|||||||
|
|
||||||
extern FuncCandidateList FuncnameGetCandidates(List *names, int nargs);
|
extern FuncCandidateList FuncnameGetCandidates(List *names, int nargs);
|
||||||
|
|
||||||
|
extern FuncCandidateList OpernameGetCandidates(List *names, char oprkind);
|
||||||
|
|
||||||
extern Oid QualifiedNameGetCreationNamespace(List *names, char **objname_p);
|
extern Oid QualifiedNameGetCreationNamespace(List *names, char **objname_p);
|
||||||
|
|
||||||
extern RangeVar *makeRangeVarFromNameList(List *names);
|
extern RangeVar *makeRangeVarFromNameList(List *names);
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $Id: defrem.h,v 1.35 2002/04/15 05:22:03 tgl Exp $
|
* $Id: defrem.h,v 1.36 2002/04/16 23:08:12 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -42,7 +42,7 @@ extern void CreateFunction(ProcedureStmt *stmt);
|
|||||||
extern void RemoveFunction(List *functionName, List *argTypes);
|
extern void RemoveFunction(List *functionName, List *argTypes);
|
||||||
|
|
||||||
extern void DefineOperator(List *names, List *parameters);
|
extern void DefineOperator(List *names, List *parameters);
|
||||||
extern void RemoveOperator(char *operatorName,
|
extern void RemoveOperator(List *operatorName,
|
||||||
TypeName *typeName1, TypeName *typeName2);
|
TypeName *typeName1, TypeName *typeName2);
|
||||||
|
|
||||||
extern void DefineAggregate(List *names, List *parameters);
|
extern void DefineAggregate(List *names, List *parameters);
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $Id: makefuncs.h,v 1.34 2002/03/29 19:06:23 tgl Exp $
|
* $Id: makefuncs.h,v 1.35 2002/04/16 23:08:12 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -16,6 +16,11 @@
|
|||||||
|
|
||||||
#include "nodes/parsenodes.h"
|
#include "nodes/parsenodes.h"
|
||||||
|
|
||||||
|
extern A_Expr *makeA_Expr(int oper, List *name, Node *lexpr, Node *rexpr);
|
||||||
|
|
||||||
|
extern A_Expr *makeSimpleA_Expr(int oper, const char *name,
|
||||||
|
Node *lexpr, Node *rexpr);
|
||||||
|
|
||||||
extern Oper *makeOper(Oid opno,
|
extern Oper *makeOper(Oid opno,
|
||||||
Oid opid,
|
Oid opid,
|
||||||
Oid opresulttype);
|
Oid opresulttype);
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $Id: parsenodes.h,v 1.169 2002/04/09 20:35:54 tgl Exp $
|
* $Id: parsenodes.h,v 1.170 2002/04/16 23:08:12 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -158,7 +158,7 @@ typedef struct A_Expr
|
|||||||
{
|
{
|
||||||
NodeTag type;
|
NodeTag type;
|
||||||
int oper; /* type of operation (OP,OR,AND,NOT) */
|
int oper; /* type of operation (OP,OR,AND,NOT) */
|
||||||
char *opname; /* name of operator */
|
List *name; /* possibly-qualified name of operator */
|
||||||
Node *lexpr; /* left argument */
|
Node *lexpr; /* left argument */
|
||||||
Node *rexpr; /* right argument */
|
Node *rexpr; /* right argument */
|
||||||
} A_Expr;
|
} A_Expr;
|
||||||
@ -373,7 +373,7 @@ typedef struct InsertDefault
|
|||||||
typedef struct SortGroupBy
|
typedef struct SortGroupBy
|
||||||
{
|
{
|
||||||
NodeTag type;
|
NodeTag type;
|
||||||
char *useOp; /* operator to use */
|
List *useOp; /* operator to use */
|
||||||
Node *node; /* Expression */
|
Node *node; /* Expression */
|
||||||
} SortGroupBy;
|
} SortGroupBy;
|
||||||
|
|
||||||
@ -1189,7 +1189,7 @@ typedef struct RemoveFuncStmt
|
|||||||
typedef struct RemoveOperStmt
|
typedef struct RemoveOperStmt
|
||||||
{
|
{
|
||||||
NodeTag type;
|
NodeTag type;
|
||||||
char *opname; /* operator to drop */
|
List *opname; /* operator to drop */
|
||||||
List *args; /* types of the arguments */
|
List *args; /* types of the arguments */
|
||||||
} RemoveOperStmt;
|
} RemoveOperStmt;
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $Id: parse_func.h,v 1.39 2002/04/11 20:00:15 tgl Exp $
|
* $Id: parse_func.h,v 1.40 2002/04/16 23:08:12 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -28,16 +28,6 @@ typedef struct _InhPaths
|
|||||||
Oid *supervec; /* vector of superclasses */
|
Oid *supervec; /* vector of superclasses */
|
||||||
} InhPaths;
|
} InhPaths;
|
||||||
|
|
||||||
/*
|
|
||||||
* This structure holds a list of possible functions or operators that
|
|
||||||
* agree with the known name and argument types of the function/operator.
|
|
||||||
*/
|
|
||||||
typedef struct _CandidateList
|
|
||||||
{
|
|
||||||
Oid *args;
|
|
||||||
struct _CandidateList *next;
|
|
||||||
} *CandidateList;
|
|
||||||
|
|
||||||
/* Result codes for func_get_detail */
|
/* Result codes for func_get_detail */
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $Id: parse_node.h,v 1.29 2001/11/05 17:46:35 momjian Exp $
|
* $Id: parse_node.h,v 1.30 2002/04/16 23:08:12 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -51,9 +51,8 @@ typedef struct ParseState
|
|||||||
} ParseState;
|
} ParseState;
|
||||||
|
|
||||||
extern ParseState *make_parsestate(ParseState *parentParseState);
|
extern ParseState *make_parsestate(ParseState *parentParseState);
|
||||||
extern Expr *make_op(char *opname, Node *ltree, Node *rtree);
|
extern Expr *make_op(List *opname, Node *ltree, Node *rtree);
|
||||||
extern Node *make_operand(char *opname, Node *tree,
|
extern Node *make_operand(Node *tree, Oid orig_typeId, Oid target_typeId);
|
||||||
Oid orig_typeId, Oid target_typeId);
|
|
||||||
extern Var *make_var(ParseState *pstate, RangeTblEntry *rte, int attrno);
|
extern Var *make_var(ParseState *pstate, RangeTblEntry *rte, int attrno);
|
||||||
extern ArrayRef *transformArraySubscripts(ParseState *pstate,
|
extern ArrayRef *transformArraySubscripts(ParseState *pstate,
|
||||||
Node *arrayBase,
|
Node *arrayBase,
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $Id: parse_oper.h,v 1.18 2001/11/05 17:46:35 momjian Exp $
|
* $Id: parse_oper.h,v 1.19 2002/04/16 23:08:12 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -15,25 +15,31 @@
|
|||||||
#define PARSE_OPER_H
|
#define PARSE_OPER_H
|
||||||
|
|
||||||
#include "access/htup.h"
|
#include "access/htup.h"
|
||||||
|
#include "nodes/parsenodes.h"
|
||||||
|
|
||||||
typedef HeapTuple Operator;
|
typedef HeapTuple Operator;
|
||||||
|
|
||||||
|
/* Routines to look up an operator given name and exact input type(s) */
|
||||||
|
extern Oid LookupOperName(List *opername, Oid oprleft, Oid oprright);
|
||||||
|
extern Oid LookupOperNameTypeNames(List *opername, TypeName *oprleft,
|
||||||
|
TypeName *oprright, const char *caller);
|
||||||
|
|
||||||
/* Routines to find operators matching a name and given input types */
|
/* Routines to find operators matching a name and given input types */
|
||||||
/* NB: the selected operator may require coercion of the input types! */
|
/* NB: the selected operator may require coercion of the input types! */
|
||||||
extern Operator oper(char *op, Oid arg1, Oid arg2, bool noError);
|
extern Operator oper(List *op, Oid arg1, Oid arg2, bool noError);
|
||||||
extern Operator right_oper(char *op, Oid arg);
|
extern Operator right_oper(List *op, Oid arg);
|
||||||
extern Operator left_oper(char *op, Oid arg);
|
extern Operator left_oper(List *op, Oid arg);
|
||||||
|
|
||||||
/* Routines to find operators that DO NOT require coercion --- ie, their */
|
/* Routines to find operators that DO NOT require coercion --- ie, their */
|
||||||
/* input types are either exactly as given, or binary-compatible */
|
/* input types are either exactly as given, or binary-compatible */
|
||||||
extern Operator compatible_oper(char *op, Oid arg1, Oid arg2, bool noError);
|
extern Operator compatible_oper(List *op, Oid arg1, Oid arg2, bool noError);
|
||||||
|
|
||||||
/* currently no need for compatible_left_oper/compatible_right_oper */
|
/* currently no need for compatible_left_oper/compatible_right_oper */
|
||||||
|
|
||||||
/* Convenience routines that call compatible_oper() and return either */
|
/* Convenience routines that call compatible_oper() and return either */
|
||||||
/* the operator OID or the underlying function OID, or InvalidOid if fail */
|
/* the operator OID or the underlying function OID, or InvalidOid if fail */
|
||||||
extern Oid compatible_oper_opid(char *op, Oid arg1, Oid arg2, bool noError);
|
extern Oid compatible_oper_opid(List *op, Oid arg1, Oid arg2, bool noError);
|
||||||
extern Oid compatible_oper_funcid(char *op, Oid arg1, Oid arg2, bool noError);
|
extern Oid compatible_oper_funcid(List *op, Oid arg1, Oid arg2, bool noError);
|
||||||
|
|
||||||
/* Convenience routine that packages a specific call on compatible_oper */
|
/* Convenience routine that packages a specific call on compatible_oper */
|
||||||
extern Oid any_ordering_op(Oid argtype);
|
extern Oid any_ordering_op(Oid argtype);
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $Id: syscache.h,v 1.44 2002/04/11 20:00:17 tgl Exp $
|
* $Id: syscache.h,v 1.45 2002/04/16 23:08:12 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -46,7 +46,7 @@
|
|||||||
#define LANGOID 15
|
#define LANGOID 15
|
||||||
#define NAMESPACENAME 16
|
#define NAMESPACENAME 16
|
||||||
#define NAMESPACEOID 17
|
#define NAMESPACEOID 17
|
||||||
#define OPERNAME 18
|
#define OPERNAMENSP 18
|
||||||
#define OPEROID 19
|
#define OPEROID 19
|
||||||
#define PROCNAMENSP 20
|
#define PROCNAMENSP 20
|
||||||
#define PROCOID 21
|
#define PROCOID 21
|
||||||
|
@ -173,13 +173,13 @@ drop operator;
|
|||||||
ERROR: parser: parse error at or near ";"
|
ERROR: parser: parse error at or near ";"
|
||||||
-- bad operator name
|
-- bad operator name
|
||||||
drop operator equals;
|
drop operator equals;
|
||||||
ERROR: parser: parse error at or near "equals"
|
ERROR: parser: parse error at or near ";"
|
||||||
-- missing type list
|
-- missing type list
|
||||||
drop operator ===;
|
drop operator ===;
|
||||||
ERROR: parser: parse error at or near ";"
|
ERROR: parser: parse error at or near ";"
|
||||||
-- missing parentheses
|
-- missing parentheses
|
||||||
drop operator int4, int4;
|
drop operator int4, int4;
|
||||||
ERROR: parser: parse error at or near "int4"
|
ERROR: parser: parse error at or near ","
|
||||||
-- missing operator name
|
-- missing operator name
|
||||||
drop operator (int4, int4);
|
drop operator (int4, int4);
|
||||||
ERROR: parser: parse error at or near "("
|
ERROR: parser: parse error at or near "("
|
||||||
@ -191,7 +191,7 @@ drop operator === (int4);
|
|||||||
ERROR: parser: argument type missing (use NONE for unary operators)
|
ERROR: parser: argument type missing (use NONE for unary operators)
|
||||||
-- no such operator by that name
|
-- no such operator by that name
|
||||||
drop operator === (int4, int4);
|
drop operator === (int4, int4);
|
||||||
ERROR: RemoveOperator: binary operator '===' taking 'int4' and 'int4' does not exist
|
ERROR: RemoveOperator: Operator '===' for types 'int4' and 'int4' does not exist
|
||||||
-- no such type1
|
-- no such type1
|
||||||
drop operator = (nonesuch);
|
drop operator = (nonesuch);
|
||||||
ERROR: parser: argument type missing (use NONE for unary operators)
|
ERROR: parser: argument type missing (use NONE for unary operators)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user