Implement CREATE/DROP OPERATOR CLASS. Work still remains: need more
documentation (xindex.sgml should be rewritten), need to teach pg_dump about it, need to update contrib modules that currently build pg_opclass entries by hand. Original patch by Bill Studenmund, grammar adjustments and general update for 7.3 by Tom Lane.
This commit is contained in:
parent
b9459c6adb
commit
ea4686e3e1
@ -2,6 +2,10 @@
|
||||
--
|
||||
BEGIN TRANSACTION;
|
||||
|
||||
-- Adjust this setting to control where the operators, functions, and
|
||||
-- opclasses get created.
|
||||
SET search_path = public;
|
||||
|
||||
-- Query type
|
||||
CREATE FUNCTION bqarr_in(opaque)
|
||||
RETURNS opaque
|
||||
@ -143,137 +147,22 @@ CREATE FUNCTION g_int_same(_int4, _int4, opaque) RETURNS opaque
|
||||
AS 'MODULE_PATHNAME' LANGUAGE 'c';
|
||||
|
||||
|
||||
-- register the default opclass for indexing
|
||||
INSERT INTO pg_opclass (opcamid, opcname, opcnamespace, opcowner, opcintype, opcdefault, opckeytype)
|
||||
VALUES (
|
||||
(SELECT oid FROM pg_am WHERE amname = 'gist'),
|
||||
'gist__int_ops',
|
||||
(SELECT oid FROM pg_namespace WHERE nspname = 'pg_catalog'),
|
||||
1, -- UID of superuser is hardwired to 1 as of PG 7.3
|
||||
(SELECT oid FROM pg_type WHERE typname = '_int4'),
|
||||
true,
|
||||
0);
|
||||
-- Create the operator class for indexing
|
||||
|
||||
|
||||
-- get the comparators for _intments and store them in a tmp table
|
||||
SELECT o.oid AS opoid, o.oprname
|
||||
INTO TEMP TABLE _int_ops_tmp
|
||||
FROM pg_operator o, pg_type t, pg_type tq
|
||||
WHERE o.oprleft = t.oid and ( o.oprright = t.oid or o.oprright=tq.oid )
|
||||
and t.typname = '_int4'
|
||||
and tq.typname='query_int';
|
||||
|
||||
-- make sure we have the right operators
|
||||
-- SELECT * from _int_ops_tmp;
|
||||
|
||||
-- using the tmp table, generate the amop entries
|
||||
|
||||
-- _int_overlap
|
||||
INSERT INTO pg_amop (amopclaid, amopstrategy, amopreqcheck, amopopr)
|
||||
SELECT opcl.oid, 3, false, c.opoid
|
||||
FROM pg_opclass opcl, _int_ops_tmp c
|
||||
WHERE
|
||||
opcamid = (SELECT oid FROM pg_am WHERE amname = 'gist')
|
||||
and opcname = 'gist__int_ops'
|
||||
and c.oprname = '&&';
|
||||
|
||||
-- _int_same
|
||||
INSERT INTO pg_amop (amopclaid, amopstrategy, amopreqcheck, amopopr)
|
||||
SELECT opcl.oid, 6, true, c.opoid
|
||||
FROM pg_opclass opcl, _int_ops_tmp c
|
||||
WHERE
|
||||
opcamid = (SELECT oid FROM pg_am WHERE amname = 'gist')
|
||||
and opcname = 'gist__int_ops'
|
||||
and c.oprname = '=';
|
||||
|
||||
-- _int_contains
|
||||
INSERT INTO pg_amop (amopclaid, amopstrategy, amopreqcheck, amopopr)
|
||||
SELECT opcl.oid, 7, false, c.opoid
|
||||
FROM pg_opclass opcl, _int_ops_tmp c
|
||||
WHERE
|
||||
opcamid = (SELECT oid FROM pg_am WHERE amname = 'gist')
|
||||
and opcname = 'gist__int_ops'
|
||||
and c.oprname = '@';
|
||||
|
||||
-- _int_contained
|
||||
INSERT INTO pg_amop (amopclaid, amopstrategy, amopreqcheck, amopopr)
|
||||
SELECT opcl.oid, 8, false, c.opoid
|
||||
FROM pg_opclass opcl, _int_ops_tmp c
|
||||
WHERE
|
||||
opcamid = (SELECT oid FROM pg_am WHERE amname = 'gist')
|
||||
and opcname = 'gist__int_ops'
|
||||
and c.oprname = '~';
|
||||
|
||||
--boolean search
|
||||
INSERT INTO pg_amop (amopclaid, amopstrategy, amopreqcheck, amopopr)
|
||||
SELECT opcl.oid, 20, false, c.opoid
|
||||
FROM pg_opclass opcl, _int_ops_tmp c
|
||||
WHERE
|
||||
opcamid = (SELECT oid FROM pg_am WHERE amname = 'gist')
|
||||
and opcname = 'gist__int_ops'
|
||||
and c.oprname = '@@';
|
||||
|
||||
DROP TABLE _int_ops_tmp;
|
||||
|
||||
|
||||
-- add the entries to amproc for the support methods
|
||||
-- note the amprocnum numbers associated with each are specific!
|
||||
|
||||
INSERT INTO pg_amproc (amopclaid, amprocnum, amproc)
|
||||
SELECT opcl.oid, 1, pro.oid
|
||||
FROM pg_opclass opcl, pg_proc pro
|
||||
WHERE
|
||||
opcamid = (SELECT oid FROM pg_am WHERE amname = 'gist')
|
||||
and opcname = 'gist__int_ops'
|
||||
and proname = 'g_int_consistent';
|
||||
|
||||
INSERT INTO pg_amproc (amopclaid, amprocnum, amproc)
|
||||
SELECT opcl.oid, 2, pro.oid
|
||||
FROM pg_opclass opcl, pg_proc pro
|
||||
WHERE
|
||||
opcamid = (SELECT oid FROM pg_am WHERE amname = 'gist')
|
||||
and opcname = 'gist__int_ops'
|
||||
and proname = 'g_int_union';
|
||||
|
||||
INSERT INTO pg_amproc (amopclaid, amprocnum, amproc)
|
||||
SELECT opcl.oid, 3, pro.oid
|
||||
FROM pg_opclass opcl, pg_proc pro
|
||||
WHERE
|
||||
opcamid = (SELECT oid FROM pg_am WHERE amname = 'gist')
|
||||
and opcname = 'gist__int_ops'
|
||||
and proname = 'g_int_compress';
|
||||
|
||||
INSERT INTO pg_amproc (amopclaid, amprocnum, amproc)
|
||||
SELECT opcl.oid, 4, pro.oid
|
||||
FROM pg_opclass opcl, pg_proc pro
|
||||
WHERE
|
||||
opcamid = (SELECT oid FROM pg_am WHERE amname = 'gist')
|
||||
and opcname = 'gist__int_ops'
|
||||
and proname = 'g_int_decompress';
|
||||
|
||||
INSERT INTO pg_amproc (amopclaid, amprocnum, amproc)
|
||||
SELECT opcl.oid, 5, pro.oid
|
||||
FROM pg_opclass opcl, pg_proc pro
|
||||
WHERE
|
||||
opcamid = (SELECT oid FROM pg_am WHERE amname = 'gist')
|
||||
and opcname = 'gist__int_ops'
|
||||
and proname = 'g_int_penalty';
|
||||
|
||||
INSERT INTO pg_amproc (amopclaid, amprocnum, amproc)
|
||||
SELECT opcl.oid, 6, pro.oid
|
||||
FROM pg_opclass opcl, pg_proc pro
|
||||
WHERE
|
||||
opcamid = (SELECT oid FROM pg_am WHERE amname = 'gist')
|
||||
and opcname = 'gist__int_ops'
|
||||
and proname = 'g_int_picksplit';
|
||||
|
||||
INSERT INTO pg_amproc (amopclaid, amprocnum, amproc)
|
||||
SELECT opcl.oid, 7, pro.oid
|
||||
FROM pg_opclass opcl, pg_proc pro
|
||||
WHERE
|
||||
opcamid = (SELECT oid FROM pg_am WHERE amname = 'gist')
|
||||
and opcname = 'gist__int_ops'
|
||||
and proname = 'g_int_same';
|
||||
CREATE OPERATOR CLASS gist__int_ops
|
||||
DEFAULT FOR TYPE _int4 USING gist AS
|
||||
OPERATOR 3 &&,
|
||||
OPERATOR 6 = RECHECK,
|
||||
OPERATOR 7 @,
|
||||
OPERATOR 8 ~,
|
||||
OPERATOR 20 @@ (_int4, query_int),
|
||||
FUNCTION 1 g_int_consistent (opaque, _int4, int4),
|
||||
FUNCTION 2 g_int_union (bytea, opaque),
|
||||
FUNCTION 3 g_int_compress (opaque),
|
||||
FUNCTION 4 g_int_decompress (opaque),
|
||||
FUNCTION 5 g_int_penalty (opaque, opaque, opaque),
|
||||
FUNCTION 6 g_int_picksplit (opaque, opaque),
|
||||
FUNCTION 7 g_int_same (_int4, _int4, opaque);
|
||||
|
||||
|
||||
---------------------------------------------
|
||||
@ -302,136 +191,20 @@ CREATE FUNCTION g_intbig_same(_int4, _int4, opaque) RETURNS opaque
|
||||
AS 'MODULE_PATHNAME' LANGUAGE 'c';
|
||||
|
||||
-- register the opclass for indexing (not as default)
|
||||
INSERT INTO pg_opclass (opcamid, opcname, opcnamespace, opcowner, opcintype, opcdefault, opckeytype)
|
||||
VALUES (
|
||||
(SELECT oid FROM pg_am WHERE amname = 'gist'),
|
||||
'gist__intbig_ops',
|
||||
(SELECT oid FROM pg_namespace WHERE nspname = 'pg_catalog'),
|
||||
1, -- UID of superuser is hardwired to 1 as of PG 7.3
|
||||
(SELECT oid FROM pg_type WHERE typname = '_int4'),
|
||||
false,
|
||||
0);
|
||||
|
||||
|
||||
-- get the comparators for _intments and store them in a tmp table
|
||||
SELECT o.oid AS opoid, o.oprname
|
||||
INTO TEMP TABLE _int_ops_tmp
|
||||
FROM pg_operator o, pg_type t, pg_type tq
|
||||
WHERE o.oprleft = t.oid and ( o.oprright = t.oid or o.oprright=tq.oid )
|
||||
and t.typname = '_int4'
|
||||
and tq.typname='query_int';
|
||||
|
||||
-- make sure we have the right operators
|
||||
-- SELECT * from _int_ops_tmp;
|
||||
|
||||
-- using the tmp table, generate the amop entries
|
||||
-- note: these operators are all lossy
|
||||
|
||||
-- _int_overlap
|
||||
INSERT INTO pg_amop (amopclaid, amopstrategy, amopreqcheck, amopopr)
|
||||
SELECT opcl.oid, 3, true, c.opoid
|
||||
FROM pg_opclass opcl, _int_ops_tmp c
|
||||
WHERE
|
||||
opcamid = (SELECT oid FROM pg_am WHERE amname = 'gist')
|
||||
and opcname = 'gist__intbig_ops'
|
||||
and c.oprname = '&&';
|
||||
|
||||
-- _int_contains
|
||||
INSERT INTO pg_amop (amopclaid, amopstrategy, amopreqcheck, amopopr)
|
||||
SELECT opcl.oid, 7, true, c.opoid
|
||||
FROM pg_opclass opcl, _int_ops_tmp c
|
||||
WHERE
|
||||
opcamid = (SELECT oid FROM pg_am WHERE amname = 'gist')
|
||||
and opcname = 'gist__intbig_ops'
|
||||
and c.oprname = '@';
|
||||
|
||||
-- _int_contained
|
||||
INSERT INTO pg_amop (amopclaid, amopstrategy, amopreqcheck, amopopr)
|
||||
SELECT opcl.oid, 8, true, c.opoid
|
||||
FROM pg_opclass opcl, _int_ops_tmp c
|
||||
WHERE
|
||||
opcamid = (SELECT oid FROM pg_am WHERE amname = 'gist')
|
||||
and opcname = 'gist__intbig_ops'
|
||||
and c.oprname = '~';
|
||||
|
||||
-- _int_same
|
||||
INSERT INTO pg_amop (amopclaid, amopstrategy, amopreqcheck, amopopr)
|
||||
SELECT opcl.oid, 6, true, c.opoid
|
||||
FROM pg_opclass opcl, _int_ops_tmp c
|
||||
WHERE
|
||||
opcamid = (SELECT oid FROM pg_am WHERE amname = 'gist')
|
||||
and opcname = 'gist__intbig_ops'
|
||||
and c.oprname = '=';
|
||||
|
||||
--boolean search
|
||||
INSERT INTO pg_amop (amopclaid, amopstrategy, amopreqcheck, amopopr)
|
||||
SELECT opcl.oid, 20, true, c.opoid
|
||||
FROM pg_opclass opcl, _int_ops_tmp c
|
||||
WHERE
|
||||
opcamid = (SELECT oid FROM pg_am WHERE amname = 'gist')
|
||||
and opcname = 'gist__intbig_ops'
|
||||
and c.oprname = '@@';
|
||||
|
||||
DROP TABLE _int_ops_tmp;
|
||||
|
||||
|
||||
-- add the entries to amproc for the support methods
|
||||
-- note the amprocnum numbers associated with each are specific!
|
||||
|
||||
INSERT INTO pg_amproc (amopclaid, amprocnum, amproc)
|
||||
SELECT opcl.oid, 1, pro.oid
|
||||
FROM pg_opclass opcl, pg_proc pro
|
||||
WHERE
|
||||
opcamid = (SELECT oid FROM pg_am WHERE amname = 'gist')
|
||||
and opcname = 'gist__intbig_ops'
|
||||
and proname = 'g_intbig_consistent';
|
||||
|
||||
INSERT INTO pg_amproc (amopclaid, amprocnum, amproc)
|
||||
SELECT opcl.oid, 2, pro.oid
|
||||
FROM pg_opclass opcl, pg_proc pro
|
||||
WHERE
|
||||
opcamid = (SELECT oid FROM pg_am WHERE amname = 'gist')
|
||||
and opcname = 'gist__intbig_ops'
|
||||
and proname = 'g_intbig_union';
|
||||
|
||||
INSERT INTO pg_amproc (amopclaid, amprocnum, amproc)
|
||||
SELECT opcl.oid, 3, pro.oid
|
||||
FROM pg_opclass opcl, pg_proc pro
|
||||
WHERE
|
||||
opcamid = (SELECT oid FROM pg_am WHERE amname = 'gist')
|
||||
and opcname = 'gist__intbig_ops'
|
||||
and proname = 'g_intbig_compress';
|
||||
|
||||
INSERT INTO pg_amproc (amopclaid, amprocnum, amproc)
|
||||
SELECT opcl.oid, 4, pro.oid
|
||||
FROM pg_opclass opcl, pg_proc pro
|
||||
WHERE
|
||||
opcamid = (SELECT oid FROM pg_am WHERE amname = 'gist')
|
||||
and opcname = 'gist__intbig_ops'
|
||||
and proname = 'g_intbig_decompress';
|
||||
|
||||
INSERT INTO pg_amproc (amopclaid, amprocnum, amproc)
|
||||
SELECT opcl.oid, 5, pro.oid
|
||||
FROM pg_opclass opcl, pg_proc pro
|
||||
WHERE
|
||||
opcamid = (SELECT oid FROM pg_am WHERE amname = 'gist')
|
||||
and opcname = 'gist__intbig_ops'
|
||||
and proname = 'g_intbig_penalty';
|
||||
|
||||
INSERT INTO pg_amproc (amopclaid, amprocnum, amproc)
|
||||
SELECT opcl.oid, 6, pro.oid
|
||||
FROM pg_opclass opcl, pg_proc pro
|
||||
WHERE
|
||||
opcamid = (SELECT oid FROM pg_am WHERE amname = 'gist')
|
||||
and opcname = 'gist__intbig_ops'
|
||||
and proname = 'g_intbig_picksplit';
|
||||
|
||||
INSERT INTO pg_amproc (amopclaid, amprocnum, amproc)
|
||||
SELECT opcl.oid, 7, pro.oid
|
||||
FROM pg_opclass opcl, pg_proc pro
|
||||
WHERE
|
||||
opcamid = (SELECT oid FROM pg_am WHERE amname = 'gist')
|
||||
and opcname = 'gist__intbig_ops'
|
||||
and proname = 'g_intbig_same';
|
||||
CREATE OPERATOR CLASS gist__intbig_ops
|
||||
FOR TYPE _int4 USING gist AS
|
||||
OPERATOR 3 && RECHECK,
|
||||
OPERATOR 6 = RECHECK,
|
||||
OPERATOR 7 @ RECHECK,
|
||||
OPERATOR 8 ~ RECHECK,
|
||||
OPERATOR 20 @@ (_int4, query_int) RECHECK,
|
||||
FUNCTION 1 g_intbig_consistent (opaque, _int4, int4),
|
||||
FUNCTION 2 g_intbig_union (bytea, opaque),
|
||||
FUNCTION 3 g_intbig_compress (opaque),
|
||||
FUNCTION 4 g_intbig_decompress (opaque),
|
||||
FUNCTION 5 g_intbig_penalty (opaque, opaque, opaque),
|
||||
FUNCTION 6 g_intbig_picksplit (opaque, opaque),
|
||||
FUNCTION 7 g_intbig_same (_int4, _int4, opaque);
|
||||
|
||||
END TRANSACTION;
|
||||
|
@ -1,5 +1,5 @@
|
||||
<!--
|
||||
$Header: /cvsroot/pgsql/doc/src/sgml/ref/allfiles.sgml,v 1.42 2002/07/22 08:57:15 ishii Exp $
|
||||
$Header: /cvsroot/pgsql/doc/src/sgml/ref/allfiles.sgml,v 1.43 2002/07/29 22:14:10 tgl Exp $
|
||||
PostgreSQL documentation
|
||||
Complete list of usable sgml source files in this directory.
|
||||
-->
|
||||
@ -61,6 +61,7 @@ Complete list of usable sgml source files in this directory.
|
||||
<!entity createIndex system "create_index.sgml">
|
||||
<!entity createLanguage system "create_language.sgml">
|
||||
<!entity createOperator system "create_operator.sgml">
|
||||
<!entity createOperatorClass system "create_opclass.sgml">
|
||||
<!entity createRule system "create_rule.sgml">
|
||||
<!entity createSchema system "create_schema.sgml">
|
||||
<!entity createSequence system "create_sequence.sgml">
|
||||
@ -82,6 +83,7 @@ Complete list of usable sgml source files in this directory.
|
||||
<!entity dropIndex system "drop_index.sgml">
|
||||
<!entity dropLanguage system "drop_language.sgml">
|
||||
<!entity dropOperator system "drop_operator.sgml">
|
||||
<!entity dropOperatorClass system "drop_opclass.sgml">
|
||||
<!entity dropRule system "drop_rule.sgml">
|
||||
<!entity dropSchema system "drop_schema.sgml">
|
||||
<!entity dropSequence system "drop_sequence.sgml">
|
||||
|
316
doc/src/sgml/ref/create_opclass.sgml
Normal file
316
doc/src/sgml/ref/create_opclass.sgml
Normal file
@ -0,0 +1,316 @@
|
||||
<!--
|
||||
$Header: /cvsroot/pgsql/doc/src/sgml/ref/create_opclass.sgml,v 1.1 2002/07/29 22:14:10 tgl Exp $
|
||||
PostgreSQL documentation
|
||||
-->
|
||||
|
||||
<refentry id="SQL-CREATEOPCLASS">
|
||||
<refmeta>
|
||||
<refentrytitle id="sql-createopclass-title">CREATE OPERATOR CLASS</refentrytitle>
|
||||
<refmiscinfo>SQL - Language Statements</refmiscinfo>
|
||||
</refmeta>
|
||||
<refnamediv>
|
||||
<refname>
|
||||
CREATE OPERATOR CLASS
|
||||
</refname>
|
||||
<refpurpose>
|
||||
define a new operator class for indexes
|
||||
</refpurpose>
|
||||
</refnamediv>
|
||||
<refsynopsisdiv>
|
||||
<refsynopsisdivinfo>
|
||||
<date>2002-07-28</date>
|
||||
</refsynopsisdivinfo>
|
||||
<synopsis>
|
||||
CREATE OPERATOR CLASS <replaceable class="parameter">name</replaceable> [ DEFAULT ] FOR TYPE <replaceable class="parameter">data_type</replaceable> USING <replaceable class="parameter">access_method</replaceable> AS
|
||||
{ OPERATOR <replaceable class="parameter">strategy_number</replaceable> <replaceable class="parameter">operator_id</replaceable> [ ( <replaceable class="parameter">type</replaceable>, <replaceable class="parameter">type</replaceable> ) ] [ RECHECK ]
|
||||
| FUNCTION <replaceable class="parameter">support_number</replaceable> <replaceable class="parameter">func_name</replaceable> ( <replaceable class="parameter">parameter_types</replaceable> )
|
||||
| STORAGE <replaceable class="parameter">storage_type</replaceable>
|
||||
} [, ... ]
|
||||
</synopsis>
|
||||
|
||||
<refsect2 id="R2-SQL-CREATEOPCLASS-1">
|
||||
<refsect2info>
|
||||
<date>2002-07-28</date>
|
||||
</refsect2info>
|
||||
<title>
|
||||
Inputs
|
||||
</title>
|
||||
<para>
|
||||
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><replaceable class="parameter">name</replaceable></term>
|
||||
<listitem>
|
||||
<para>
|
||||
The name of the operator class to be created.
|
||||
The name may be schema-qualified.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><literal>DEFAULT</></term>
|
||||
<listitem>
|
||||
<para>
|
||||
If present, the operator class will become the default index
|
||||
operator class for its datatype. At most one operator class
|
||||
can be the default for a specific datatype and access method.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><replaceable class="parameter">data_type</replaceable></term>
|
||||
<listitem>
|
||||
<para>
|
||||
The column datatype that this operator class is for.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><replaceable class="parameter">access_method</replaceable></term>
|
||||
<listitem>
|
||||
<para>
|
||||
The name of the index access method this operator class is for.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><replaceable class="parameter">strategy_number</replaceable></term>
|
||||
<listitem>
|
||||
<para>
|
||||
The index access method's strategy number for an operator associated
|
||||
with the operator class.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><replaceable class="parameter">operator_id</replaceable></term>
|
||||
<listitem>
|
||||
<para>
|
||||
The identifier (optionally schema-qualified) of an operator associated
|
||||
with the operator class.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><replaceable class="parameter">type</replaceable></term>
|
||||
<listitem>
|
||||
<para>
|
||||
The input datatype(s) of an operator, or <literal>NONE</> to
|
||||
signify a left-unary or right-unary operator. The input datatypes
|
||||
may be omitted in the normal case where they are the same as the
|
||||
operator class's datatype.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><literal>RECHECK</></term>
|
||||
<listitem>
|
||||
<para>
|
||||
If present, the index is <quote>lossy</> for this operator,
|
||||
and so the tuples retrieved using the index must be rechecked
|
||||
to verify that they actually satisfy the qualification clause
|
||||
involving this operator.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><replaceable class="parameter">support_number</replaceable></term>
|
||||
<listitem>
|
||||
<para>
|
||||
The index access method's support procedure number for a function
|
||||
associated with the operator class.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><replaceable class="parameter">func_name</replaceable></term>
|
||||
<listitem>
|
||||
<para>
|
||||
The name (optionally schema-qualified) of a function that is
|
||||
an index access method support procedure for the operator class.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><replaceable class="parameter">parameter_types</replaceable></term>
|
||||
<listitem>
|
||||
<para>
|
||||
The parameter datatype(s) of the function.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><replaceable class="parameter">storage_type</replaceable></term>
|
||||
<listitem>
|
||||
<para>
|
||||
The datatype actually stored in the index. Normally this is the
|
||||
same as the column datatype, but some index access methods (only
|
||||
GIST at this writing) allow it to be different. The
|
||||
<literal>STORAGE</> clause must be omitted unless the index access
|
||||
method allows a different type to be used.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</para>
|
||||
</refsect2>
|
||||
|
||||
<refsect2 id="R2-SQL-CREATEOPCLASS-2">
|
||||
<refsect2info>
|
||||
<date>2002-07-28</date>
|
||||
</refsect2info>
|
||||
<title>
|
||||
Outputs
|
||||
</title>
|
||||
<para>
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><computeroutput>
|
||||
CREATE OPERATOR CLASS
|
||||
</computeroutput></term>
|
||||
<listitem>
|
||||
<para>
|
||||
Message returned if the operator class is successfully created.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</para>
|
||||
</refsect2>
|
||||
</refsynopsisdiv>
|
||||
|
||||
<refsect1 id="R1-SQL-CREATEOPCLASS-1">
|
||||
<refsect1info>
|
||||
<date>2002-07-28</date>
|
||||
</refsect1info>
|
||||
<title>
|
||||
Description
|
||||
</title>
|
||||
<para>
|
||||
<command>CREATE OPERATOR CLASS</command> defines a new operator class,
|
||||
<replaceable class="parameter">name</replaceable>.
|
||||
</para>
|
||||
<para>
|
||||
An operator class defines how a particular datatype can be used with
|
||||
an index. The operator class specifies that certain operators will fill
|
||||
particular roles or <quote>strategies</> for this datatype and this
|
||||
access method. The operator class also specifies the support procedures to
|
||||
be used by
|
||||
the index access method when the operator class is selected for an
|
||||
index column. All the operators and functions used by an operator
|
||||
class must be defined before the operator class is created.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
If a schema name is given then the operator class is created in the
|
||||
specified schema. Otherwise it is created in the current schema (the one
|
||||
at the front of the search path; see <literal>CURRENT_SCHEMA()</>).
|
||||
Two operator classes in the same schema can have the same name only if they
|
||||
are for different index access methods.
|
||||
</para>
|
||||
<para>
|
||||
The user who defines an operator class becomes its owner. The user
|
||||
must own the datatype for which the operator class is being defined,
|
||||
and must have execute permission for all referenced operators and functions.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
<command>CREATE OPERATOR CLASS</command> does not presently check
|
||||
whether the class definition includes all the operators and functions
|
||||
required by the index access method. It is the user's
|
||||
responsibility to define a valid operator class.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Refer to the chapter on interfacing extensions to indexes in the
|
||||
<citetitle>PostgreSQL Programmer's Guide</citetitle>
|
||||
for further information.
|
||||
</para>
|
||||
|
||||
<refsect2 id="R2-SQL-CREATEOPCLASS-3">
|
||||
<refsect2info>
|
||||
<date>2002-07-28</date>
|
||||
</refsect2info>
|
||||
<title>
|
||||
Notes
|
||||
</title>
|
||||
<para>
|
||||
Refer to
|
||||
<xref linkend="sql-dropopclass" endterm="sql-dropopclass-title">
|
||||
to delete user-defined operator classes from a database.
|
||||
</para>
|
||||
</refsect2>
|
||||
</refsect1>
|
||||
|
||||
<refsect1 id="R1-SQL-CREATEOPCLASS-2">
|
||||
<title>
|
||||
Usage
|
||||
</title>
|
||||
<para>
|
||||
The following example command defines a GiST index operator class
|
||||
for datatype <literal>_int4</> (array of int4). See
|
||||
<filename>contrib/intarray/</> for the complete example.
|
||||
</para>
|
||||
|
||||
<programlisting>
|
||||
CREATE OPERATOR CLASS gist__int_ops
|
||||
DEFAULT FOR TYPE _int4 USING gist AS
|
||||
OPERATOR 3 &&,
|
||||
OPERATOR 6 = RECHECK,
|
||||
OPERATOR 7 @,
|
||||
OPERATOR 8 ~,
|
||||
OPERATOR 20 @@ (_int4, query_int),
|
||||
FUNCTION 1 g_int_consistent (opaque, _int4, int4),
|
||||
FUNCTION 2 g_int_union (bytea, opaque),
|
||||
FUNCTION 3 g_int_compress (opaque),
|
||||
FUNCTION 4 g_int_decompress (opaque),
|
||||
FUNCTION 5 g_int_penalty (opaque, opaque, opaque),
|
||||
FUNCTION 6 g_int_picksplit (opaque, opaque),
|
||||
FUNCTION 7 g_int_same (_int4, _int4, opaque);
|
||||
</programlisting>
|
||||
|
||||
<para>
|
||||
The <literal>OPERATOR</>, <literal>FUNCTION</>, and <literal>STORAGE</>
|
||||
clauses may appear in any order.
|
||||
</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1 id="R1-SQL-CREATEOPCLASS-3">
|
||||
<title>
|
||||
Compatibility
|
||||
</title>
|
||||
|
||||
<refsect2 id="R2-SQL-CREATEOPCLASS-4">
|
||||
<refsect2info>
|
||||
<date>2002-07-28</date>
|
||||
</refsect2info>
|
||||
<title>
|
||||
SQL92
|
||||
</title>
|
||||
|
||||
<para>
|
||||
<command>CREATE OPERATOR CLASS</command>
|
||||
is a <productname>PostgreSQL</productname> extension.
|
||||
There is no <command>CREATE OPERATOR CLASS</command>
|
||||
statement in <acronym>SQL92</acronym>.
|
||||
</para>
|
||||
</refsect2>
|
||||
</refsect1>
|
||||
</refentry>
|
||||
|
||||
<!-- Keep this comment at the end of the file
|
||||
Local variables:
|
||||
mode: sgml
|
||||
sgml-omittag:nil
|
||||
sgml-shorttag:t
|
||||
sgml-minimize-attributes:nil
|
||||
sgml-always-quote-attributes:t
|
||||
sgml-indent-step:1
|
||||
sgml-indent-data:t
|
||||
sgml-parent-document:nil
|
||||
sgml-default-dtd-file:"../reference.ced"
|
||||
sgml-exposed-tags:nil
|
||||
sgml-local-catalogs:"/usr/lib/sgml/catalog"
|
||||
sgml-local-ecat-files:nil
|
||||
End:
|
||||
-->
|
184
doc/src/sgml/ref/drop_opclass.sgml
Normal file
184
doc/src/sgml/ref/drop_opclass.sgml
Normal file
@ -0,0 +1,184 @@
|
||||
<!--
|
||||
$Header: /cvsroot/pgsql/doc/src/sgml/ref/drop_opclass.sgml,v 1.1 2002/07/29 22:14:10 tgl Exp $
|
||||
PostgreSQL documentation
|
||||
-->
|
||||
|
||||
<refentry id="SQL-DROPOPCLASS">
|
||||
<refmeta>
|
||||
<refentrytitle id="SQL-DROPOPCLASS-TITLE">DROP OPERATOR CLASS</refentrytitle>
|
||||
<refmiscinfo>SQL - Language Statements</refmiscinfo>
|
||||
</refmeta>
|
||||
<refnamediv>
|
||||
<refname>
|
||||
DROP OPERATOR CLASS
|
||||
</refname>
|
||||
<refpurpose>
|
||||
remove a user-defined operator class
|
||||
</refpurpose>
|
||||
</refnamediv>
|
||||
|
||||
<refsynopsisdiv>
|
||||
<refsynopsisdivinfo>
|
||||
<date>2002-07-28</date>
|
||||
</refsynopsisdivinfo>
|
||||
<synopsis>
|
||||
DROP OPERATOR CLASS <replaceable class="PARAMETER">name</replaceable> USING <replaceable class="PARAMETER">access_method</replaceable> [ CASCADE | RESTRICT ]
|
||||
</synopsis>
|
||||
|
||||
<refsect2 id="R2-SQL-DROPOPCLASS-1">
|
||||
<refsect2info>
|
||||
<date>2002-07-28</date>
|
||||
</refsect2info>
|
||||
<title>
|
||||
Inputs
|
||||
</title>
|
||||
<para>
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><replaceable class="parameter">name</replaceable></term>
|
||||
<listitem>
|
||||
<para>
|
||||
The name (optionally schema-qualified) of an existing operator class.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><replaceable class="parameter">access_method</replaceable></term>
|
||||
<listitem>
|
||||
<para>
|
||||
The name of the index access method the operator class is for.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>CASCADE</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Automatically drop objects that depend on the operator class.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>RESTRICT</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Refuse to drop the operator class if there are any dependent objects.
|
||||
This is the default.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</para>
|
||||
</refsect2>
|
||||
|
||||
<refsect2 id="R2-SQL-DROPOPCLASS-2">
|
||||
<refsect2info>
|
||||
<date>2002-07-28</date>
|
||||
</refsect2info>
|
||||
<title>
|
||||
Outputs
|
||||
</title>
|
||||
<para>
|
||||
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><computeroutput>
|
||||
DROP OPERATOR CLASS
|
||||
</computeroutput></term>
|
||||
<listitem>
|
||||
<para>
|
||||
The message returned if the command is successful.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</para>
|
||||
</refsect2>
|
||||
</refsynopsisdiv>
|
||||
|
||||
<refsect1 id="R1-SQL-DROPOPCLASS-1">
|
||||
<refsect1info>
|
||||
<date>2002-07-28</date>
|
||||
</refsect1info>
|
||||
<title>
|
||||
Description
|
||||
</title>
|
||||
<para>
|
||||
<command>DROP OPERATOR CLASS</command> drops an existing operator class
|
||||
from the database.
|
||||
To execute this command you must be the owner of the operator class.
|
||||
</para>
|
||||
|
||||
<refsect2 id="R2-SQL-DROPOPCLASS-3">
|
||||
<refsect2info>
|
||||
<date>2002-07-28</date>
|
||||
</refsect2info>
|
||||
<title>
|
||||
Notes
|
||||
</title>
|
||||
<para>
|
||||
The <command>DROP OPERATOR CLASS</command> statement is a
|
||||
<productname>PostgreSQL</productname>
|
||||
language extension.
|
||||
</para>
|
||||
<para>
|
||||
Refer to
|
||||
<xref linkend="sql-createopclass" endterm="sql-createopclass-title">
|
||||
for information on how to create operator classes.
|
||||
</para>
|
||||
</refsect2>
|
||||
</refsect1>
|
||||
|
||||
<refsect1 id="R1-SQL-DROPOPCLASS-2">
|
||||
<title>
|
||||
Usage
|
||||
</title>
|
||||
<para>
|
||||
Remove btree operator class <literal>widget_ops</literal>:
|
||||
|
||||
<programlisting>
|
||||
DROP OPERATOR CLASS widget_ops USING btree;
|
||||
</programlisting>
|
||||
|
||||
This command will not execute if there are any existing indexes
|
||||
that use the operator class. Add <literal>CASCADE</> to drop
|
||||
such indexes along with the operator class.
|
||||
</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1 id="R1-SQL-DROPOPCLASS-3">
|
||||
<title>
|
||||
Compatibility
|
||||
</title>
|
||||
|
||||
<refsect2 id="R2-SQL-DROPOPCLASS-4">
|
||||
<refsect2info>
|
||||
<date>2002-07-28</date>
|
||||
</refsect2info>
|
||||
<title>
|
||||
SQL92
|
||||
</title>
|
||||
<para>
|
||||
There is no <command>DROP OPERATOR CLASS</command> in
|
||||
<acronym>SQL92</acronym>.
|
||||
</para>
|
||||
</refsect2>
|
||||
</refsect1>
|
||||
</refentry>
|
||||
|
||||
<!-- Keep this comment at the end of the file
|
||||
Local variables:
|
||||
mode: sgml
|
||||
sgml-omittag:nil
|
||||
sgml-shorttag:t
|
||||
sgml-minimize-attributes:nil
|
||||
sgml-always-quote-attributes:t
|
||||
sgml-indent-step:1
|
||||
sgml-indent-data:t
|
||||
sgml-parent-document:nil
|
||||
sgml-default-dtd-file:"../reference.ced"
|
||||
sgml-exposed-tags:nil
|
||||
sgml-local-catalogs:"/usr/lib/sgml/catalog"
|
||||
sgml-local-ecat-files:nil
|
||||
End:
|
||||
-->
|
@ -1,5 +1,5 @@
|
||||
<!--
|
||||
$Header: /cvsroot/pgsql/doc/src/sgml/ref/drop_operator.sgml,v 1.17 2002/07/12 18:43:13 tgl Exp $
|
||||
$Header: /cvsroot/pgsql/doc/src/sgml/ref/drop_operator.sgml,v 1.18 2002/07/29 22:14:10 tgl Exp $
|
||||
PostgreSQL documentation
|
||||
-->
|
||||
|
||||
@ -172,10 +172,6 @@ ERROR: RemoveOperator: right unary operator '<replaceable class="PARAMETER">oper
|
||||
<xref linkend="sql-createoperator" endterm="sql-createoperator-title">
|
||||
for information on how to create operators.
|
||||
</para>
|
||||
<para>
|
||||
It is the user's responsibility to remove any access method
|
||||
operator classes that rely on the deleted operator.
|
||||
</para>
|
||||
</refsect2>
|
||||
</refsect1>
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
<!-- reference.sgml
|
||||
$Header: /cvsroot/pgsql/doc/src/sgml/reference.sgml,v 1.31 2002/07/22 08:57:15 ishii Exp $
|
||||
$Header: /cvsroot/pgsql/doc/src/sgml/reference.sgml,v 1.32 2002/07/29 22:14:10 tgl Exp $
|
||||
|
||||
PostgreSQL Reference Manual
|
||||
-->
|
||||
@ -70,6 +70,7 @@ PostgreSQL Reference Manual
|
||||
&createIndex;
|
||||
&createLanguage;
|
||||
&createOperator;
|
||||
&createOperatorClass;
|
||||
&createRule;
|
||||
&createSchema;
|
||||
&createSequence;
|
||||
@ -91,6 +92,7 @@ PostgreSQL Reference Manual
|
||||
&dropIndex;
|
||||
&dropLanguage;
|
||||
&dropOperator;
|
||||
&dropOperatorClass;
|
||||
&dropRule;
|
||||
&dropSchema;
|
||||
&dropSequence;
|
||||
|
@ -1,5 +1,5 @@
|
||||
<!--
|
||||
$Header: /cvsroot/pgsql/doc/src/sgml/release.sgml,v 1.143 2002/07/20 15:12:55 tgl Exp $
|
||||
$Header: /cvsroot/pgsql/doc/src/sgml/release.sgml,v 1.144 2002/07/29 22:14:10 tgl Exp $
|
||||
-->
|
||||
|
||||
<appendix id="release">
|
||||
@ -24,6 +24,7 @@ CDATA means the content is "SGML-free", so you can write without
|
||||
worries about funny characters.
|
||||
-->
|
||||
<literallayout><![CDATA[
|
||||
CREATE OPERATOR CLASS/DROP OPERATOR CLASS
|
||||
CREATE CAST/DROP CAST
|
||||
Sequences created by SERIAL column definitions now auto-drop with the column
|
||||
Most forms of DROP now support RESTRICT and CASCADE options
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/catalog/aclchk.c,v 1.71 2002/07/20 05:16:56 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/catalog/aclchk.c,v 1.72 2002/07/29 22:14:10 tgl Exp $
|
||||
*
|
||||
* NOTES
|
||||
* See acl.h.
|
||||
@ -26,6 +26,7 @@
|
||||
#include "catalog/pg_group.h"
|
||||
#include "catalog/pg_language.h"
|
||||
#include "catalog/pg_namespace.h"
|
||||
#include "catalog/pg_opclass.h"
|
||||
#include "catalog/pg_operator.h"
|
||||
#include "catalog/pg_proc.h"
|
||||
#include "catalog/pg_shadow.h"
|
||||
@ -1369,3 +1370,30 @@ pg_namespace_ownercheck(Oid nsp_oid, Oid userid)
|
||||
|
||||
return userid == owner_id;
|
||||
}
|
||||
|
||||
/*
|
||||
* Ownership check for an operator class (specified by OID).
|
||||
*/
|
||||
bool
|
||||
pg_opclass_ownercheck(Oid opc_oid, Oid userid)
|
||||
{
|
||||
HeapTuple tuple;
|
||||
AclId owner_id;
|
||||
|
||||
/* Superusers bypass all permission checking. */
|
||||
if (superuser_arg(userid))
|
||||
return true;
|
||||
|
||||
tuple = SearchSysCache(CLAOID,
|
||||
ObjectIdGetDatum(opc_oid),
|
||||
0, 0, 0);
|
||||
if (!HeapTupleIsValid(tuple))
|
||||
elog(ERROR, "pg_opclass_ownercheck: operator class %u not found",
|
||||
opc_oid);
|
||||
|
||||
owner_id = ((Form_pg_opclass) GETSTRUCT(tuple))->opcowner;
|
||||
|
||||
ReleaseSysCache(tuple);
|
||||
|
||||
return userid == owner_id;
|
||||
}
|
||||
|
@ -8,7 +8,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/catalog/dependency.c,v 1.6 2002/07/25 10:07:10 ishii Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/catalog/dependency.c,v 1.7 2002/07/29 22:14:10 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -21,15 +21,16 @@
|
||||
#include "catalog/heap.h"
|
||||
#include "catalog/index.h"
|
||||
#include "catalog/indexing.h"
|
||||
#include "catalog/namespace.h"
|
||||
#include "catalog/pg_attrdef.h"
|
||||
#include "catalog/pg_cast.h"
|
||||
#include "catalog/pg_constraint.h"
|
||||
#include "catalog/pg_conversion.h"
|
||||
#include "catalog/pg_depend.h"
|
||||
#include "catalog/pg_language.h"
|
||||
#include "catalog/pg_namespace.h"
|
||||
#include "catalog/pg_opclass.h"
|
||||
#include "catalog/pg_rewrite.h"
|
||||
#include "catalog/pg_trigger.h"
|
||||
#include "catalog/pg_type.h"
|
||||
#include "commands/comment.h"
|
||||
#include "commands/defrem.h"
|
||||
#include "commands/proclang.h"
|
||||
@ -40,6 +41,7 @@
|
||||
#include "optimizer/clauses.h"
|
||||
#include "parser/parsetree.h"
|
||||
#include "rewrite/rewriteRemove.h"
|
||||
#include "utils/builtins.h"
|
||||
#include "utils/fmgroids.h"
|
||||
#include "utils/lsyscache.h"
|
||||
#include "utils/syscache.h"
|
||||
@ -48,15 +50,16 @@
|
||||
/* This enum covers all system catalogs whose OIDs can appear in classid. */
|
||||
typedef enum ObjectClasses
|
||||
{
|
||||
OCLASS_CAST, /* pg_cast */
|
||||
OCLASS_CLASS, /* pg_class */
|
||||
OCLASS_PROC, /* pg_proc */
|
||||
OCLASS_TYPE, /* pg_type */
|
||||
OCLASS_CAST, /* pg_cast */
|
||||
OCLASS_CONSTRAINT, /* pg_constraint */
|
||||
OCLASS_CONVERSION, /* pg_conversion */
|
||||
OCLASS_DEFAULT, /* pg_attrdef */
|
||||
OCLASS_LANGUAGE, /* pg_language */
|
||||
OCLASS_OPERATOR, /* pg_operator */
|
||||
OCLASS_OPCLASS, /* pg_opclass */
|
||||
OCLASS_REWRITE, /* pg_rewrite */
|
||||
OCLASS_TRIGGER, /* pg_trigger */
|
||||
OCLASS_SCHEMA, /* pg_namespace */
|
||||
@ -579,6 +582,10 @@ doDeletion(const ObjectAddress *object)
|
||||
RemoveTypeById(object->objectId);
|
||||
break;
|
||||
|
||||
case OCLASS_CAST:
|
||||
DropCastById(object->objectId);
|
||||
break;
|
||||
|
||||
case OCLASS_CONSTRAINT:
|
||||
RemoveConstraintById(object->objectId);
|
||||
break;
|
||||
@ -599,6 +606,10 @@ doDeletion(const ObjectAddress *object)
|
||||
RemoveOperatorById(object->objectId);
|
||||
break;
|
||||
|
||||
case OCLASS_OPCLASS:
|
||||
RemoveOpClassById(object->objectId);
|
||||
break;
|
||||
|
||||
case OCLASS_REWRITE:
|
||||
RemoveRewriteRuleById(object->objectId);
|
||||
break;
|
||||
@ -611,10 +622,6 @@ doDeletion(const ObjectAddress *object)
|
||||
RemoveSchemaById(object->objectId);
|
||||
break;
|
||||
|
||||
case OCLASS_CAST:
|
||||
DropCastById(object->objectId);
|
||||
break;
|
||||
|
||||
default:
|
||||
elog(ERROR, "doDeletion: Unsupported object class %u",
|
||||
object->classId);
|
||||
@ -990,15 +997,16 @@ term_object_addresses(ObjectAddresses *addrs)
|
||||
static void
|
||||
init_object_classes(void)
|
||||
{
|
||||
object_classes[OCLASS_CAST] = get_system_catalog_relid(CastRelationName);
|
||||
object_classes[OCLASS_CLASS] = RelOid_pg_class;
|
||||
object_classes[OCLASS_PROC] = RelOid_pg_proc;
|
||||
object_classes[OCLASS_TYPE] = RelOid_pg_type;
|
||||
object_classes[OCLASS_CAST] = get_system_catalog_relid(CastRelationName);
|
||||
object_classes[OCLASS_CONSTRAINT] = get_system_catalog_relid(ConstraintRelationName);
|
||||
object_classes[OCLASS_CONVERSION] = get_system_catalog_relid(ConversionRelationName);
|
||||
object_classes[OCLASS_DEFAULT] = get_system_catalog_relid(AttrDefaultRelationName);
|
||||
object_classes[OCLASS_LANGUAGE] = get_system_catalog_relid(LanguageRelationName);
|
||||
object_classes[OCLASS_OPERATOR] = get_system_catalog_relid(OperatorRelationName);
|
||||
object_classes[OCLASS_OPCLASS] = get_system_catalog_relid(OperatorClassRelationName);
|
||||
object_classes[OCLASS_REWRITE] = get_system_catalog_relid(RewriteRelationName);
|
||||
object_classes[OCLASS_TRIGGER] = get_system_catalog_relid(TriggerRelationName);
|
||||
object_classes[OCLASS_SCHEMA] = get_system_catalog_relid(NamespaceRelationName);
|
||||
@ -1066,6 +1074,11 @@ getObjectClass(const ObjectAddress *object)
|
||||
Assert(object->objectSubId == 0);
|
||||
return OCLASS_OPERATOR;
|
||||
}
|
||||
if (object->classId == object_classes[OCLASS_OPCLASS])
|
||||
{
|
||||
Assert(object->objectSubId == 0);
|
||||
return OCLASS_OPCLASS;
|
||||
}
|
||||
if (object->classId == object_classes[OCLASS_REWRITE])
|
||||
{
|
||||
Assert(object->objectSubId == 0);
|
||||
@ -1101,10 +1114,6 @@ getObjectDescription(const ObjectAddress *object)
|
||||
|
||||
switch (getObjectClass(object))
|
||||
{
|
||||
case OCLASS_CAST:
|
||||
appendStringInfo(&buffer, "cast");
|
||||
break;
|
||||
|
||||
case OCLASS_CLASS:
|
||||
getRelationDescription(&buffer, object->objectId);
|
||||
if (object->objectSubId != 0)
|
||||
@ -1114,24 +1123,46 @@ getObjectDescription(const ObjectAddress *object)
|
||||
break;
|
||||
|
||||
case OCLASS_PROC:
|
||||
/* XXX could improve on this */
|
||||
appendStringInfo(&buffer, "function %s",
|
||||
get_func_name(object->objectId));
|
||||
format_procedure(object->objectId));
|
||||
break;
|
||||
|
||||
case OCLASS_TYPE:
|
||||
{
|
||||
HeapTuple typeTup;
|
||||
|
||||
typeTup = SearchSysCache(TYPEOID,
|
||||
ObjectIdGetDatum(object->objectId),
|
||||
0, 0, 0);
|
||||
if (!HeapTupleIsValid(typeTup))
|
||||
elog(ERROR, "getObjectDescription: Type %u does not exist",
|
||||
object->objectId);
|
||||
appendStringInfo(&buffer, "type %s",
|
||||
NameStr(((Form_pg_type) GETSTRUCT(typeTup))->typname));
|
||||
ReleaseSysCache(typeTup);
|
||||
format_type_be(object->objectId));
|
||||
break;
|
||||
|
||||
case OCLASS_CAST:
|
||||
{
|
||||
Relation castDesc;
|
||||
ScanKeyData skey[1];
|
||||
SysScanDesc rcscan;
|
||||
HeapTuple tup;
|
||||
Form_pg_cast castForm;
|
||||
|
||||
castDesc = heap_openr(CastRelationName, AccessShareLock);
|
||||
|
||||
ScanKeyEntryInitialize(&skey[0], 0x0,
|
||||
ObjectIdAttributeNumber, F_OIDEQ,
|
||||
ObjectIdGetDatum(object->objectId));
|
||||
|
||||
rcscan = systable_beginscan(castDesc, CastOidIndex, true,
|
||||
SnapshotNow, 1, skey);
|
||||
|
||||
tup = systable_getnext(rcscan);
|
||||
|
||||
if (!HeapTupleIsValid(tup))
|
||||
elog(ERROR, "getObjectDescription: Cast %u does not exist",
|
||||
object->objectId);
|
||||
|
||||
castForm = (Form_pg_cast) GETSTRUCT(tup);
|
||||
|
||||
appendStringInfo(&buffer, "cast from %s to %s",
|
||||
format_type_be(castForm->castsource),
|
||||
format_type_be(castForm->casttarget));
|
||||
|
||||
systable_endscan(rcscan);
|
||||
heap_close(castDesc, AccessShareLock);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1248,11 +1279,52 @@ getObjectDescription(const ObjectAddress *object)
|
||||
}
|
||||
|
||||
case OCLASS_OPERATOR:
|
||||
/* XXX could improve on this */
|
||||
appendStringInfo(&buffer, "operator %s",
|
||||
get_opname(object->objectId));
|
||||
format_operator(object->objectId));
|
||||
break;
|
||||
|
||||
case OCLASS_OPCLASS:
|
||||
{
|
||||
HeapTuple opcTup;
|
||||
Form_pg_opclass opcForm;
|
||||
HeapTuple amTup;
|
||||
Form_pg_am amForm;
|
||||
char *nspname;
|
||||
|
||||
opcTup = SearchSysCache(CLAOID,
|
||||
ObjectIdGetDatum(object->objectId),
|
||||
0, 0, 0);
|
||||
if (!HeapTupleIsValid(opcTup))
|
||||
elog(ERROR, "cache lookup of opclass %u failed",
|
||||
object->objectId);
|
||||
opcForm = (Form_pg_opclass) GETSTRUCT(opcTup);
|
||||
|
||||
/* Qualify the name if not visible in search path */
|
||||
if (OpclassIsVisible(object->objectId))
|
||||
nspname = NULL;
|
||||
else
|
||||
nspname = get_namespace_name(opcForm->opcnamespace);
|
||||
|
||||
appendStringInfo(&buffer, "operator class %s",
|
||||
quote_qualified_identifier(nspname,
|
||||
NameStr(opcForm->opcname)));
|
||||
|
||||
amTup = SearchSysCache(AMOID,
|
||||
ObjectIdGetDatum(opcForm->opcamid),
|
||||
0, 0, 0);
|
||||
if (!HeapTupleIsValid(amTup))
|
||||
elog(ERROR, "syscache lookup for AM %u failed",
|
||||
opcForm->opcamid);
|
||||
amForm = (Form_pg_am) GETSTRUCT(amTup);
|
||||
|
||||
appendStringInfo(&buffer, " for %s",
|
||||
NameStr(amForm->amname));
|
||||
|
||||
ReleaseSysCache(amTup);
|
||||
ReleaseSysCache(opcTup);
|
||||
break;
|
||||
}
|
||||
|
||||
case OCLASS_REWRITE:
|
||||
{
|
||||
Relation ruleDesc;
|
||||
@ -1323,17 +1395,13 @@ getObjectDescription(const ObjectAddress *object)
|
||||
|
||||
case OCLASS_SCHEMA:
|
||||
{
|
||||
HeapTuple schemaTup;
|
||||
char *nspname;
|
||||
|
||||
schemaTup = SearchSysCache(NAMESPACEOID,
|
||||
ObjectIdGetDatum(object->objectId),
|
||||
0, 0, 0);
|
||||
if (!HeapTupleIsValid(schemaTup))
|
||||
nspname = get_namespace_name(object->objectId);
|
||||
if (!nspname)
|
||||
elog(ERROR, "getObjectDescription: Schema %u does not exist",
|
||||
object->objectId);
|
||||
appendStringInfo(&buffer, "schema %s",
|
||||
NameStr(((Form_pg_namespace) GETSTRUCT(schemaTup))->nspname));
|
||||
ReleaseSysCache(schemaTup);
|
||||
appendStringInfo(&buffer, "schema %s", nspname);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1356,49 +1424,58 @@ getRelationDescription(StringInfo buffer, Oid relid)
|
||||
{
|
||||
HeapTuple relTup;
|
||||
Form_pg_class relForm;
|
||||
char *nspname;
|
||||
char *relname;
|
||||
|
||||
relTup = SearchSysCache(RELOID,
|
||||
ObjectIdGetDatum(relid),
|
||||
0, 0, 0);
|
||||
if (!HeapTupleIsValid(relTup))
|
||||
elog(ERROR, "getObjectDescription: Relation %u does not exist",
|
||||
relid);
|
||||
elog(ERROR, "cache lookup of relation %u failed", relid);
|
||||
relForm = (Form_pg_class) GETSTRUCT(relTup);
|
||||
|
||||
/* Qualify the name if not visible in search path */
|
||||
if (RelationIsVisible(relid))
|
||||
nspname = NULL;
|
||||
else
|
||||
nspname = get_namespace_name(relForm->relnamespace);
|
||||
|
||||
relname = quote_qualified_identifier(nspname, NameStr(relForm->relname));
|
||||
|
||||
switch (relForm->relkind)
|
||||
{
|
||||
case RELKIND_RELATION:
|
||||
appendStringInfo(buffer, "table %s",
|
||||
NameStr(relForm->relname));
|
||||
relname);
|
||||
break;
|
||||
case RELKIND_INDEX:
|
||||
appendStringInfo(buffer, "index %s",
|
||||
NameStr(relForm->relname));
|
||||
relname);
|
||||
break;
|
||||
case RELKIND_SPECIAL:
|
||||
appendStringInfo(buffer, "special system relation %s",
|
||||
NameStr(relForm->relname));
|
||||
relname);
|
||||
break;
|
||||
case RELKIND_SEQUENCE:
|
||||
appendStringInfo(buffer, "sequence %s",
|
||||
NameStr(relForm->relname));
|
||||
relname);
|
||||
break;
|
||||
case RELKIND_UNCATALOGED:
|
||||
appendStringInfo(buffer, "uncataloged table %s",
|
||||
NameStr(relForm->relname));
|
||||
relname);
|
||||
break;
|
||||
case RELKIND_TOASTVALUE:
|
||||
appendStringInfo(buffer, "toast table %s",
|
||||
NameStr(relForm->relname));
|
||||
relname);
|
||||
break;
|
||||
case RELKIND_VIEW:
|
||||
appendStringInfo(buffer, "view %s",
|
||||
NameStr(relForm->relname));
|
||||
relname);
|
||||
break;
|
||||
default:
|
||||
/* shouldn't get here */
|
||||
appendStringInfo(buffer, "relation %s",
|
||||
NameStr(relForm->relname));
|
||||
relname);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.186 2002/07/20 05:16:56 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.187 2002/07/29 22:14:10 tgl Exp $
|
||||
*
|
||||
*
|
||||
* INTERFACE ROUTINES
|
||||
@ -712,7 +712,7 @@ index_create(Oid heapRelationId,
|
||||
false, /* isDeferred */
|
||||
heapRelationId,
|
||||
indexInfo->ii_KeyAttrNumbers,
|
||||
indexInfo->ii_NumIndexAttrs,
|
||||
indexInfo->ii_NumKeyAttrs,
|
||||
InvalidOid, /* no domain */
|
||||
InvalidOid, /* no foreign key */
|
||||
NULL,
|
||||
@ -732,7 +732,7 @@ index_create(Oid heapRelationId,
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = 0; i < indexInfo->ii_NumIndexAttrs; i++)
|
||||
for (i = 0; i < indexInfo->ii_NumKeyAttrs; i++)
|
||||
{
|
||||
referenced.classId = RelOid_pg_class;
|
||||
referenced.objectId = heapRelationId;
|
||||
@ -742,6 +742,16 @@ index_create(Oid heapRelationId,
|
||||
}
|
||||
}
|
||||
|
||||
/* Store dependency on operator classes */
|
||||
referenced.classId = get_system_catalog_relid(OperatorClassRelationName);
|
||||
for (i = 0; i < indexInfo->ii_NumIndexAttrs; i++)
|
||||
{
|
||||
referenced.objectId = classObjectId[i];
|
||||
referenced.objectSubId = 0;
|
||||
|
||||
recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
|
||||
}
|
||||
|
||||
/* Store the dependency on the function (if appropriate) */
|
||||
if (OidIsValid(indexInfo->ii_FuncOid))
|
||||
{
|
||||
|
@ -4,7 +4,7 @@
|
||||
# Makefile for backend/commands
|
||||
#
|
||||
# IDENTIFICATION
|
||||
# $Header: /cvsroot/pgsql/src/backend/commands/Makefile,v 1.29 2002/07/11 07:39:27 ishii Exp $
|
||||
# $Header: /cvsroot/pgsql/src/backend/commands/Makefile,v 1.30 2002/07/29 22:14:10 tgl Exp $
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
|
||||
@ -15,7 +15,8 @@ include $(top_builddir)/src/Makefile.global
|
||||
OBJS = aggregatecmds.o analyze.o async.o cluster.o comment.o \
|
||||
conversioncmds.o copy.o \
|
||||
dbcommands.o define.o explain.o functioncmds.o \
|
||||
indexcmds.o lockcmds.o operatorcmds.o portalcmds.o proclang.o \
|
||||
indexcmds.o lockcmds.o operatorcmds.o opclasscmds.o \
|
||||
portalcmds.o proclang.o \
|
||||
schemacmds.o sequence.o tablecmds.o trigger.o typecmds.o user.o \
|
||||
vacuum.o vacuumlazy.o variable.o view.o
|
||||
|
||||
|
639
src/backend/commands/opclasscmds.c
Normal file
639
src/backend/commands/opclasscmds.c
Normal file
@ -0,0 +1,639 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* opclasscmds.c
|
||||
*
|
||||
* Routines for opclass manipulation commands
|
||||
*
|
||||
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/opclasscmds.c,v 1.1 2002/07/29 22:14:10 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
#include "postgres.h"
|
||||
|
||||
#include "access/genam.h"
|
||||
#include "access/heapam.h"
|
||||
#include "catalog/catname.h"
|
||||
#include "catalog/dependency.h"
|
||||
#include "catalog/indexing.h"
|
||||
#include "catalog/namespace.h"
|
||||
#include "catalog/pg_am.h"
|
||||
#include "catalog/pg_amop.h"
|
||||
#include "catalog/pg_amproc.h"
|
||||
#include "catalog/pg_opclass.h"
|
||||
#include "commands/defrem.h"
|
||||
#include "miscadmin.h"
|
||||
#include "parser/parse_func.h"
|
||||
#include "parser/parse_oper.h"
|
||||
#include "parser/parse_type.h"
|
||||
#include "utils/acl.h"
|
||||
#include "utils/builtins.h"
|
||||
#include "utils/fmgroids.h"
|
||||
#include "utils/lsyscache.h"
|
||||
#include "utils/syscache.h"
|
||||
|
||||
|
||||
static void storeOperators(Oid opclassoid, int numOperators,
|
||||
Oid *operators, bool *recheck);
|
||||
static void storeProcedures(Oid opclassoid, int numProcs, Oid *procedures);
|
||||
|
||||
|
||||
/*
|
||||
* DefineOpClass
|
||||
* Define a new index operator class.
|
||||
*/
|
||||
void
|
||||
DefineOpClass(CreateOpClassStmt *stmt)
|
||||
{
|
||||
char *opcname; /* name of opclass we're creating */
|
||||
Oid amoid, /* our AM's oid */
|
||||
typeoid, /* indexable datatype oid */
|
||||
storageoid, /* storage datatype oid, if any */
|
||||
namespaceoid, /* namespace to create opclass in */
|
||||
opclassoid; /* oid of opclass we create */
|
||||
int numOperators, /* amstrategies value */
|
||||
numProcs; /* amsupport value */
|
||||
Oid *operators, /* oids of operators, by strategy num */
|
||||
*procedures; /* oids of support procs */
|
||||
bool *recheck; /* do operators need recheck */
|
||||
List *iteml;
|
||||
Relation rel;
|
||||
HeapTuple tup;
|
||||
Datum values[Natts_pg_opclass];
|
||||
char nulls[Natts_pg_opclass];
|
||||
AclResult aclresult;
|
||||
NameData opcName;
|
||||
int i;
|
||||
ObjectAddress myself,
|
||||
referenced;
|
||||
|
||||
/* Convert list of names to a name and namespace */
|
||||
namespaceoid = QualifiedNameGetCreationNamespace(stmt->opclassname,
|
||||
&opcname);
|
||||
|
||||
/* Check we have creation rights in target namespace */
|
||||
aclresult = pg_namespace_aclcheck(namespaceoid, GetUserId(), ACL_CREATE);
|
||||
if (aclresult != ACLCHECK_OK)
|
||||
aclcheck_error(aclresult, get_namespace_name(namespaceoid));
|
||||
|
||||
/* Get necessary info about access method */
|
||||
tup = SearchSysCache(AMNAME,
|
||||
CStringGetDatum(stmt->amname),
|
||||
0, 0, 0);
|
||||
if (!HeapTupleIsValid(tup))
|
||||
elog(ERROR, "DefineOpClass: access method \"%s\" not found",
|
||||
stmt->amname);
|
||||
|
||||
amoid = HeapTupleGetOid(tup);
|
||||
numOperators = ((Form_pg_am) GETSTRUCT(tup))->amstrategies;
|
||||
numProcs = ((Form_pg_am) GETSTRUCT(tup))->amsupport;
|
||||
|
||||
/* XXX Should we make any privilege check against the AM? */
|
||||
|
||||
ReleaseSysCache(tup);
|
||||
|
||||
/* Look up the datatype */
|
||||
typeoid = typenameTypeId(stmt->datatype);
|
||||
|
||||
/* Check we have ownership of the datatype */
|
||||
if (!pg_type_ownercheck(typeoid, GetUserId()))
|
||||
aclcheck_error(ACLCHECK_NOT_OWNER, format_type_be(typeoid));
|
||||
|
||||
/* Storage datatype is optional */
|
||||
storageoid = InvalidOid;
|
||||
|
||||
/*
|
||||
* Create work arrays to hold info about operators and procedures.
|
||||
* We do this mainly so that we can detect duplicate strategy
|
||||
* numbers and support-proc numbers.
|
||||
*/
|
||||
operators = (Oid *) palloc(sizeof(Oid) * numOperators);
|
||||
MemSet(operators, 0, sizeof(Oid) * numOperators);
|
||||
procedures = (Oid *) palloc(sizeof(Oid) * numProcs);
|
||||
MemSet(procedures, 0, sizeof(Oid) * numProcs);
|
||||
recheck = (bool *) palloc(sizeof(bool) * numOperators);
|
||||
MemSet(recheck, 0, sizeof(bool) * numOperators);
|
||||
|
||||
/*
|
||||
* Scan the "items" list to obtain additional info.
|
||||
*/
|
||||
foreach(iteml, stmt->items)
|
||||
{
|
||||
CreateOpClassItem *item = lfirst(iteml);
|
||||
Oid operOid;
|
||||
Oid funcOid;
|
||||
AclResult aclresult;
|
||||
|
||||
Assert(IsA(item, CreateOpClassItem));
|
||||
switch (item->itemtype)
|
||||
{
|
||||
case OPCLASS_ITEM_OPERATOR:
|
||||
if (item->number <= 0 || item->number > numOperators)
|
||||
elog(ERROR, "DefineOpClass: invalid operator number %d,"
|
||||
" must be between 1 and %d",
|
||||
item->number, numOperators);
|
||||
if (operators[item->number - 1] != InvalidOid)
|
||||
elog(ERROR, "DefineOpClass: operator number %d appears more than once",
|
||||
item->number);
|
||||
if (item->args != NIL)
|
||||
{
|
||||
TypeName *typeName1 = (TypeName *) lfirst(item->args);
|
||||
TypeName *typeName2 = (TypeName *) lsecond(item->args);
|
||||
|
||||
operOid = LookupOperNameTypeNames(item->name,
|
||||
typeName1, typeName2,
|
||||
"DefineOpClass");
|
||||
/* No need to check for error */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Default to binary op on input datatype */
|
||||
operOid = LookupOperName(item->name, typeoid, typeoid);
|
||||
if (!OidIsValid(operOid))
|
||||
elog(ERROR, "DefineOpClass: Operator '%s' for types '%s' and '%s' does not exist",
|
||||
NameListToString(item->name),
|
||||
format_type_be(typeoid),
|
||||
format_type_be(typeoid));
|
||||
}
|
||||
/* Caller must have execute permission on operators */
|
||||
funcOid = get_opcode(operOid);
|
||||
aclresult = pg_proc_aclcheck(funcOid, GetUserId(),
|
||||
ACL_EXECUTE);
|
||||
if (aclresult != ACLCHECK_OK)
|
||||
aclcheck_error(aclresult, get_func_name(funcOid));
|
||||
operators[item->number - 1] = operOid;
|
||||
recheck[item->number - 1] = item->recheck;
|
||||
break;
|
||||
case OPCLASS_ITEM_FUNCTION:
|
||||
if (item->number <= 0 || item->number > numProcs)
|
||||
elog(ERROR, "DefineOpClass: invalid procedure number %d,"
|
||||
" must be between 1 and %d",
|
||||
item->number, numProcs);
|
||||
if (procedures[item->number - 1] != InvalidOid)
|
||||
elog(ERROR, "DefineOpClass: procedure number %d appears more than once",
|
||||
item->number);
|
||||
funcOid = LookupFuncNameTypeNames(item->name, item->args,
|
||||
true, "DefineOpClass");
|
||||
/* Caller must have execute permission on functions */
|
||||
aclresult = pg_proc_aclcheck(funcOid, GetUserId(),
|
||||
ACL_EXECUTE);
|
||||
if (aclresult != ACLCHECK_OK)
|
||||
aclcheck_error(aclresult, get_func_name(funcOid));
|
||||
procedures[item->number - 1] = funcOid;
|
||||
break;
|
||||
case OPCLASS_ITEM_STORAGETYPE:
|
||||
if (OidIsValid(storageoid))
|
||||
elog(ERROR, "DefineOpClass: storage type specified more than once");
|
||||
storageoid = typenameTypeId(item->storedtype);
|
||||
break;
|
||||
default:
|
||||
elog(ERROR, "DefineOpClass: bogus item type %d",
|
||||
item->itemtype);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If storagetype is specified, make sure it's legal.
|
||||
*/
|
||||
if (OidIsValid(storageoid))
|
||||
{
|
||||
/* Just drop the spec if same as column datatype */
|
||||
if (storageoid == typeoid)
|
||||
storageoid = InvalidOid;
|
||||
else
|
||||
{
|
||||
/*
|
||||
* Currently, only GiST allows storagetype different from
|
||||
* datatype. This hardcoded test should be eliminated in
|
||||
* favor of adding another boolean column to pg_am ...
|
||||
*/
|
||||
if (amoid != GIST_AM_OID)
|
||||
elog(ERROR, "Storage type may not be different from datatype for access method %s",
|
||||
stmt->amname);
|
||||
}
|
||||
}
|
||||
|
||||
rel = heap_openr(OperatorClassRelationName, RowExclusiveLock);
|
||||
|
||||
/*
|
||||
* Make sure there is no existing opclass of this name (this is
|
||||
* just to give a more friendly error message than "duplicate key").
|
||||
*/
|
||||
if (SearchSysCacheExists(CLAAMNAMENSP,
|
||||
ObjectIdGetDatum(amoid),
|
||||
CStringGetDatum(opcname),
|
||||
ObjectIdGetDatum(namespaceoid),
|
||||
0))
|
||||
elog(ERROR, "Operator class \"%s\" already exists for access method \"%s\"",
|
||||
opcname, stmt->amname);
|
||||
|
||||
/*
|
||||
* If we are creating a default opclass, check there isn't one already.
|
||||
* (XXX should we restrict this test to visible opclasses?)
|
||||
*/
|
||||
if (stmt->isDefault)
|
||||
{
|
||||
ScanKeyData skey[1];
|
||||
SysScanDesc scan;
|
||||
|
||||
ScanKeyEntryInitialize(&skey[0], 0x0,
|
||||
Anum_pg_opclass_opcamid, F_OIDEQ,
|
||||
ObjectIdGetDatum(amoid));
|
||||
|
||||
scan = systable_beginscan(rel, OpclassAmNameNspIndex, true,
|
||||
SnapshotNow, 1, skey);
|
||||
|
||||
while (HeapTupleIsValid(tup = systable_getnext(scan)))
|
||||
{
|
||||
Form_pg_opclass opclass = (Form_pg_opclass) GETSTRUCT(tup);
|
||||
|
||||
if (opclass->opcintype == typeoid && opclass->opcdefault)
|
||||
elog(ERROR, "Can't add class \"%s\" as default for type %s"
|
||||
"\n\tclass \"%s\" already is the default",
|
||||
opcname,
|
||||
TypeNameToString(stmt->datatype),
|
||||
NameStr(opclass->opcname));
|
||||
}
|
||||
|
||||
systable_endscan(scan);
|
||||
}
|
||||
|
||||
/*
|
||||
* Okay, let's create the pg_opclass entry.
|
||||
*/
|
||||
for (i = 0; i < Natts_pg_opclass; ++i)
|
||||
{
|
||||
nulls[i] = ' ';
|
||||
values[i] = (Datum) NULL; /* redundant, but safe */
|
||||
}
|
||||
|
||||
i = 0;
|
||||
values[i++] = ObjectIdGetDatum(amoid); /* opcamid */
|
||||
namestrcpy(&opcName, opcname);
|
||||
values[i++] = NameGetDatum(&opcName); /* opcname */
|
||||
values[i++] = ObjectIdGetDatum(namespaceoid); /* opcnamespace */
|
||||
values[i++] = Int32GetDatum(GetUserId()); /* opcowner */
|
||||
values[i++] = ObjectIdGetDatum(typeoid); /* opcintype */
|
||||
values[i++] = BoolGetDatum(stmt->isDefault); /* opcdefault */
|
||||
values[i++] = ObjectIdGetDatum(storageoid); /* opckeytype */
|
||||
|
||||
tup = heap_formtuple(rel->rd_att, values, nulls);
|
||||
|
||||
opclassoid = simple_heap_insert(rel, tup);
|
||||
|
||||
if (RelationGetForm(rel)->relhasindex)
|
||||
{
|
||||
Relation idescs[Num_pg_opclass_indices];
|
||||
|
||||
CatalogOpenIndices(Num_pg_opclass_indices, Name_pg_opclass_indices,
|
||||
idescs);
|
||||
CatalogIndexInsert(idescs, Num_pg_opclass_indices, rel, tup);
|
||||
CatalogCloseIndices(Num_pg_opclass_indices, idescs);
|
||||
}
|
||||
|
||||
heap_freetuple(tup);
|
||||
|
||||
/*
|
||||
* Now add tuples to pg_amop and pg_amproc tying in the
|
||||
* operators and functions.
|
||||
*/
|
||||
storeOperators(opclassoid, numOperators, operators, recheck);
|
||||
storeProcedures(opclassoid, numProcs, procedures);
|
||||
|
||||
/*
|
||||
* Create dependencies. Note: we do not create a dependency link to
|
||||
* the AM, because we don't currently support DROP ACCESS METHOD.
|
||||
*/
|
||||
myself.classId = RelationGetRelid(rel);
|
||||
myself.objectId = opclassoid;
|
||||
myself.objectSubId = 0;
|
||||
|
||||
/* dependency on namespace */
|
||||
referenced.classId = get_system_catalog_relid(NamespaceRelationName);
|
||||
referenced.objectId = namespaceoid;
|
||||
referenced.objectSubId = 0;
|
||||
recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
|
||||
|
||||
/* dependency on indexed datatype */
|
||||
referenced.classId = RelOid_pg_type;
|
||||
referenced.objectId = typeoid;
|
||||
referenced.objectSubId = 0;
|
||||
recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
|
||||
|
||||
/* dependency on storage datatype */
|
||||
if (OidIsValid(storageoid))
|
||||
{
|
||||
referenced.classId = RelOid_pg_type;
|
||||
referenced.objectId = storageoid;
|
||||
referenced.objectSubId = 0;
|
||||
recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
|
||||
}
|
||||
|
||||
/* dependencies on operators */
|
||||
referenced.classId = get_system_catalog_relid(OperatorRelationName);
|
||||
for (i = 0; i < numOperators; i++)
|
||||
{
|
||||
if (operators[i] == InvalidOid)
|
||||
continue;
|
||||
referenced.objectId = operators[i];
|
||||
referenced.objectSubId = 0;
|
||||
recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
|
||||
}
|
||||
|
||||
/* dependencies on procedures */
|
||||
for (i = 0; i < numProcs; i++)
|
||||
{
|
||||
if (procedures[i] == InvalidOid)
|
||||
continue;
|
||||
referenced.classId = RelOid_pg_proc;
|
||||
referenced.objectId = procedures[i];
|
||||
referenced.objectSubId = 0;
|
||||
recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
|
||||
}
|
||||
|
||||
heap_close(rel, RowExclusiveLock);
|
||||
}
|
||||
|
||||
/*
|
||||
* Dump the operators to pg_amop
|
||||
*/
|
||||
static void
|
||||
storeOperators(Oid opclassoid, int numOperators,
|
||||
Oid *operators, bool *recheck)
|
||||
{
|
||||
Relation rel;
|
||||
Datum values[Natts_pg_amop];
|
||||
char nulls[Natts_pg_amop];
|
||||
HeapTuple tup;
|
||||
int i, j;
|
||||
|
||||
rel = heap_openr(AccessMethodOperatorRelationName, RowExclusiveLock);
|
||||
|
||||
for (j = 0; j < numOperators; j++)
|
||||
{
|
||||
if (operators[j] == InvalidOid)
|
||||
continue;
|
||||
|
||||
for (i = 0; i < Natts_pg_amop; ++i)
|
||||
{
|
||||
nulls[i] = ' ';
|
||||
values[i] = (Datum) NULL;
|
||||
}
|
||||
|
||||
i = 0;
|
||||
values[i++] = ObjectIdGetDatum(opclassoid); /* amopclaid */
|
||||
values[i++] = Int16GetDatum(j + 1); /* amopstrategy */
|
||||
values[i++] = BoolGetDatum(recheck[j]); /* amopreqcheck */
|
||||
values[i++] = ObjectIdGetDatum(operators[j]); /* amopopr */
|
||||
|
||||
tup = heap_formtuple(rel->rd_att, values, nulls);
|
||||
|
||||
simple_heap_insert(rel, tup);
|
||||
|
||||
if (RelationGetForm(rel)->relhasindex)
|
||||
{
|
||||
Relation idescs[Num_pg_amop_indices];
|
||||
|
||||
CatalogOpenIndices(Num_pg_amop_indices, Name_pg_amop_indices,
|
||||
idescs);
|
||||
CatalogIndexInsert(idescs, Num_pg_amop_indices, rel, tup);
|
||||
CatalogCloseIndices(Num_pg_amop_indices, idescs);
|
||||
}
|
||||
heap_freetuple(tup);
|
||||
}
|
||||
|
||||
heap_close(rel, RowExclusiveLock);
|
||||
}
|
||||
|
||||
/*
|
||||
* Dump the procedures (support routines) to pg_amproc
|
||||
*/
|
||||
static void
|
||||
storeProcedures(Oid opclassoid, int numProcs, Oid *procedures)
|
||||
{
|
||||
Relation rel;
|
||||
Datum values[Natts_pg_amproc];
|
||||
char nulls[Natts_pg_amproc];
|
||||
HeapTuple tup;
|
||||
int i, j;
|
||||
|
||||
rel = heap_openr(AccessMethodProcedureRelationName, RowExclusiveLock);
|
||||
|
||||
for (j = 0; j < numProcs; j++)
|
||||
{
|
||||
if (procedures[j] == InvalidOid)
|
||||
continue;
|
||||
|
||||
for (i = 0; i < Natts_pg_amproc; ++i)
|
||||
{
|
||||
nulls[i] = ' ';
|
||||
values[i] = (Datum) NULL;
|
||||
}
|
||||
|
||||
i = 0;
|
||||
values[i++] = ObjectIdGetDatum(opclassoid); /* amopclaid */
|
||||
values[i++] = Int16GetDatum(j + 1); /* amprocnum */
|
||||
values[i++] = ObjectIdGetDatum(procedures[j]); /* amproc */
|
||||
|
||||
tup = heap_formtuple(rel->rd_att, values, nulls);
|
||||
|
||||
simple_heap_insert(rel, tup);
|
||||
|
||||
if (RelationGetForm(rel)->relhasindex)
|
||||
{
|
||||
Relation idescs[Num_pg_amproc_indices];
|
||||
|
||||
CatalogOpenIndices(Num_pg_amproc_indices, Name_pg_amproc_indices,
|
||||
idescs);
|
||||
CatalogIndexInsert(idescs, Num_pg_amproc_indices, rel, tup);
|
||||
CatalogCloseIndices(Num_pg_amproc_indices, idescs);
|
||||
}
|
||||
heap_freetuple(tup);
|
||||
}
|
||||
|
||||
heap_close(rel, RowExclusiveLock);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* RemoveOpClass
|
||||
* Deletes an opclass.
|
||||
*/
|
||||
void
|
||||
RemoveOpClass(RemoveOpClassStmt *stmt)
|
||||
{
|
||||
Oid amID, opcID;
|
||||
char *catalogname;
|
||||
char *schemaname = NULL;
|
||||
char *opcname = NULL;
|
||||
HeapTuple tuple;
|
||||
ObjectAddress object;
|
||||
|
||||
/*
|
||||
* Get the access method's OID.
|
||||
*/
|
||||
amID = GetSysCacheOid(AMNAME,
|
||||
CStringGetDatum(stmt->amname),
|
||||
0, 0, 0);
|
||||
if (!OidIsValid(amID))
|
||||
elog(ERROR, "RemoveOpClass: access method \"%s\" not found",
|
||||
stmt->amname);
|
||||
|
||||
/*
|
||||
* Look up the opclass.
|
||||
*/
|
||||
|
||||
/* deconstruct the name list */
|
||||
switch (length(stmt->opclassname))
|
||||
{
|
||||
case 1:
|
||||
opcname = strVal(lfirst(stmt->opclassname));
|
||||
break;
|
||||
case 2:
|
||||
schemaname = strVal(lfirst(stmt->opclassname));
|
||||
opcname = strVal(lsecond(stmt->opclassname));
|
||||
break;
|
||||
case 3:
|
||||
catalogname = strVal(lfirst(stmt->opclassname));
|
||||
schemaname = strVal(lsecond(stmt->opclassname));
|
||||
opcname = strVal(lfirst(lnext(lnext(stmt->opclassname))));
|
||||
/*
|
||||
* 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 opclass name (too many dotted names): %s",
|
||||
NameListToString(stmt->opclassname));
|
||||
break;
|
||||
}
|
||||
|
||||
if (schemaname)
|
||||
{
|
||||
/* Look in specific schema only */
|
||||
Oid namespaceId;
|
||||
|
||||
namespaceId = GetSysCacheOid(NAMESPACENAME,
|
||||
CStringGetDatum(schemaname),
|
||||
0, 0, 0);
|
||||
if (!OidIsValid(namespaceId))
|
||||
elog(ERROR, "Namespace \"%s\" does not exist",
|
||||
schemaname);
|
||||
tuple = SearchSysCache(CLAAMNAMENSP,
|
||||
ObjectIdGetDatum(amID),
|
||||
PointerGetDatum(opcname),
|
||||
ObjectIdGetDatum(namespaceId),
|
||||
0);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Unqualified opclass name, so search the search path */
|
||||
opcID = OpclassnameGetOpcid(amID, opcname);
|
||||
if (!OidIsValid(opcID))
|
||||
elog(ERROR, "RemoveOpClass: operator class \"%s\" not supported by access method \"%s\"",
|
||||
opcname, stmt->amname);
|
||||
tuple = SearchSysCache(CLAOID,
|
||||
ObjectIdGetDatum(opcID),
|
||||
0, 0, 0);
|
||||
}
|
||||
|
||||
if (!HeapTupleIsValid(tuple))
|
||||
elog(ERROR, "RemoveOpClass: operator class \"%s\" not supported by access method \"%s\"",
|
||||
NameListToString(stmt->opclassname), stmt->amname);
|
||||
|
||||
opcID = HeapTupleGetOid(tuple);
|
||||
|
||||
/* Permission check: must own opclass or its namespace */
|
||||
if (!pg_opclass_ownercheck(opcID, GetUserId()) &&
|
||||
!pg_namespace_ownercheck(((Form_pg_opclass) GETSTRUCT(tuple))->opcnamespace,
|
||||
GetUserId()))
|
||||
aclcheck_error(ACLCHECK_NOT_OWNER,
|
||||
NameListToString(stmt->opclassname));
|
||||
|
||||
ReleaseSysCache(tuple);
|
||||
|
||||
/*
|
||||
* Do the deletion
|
||||
*/
|
||||
object.classId = get_system_catalog_relid(OperatorClassRelationName);
|
||||
object.objectId = opcID;
|
||||
object.objectSubId = 0;
|
||||
|
||||
performDeletion(&object, stmt->behavior);
|
||||
}
|
||||
|
||||
/*
|
||||
* Guts of opclass deletion.
|
||||
*/
|
||||
void
|
||||
RemoveOpClassById(Oid opclassOid)
|
||||
{
|
||||
Relation rel;
|
||||
HeapTuple tup;
|
||||
ScanKeyData skey[1];
|
||||
SysScanDesc scan;
|
||||
|
||||
/*
|
||||
* First remove the pg_opclass entry itself.
|
||||
*/
|
||||
rel = heap_openr(OperatorClassRelationName, RowExclusiveLock);
|
||||
|
||||
tup = SearchSysCache(CLAOID,
|
||||
ObjectIdGetDatum(opclassOid),
|
||||
0, 0, 0);
|
||||
if (!HeapTupleIsValid(tup)) /* should not happen */
|
||||
elog(ERROR, "RemoveOpClassById: couldn't find pg_class entry %u",
|
||||
opclassOid);
|
||||
|
||||
simple_heap_delete(rel, &tup->t_self);
|
||||
|
||||
ReleaseSysCache(tup);
|
||||
|
||||
heap_close(rel, RowExclusiveLock);
|
||||
|
||||
/*
|
||||
* Remove associated entries in pg_amop.
|
||||
*/
|
||||
ScanKeyEntryInitialize(&skey[0], 0,
|
||||
Anum_pg_amop_amopclaid, F_OIDEQ,
|
||||
ObjectIdGetDatum(opclassOid));
|
||||
|
||||
rel = heap_openr(AccessMethodOperatorRelationName, RowExclusiveLock);
|
||||
|
||||
scan = systable_beginscan(rel, AccessMethodStrategyIndex, true,
|
||||
SnapshotNow, 1, skey);
|
||||
|
||||
while (HeapTupleIsValid(tup = systable_getnext(scan)))
|
||||
{
|
||||
simple_heap_delete(rel, &tup->t_self);
|
||||
}
|
||||
|
||||
systable_endscan(scan);
|
||||
heap_close(rel, RowExclusiveLock);
|
||||
|
||||
/*
|
||||
* Remove associated entries in pg_amproc.
|
||||
*/
|
||||
ScanKeyEntryInitialize(&skey[0], 0,
|
||||
Anum_pg_amproc_amopclaid, F_OIDEQ,
|
||||
ObjectIdGetDatum(opclassOid));
|
||||
|
||||
rel = heap_openr(AccessMethodProcedureRelationName, RowExclusiveLock);
|
||||
|
||||
scan = systable_beginscan(rel, AccessMethodProcedureIndex, true,
|
||||
SnapshotNow, 1, skey);
|
||||
|
||||
while (HeapTupleIsValid(tup = systable_getnext(scan)))
|
||||
{
|
||||
simple_heap_delete(rel, &tup->t_self);
|
||||
}
|
||||
|
||||
systable_endscan(scan);
|
||||
heap_close(rel, RowExclusiveLock);
|
||||
}
|
@ -15,7 +15,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.197 2002/07/24 19:11:10 petere Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.198 2002/07/29 22:14:10 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -2147,6 +2147,19 @@ _copyRemoveOperStmt(RemoveOperStmt *from)
|
||||
return newnode;
|
||||
}
|
||||
|
||||
static RemoveOpClassStmt *
|
||||
_copyRemoveOpClassStmt(RemoveOpClassStmt *from)
|
||||
{
|
||||
RemoveOpClassStmt *newnode = makeNode(RemoveOpClassStmt);
|
||||
|
||||
Node_Copy(from, newnode, opclassname);
|
||||
if (from->amname)
|
||||
newnode->amname = pstrdup(from->amname);
|
||||
newnode->behavior = from->behavior;
|
||||
|
||||
return newnode;
|
||||
}
|
||||
|
||||
static RenameStmt *
|
||||
_copyRenameStmt(RenameStmt *from)
|
||||
{
|
||||
@ -2252,6 +2265,36 @@ _copyCreateDomainStmt(CreateDomainStmt *from)
|
||||
return newnode;
|
||||
}
|
||||
|
||||
static CreateOpClassStmt *
|
||||
_copyCreateOpClassStmt(CreateOpClassStmt *from)
|
||||
{
|
||||
CreateOpClassStmt *newnode = makeNode(CreateOpClassStmt);
|
||||
|
||||
Node_Copy(from, newnode, opclassname);
|
||||
if (from->amname)
|
||||
newnode->amname = pstrdup(from->amname);
|
||||
Node_Copy(from, newnode, datatype);
|
||||
Node_Copy(from, newnode, items);
|
||||
newnode->isDefault = from->isDefault;
|
||||
|
||||
return newnode;
|
||||
}
|
||||
|
||||
static CreateOpClassItem *
|
||||
_copyCreateOpClassItem(CreateOpClassItem *from)
|
||||
{
|
||||
CreateOpClassItem *newnode = makeNode(CreateOpClassItem);
|
||||
|
||||
newnode->itemtype = from->itemtype;
|
||||
Node_Copy(from, newnode, name);
|
||||
Node_Copy(from, newnode, args);
|
||||
newnode->number = from->number;
|
||||
newnode->recheck = from->recheck;
|
||||
Node_Copy(from, newnode, storedtype);
|
||||
|
||||
return newnode;
|
||||
}
|
||||
|
||||
static CreatedbStmt *
|
||||
_copyCreatedbStmt(CreatedbStmt *from)
|
||||
{
|
||||
@ -2872,6 +2915,9 @@ copyObject(void *from)
|
||||
case T_RemoveOperStmt:
|
||||
retval = _copyRemoveOperStmt(from);
|
||||
break;
|
||||
case T_RemoveOpClassStmt:
|
||||
retval = _copyRemoveOpClassStmt(from);
|
||||
break;
|
||||
case T_RenameStmt:
|
||||
retval = _copyRenameStmt(from);
|
||||
break;
|
||||
@ -2899,6 +2945,12 @@ copyObject(void *from)
|
||||
case T_CreateDomainStmt:
|
||||
retval = _copyCreateDomainStmt(from);
|
||||
break;
|
||||
case T_CreateOpClassStmt:
|
||||
retval = _copyCreateOpClassStmt(from);
|
||||
break;
|
||||
case T_CreateOpClassItem:
|
||||
retval = _copyCreateOpClassItem(from);
|
||||
break;
|
||||
case T_CreatedbStmt:
|
||||
retval = _copyCreatedbStmt(from);
|
||||
break;
|
||||
|
@ -20,7 +20,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.144 2002/07/24 19:11:10 petere Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.145 2002/07/29 22:14:10 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -976,6 +976,18 @@ _equalRemoveOperStmt(RemoveOperStmt *a, RemoveOperStmt *b)
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
_equalRemoveOpClassStmt(RemoveOpClassStmt *a, RemoveOpClassStmt *b)
|
||||
{
|
||||
if (!equal(a->opclassname, b->opclassname))
|
||||
return false;
|
||||
if (!equalstr(a->amname, b->amname))
|
||||
return false;
|
||||
if (a->behavior != b->behavior)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
_equalRenameStmt(RenameStmt *a, RenameStmt *b)
|
||||
@ -1082,6 +1094,42 @@ _equalCreateDomainStmt(CreateDomainStmt *a, CreateDomainStmt *b)
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
_equalCreateOpClassStmt(CreateOpClassStmt *a, CreateOpClassStmt *b)
|
||||
{
|
||||
if (!equal(a->opclassname, b->opclassname))
|
||||
return false;
|
||||
if (!equalstr(a->amname, b->amname))
|
||||
return false;
|
||||
if (!equal(a->datatype, b->datatype))
|
||||
return false;
|
||||
if (!equal(a->items, b->items))
|
||||
return false;
|
||||
if (a->isDefault != b->isDefault)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
_equalCreateOpClassItem(CreateOpClassItem *a, CreateOpClassItem *b)
|
||||
{
|
||||
if (a->itemtype != b->itemtype)
|
||||
return false;
|
||||
if (!equal(a->name, b->name))
|
||||
return false;
|
||||
if (!equal(a->args, b->args))
|
||||
return false;
|
||||
if (a->number != b->number)
|
||||
return false;
|
||||
if (a->recheck != b->recheck)
|
||||
return false;
|
||||
if (!equal(a->storedtype, b->storedtype))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
_equalCreatedbStmt(CreatedbStmt *a, CreatedbStmt *b)
|
||||
{
|
||||
@ -2036,6 +2084,9 @@ equal(void *a, void *b)
|
||||
case T_RemoveOperStmt:
|
||||
retval = _equalRemoveOperStmt(a, b);
|
||||
break;
|
||||
case T_RemoveOpClassStmt:
|
||||
retval = _equalRemoveOpClassStmt(a, b);
|
||||
break;
|
||||
case T_RenameStmt:
|
||||
retval = _equalRenameStmt(a, b);
|
||||
break;
|
||||
@ -2063,6 +2114,12 @@ equal(void *a, void *b)
|
||||
case T_CreateDomainStmt:
|
||||
retval = _equalCreateDomainStmt(a, b);
|
||||
break;
|
||||
case T_CreateOpClassStmt:
|
||||
retval = _equalCreateOpClassStmt(a, b);
|
||||
break;
|
||||
case T_CreateOpClassItem:
|
||||
retval = _equalCreateOpClassItem(a, b);
|
||||
break;
|
||||
case T_CreatedbStmt:
|
||||
retval = _equalCreatedbStmt(a, b);
|
||||
break;
|
||||
|
@ -11,7 +11,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.349 2002/07/24 19:11:10 petere Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.350 2002/07/29 22:14:10 tgl Exp $
|
||||
*
|
||||
* HISTORY
|
||||
* AUTHOR DATE MAJOR EVENT
|
||||
@ -136,11 +136,11 @@ static void doNegateFloat(Value *v);
|
||||
AlterTableStmt, AlterUserStmt, AlterUserSetStmt,
|
||||
AnalyzeStmt, ClosePortalStmt, ClusterStmt, CommentStmt,
|
||||
ConstraintsSetStmt, CopyStmt, CreateAsStmt, CreateCastStmt,
|
||||
CreateDomainStmt, CreateGroupStmt, CreatePLangStmt,
|
||||
CreateDomainStmt, CreateGroupStmt, CreateOpClassStmt, CreatePLangStmt,
|
||||
CreateSchemaStmt, CreateSeqStmt, CreateStmt,
|
||||
CreateAssertStmt, CreateTrigStmt, CreateUserStmt,
|
||||
CreatedbStmt, CursorStmt, DefineStmt, DeleteStmt,
|
||||
DropGroupStmt, DropPLangStmt, DropStmt,
|
||||
DropGroupStmt, DropOpClassStmt, DropPLangStmt, DropStmt,
|
||||
DropAssertStmt, DropTrigStmt, DropRuleStmt, DropCastStmt,
|
||||
DropUserStmt, DropdbStmt, ExplainStmt, FetchStmt,
|
||||
GrantStmt, IndexStmt, InsertStmt, ListenStmt, LoadStmt,
|
||||
@ -156,7 +156,7 @@ static void doNegateFloat(Value *v);
|
||||
%type <node> select_no_parens, select_with_parens, select_clause,
|
||||
simple_select
|
||||
|
||||
%type <node> alter_column_default
|
||||
%type <node> alter_column_default, opclass_item
|
||||
%type <ival> add_drop
|
||||
|
||||
%type <dbehavior> opt_drop_behavior
|
||||
@ -218,7 +218,7 @@ static void doNegateFloat(Value *v);
|
||||
target_list, update_target_list, insert_column_list,
|
||||
insert_target_list, def_list, opt_indirection,
|
||||
group_clause, TriggerFuncArgs, select_limit,
|
||||
opt_select_limit
|
||||
opt_select_limit, opclass_item_list
|
||||
|
||||
%type <range> into_clause, OptTempTableName
|
||||
|
||||
@ -240,7 +240,7 @@ static void doNegateFloat(Value *v);
|
||||
|
||||
%type <boolean> opt_instead, opt_cursor
|
||||
%type <boolean> index_opt_unique, opt_verbose, opt_full
|
||||
%type <boolean> opt_freeze, opt_default
|
||||
%type <boolean> opt_freeze, opt_default, opt_recheck
|
||||
%type <defelt> opt_binary, opt_oids, copy_delimiter
|
||||
|
||||
%type <boolean> copy_from
|
||||
@ -326,7 +326,7 @@ static void doNegateFloat(Value *v);
|
||||
BOOLEAN, BY,
|
||||
|
||||
CACHE, CALLED, CASCADE, CASE, CAST, CHAIN, CHAR_P,
|
||||
CHARACTER, CHARACTERISTICS, CHECK, CHECKPOINT, CLOSE,
|
||||
CHARACTER, CHARACTERISTICS, CHECK, CHECKPOINT, CLASS, CLOSE,
|
||||
CLUSTER, COALESCE, COLLATE, COLUMN, COMMENT, COMMIT,
|
||||
COMMITTED, CONSTRAINT, CONSTRAINTS, CONVERSION_P, COPY, CREATE, CREATEDB,
|
||||
CREATEUSER, CROSS, CURRENT_DATE, CURRENT_TIME,
|
||||
@ -371,7 +371,7 @@ static void doNegateFloat(Value *v);
|
||||
PRECISION, PRIMARY, PRIOR, PRIVILEGES, PROCEDURE,
|
||||
PROCEDURAL,
|
||||
|
||||
READ, REAL, REFERENCES, REINDEX, RELATIVE, RENAME, REPLACE,
|
||||
READ, REAL, RECHECK, REFERENCES, REINDEX, RELATIVE, RENAME, REPLACE,
|
||||
RESET, RESTRICT, RETURNS, REVOKE, RIGHT, ROLLBACK, ROW,
|
||||
RULE,
|
||||
|
||||
@ -481,6 +481,7 @@ stmt :
|
||||
| CreateSchemaStmt
|
||||
| CreateGroupStmt
|
||||
| CreateSeqStmt
|
||||
| CreateOpClassStmt
|
||||
| CreatePLangStmt
|
||||
| CreateAssertStmt
|
||||
| CreateTrigStmt
|
||||
@ -492,6 +493,7 @@ stmt :
|
||||
| CommentStmt
|
||||
| DropCastStmt
|
||||
| DropGroupStmt
|
||||
| DropOpClassStmt
|
||||
| DropPLangStmt
|
||||
| DropAssertStmt
|
||||
| DropTrigStmt
|
||||
@ -2265,6 +2267,93 @@ def_arg: func_return { $$ = (Node *)$1; }
|
||||
;
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* QUERIES :
|
||||
* CREATE OPERATOR CLASS ...
|
||||
* DROP OPERATOR CLASS ...
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
CreateOpClassStmt:
|
||||
CREATE OPERATOR CLASS any_name opt_default FOR TYPE_P Typename
|
||||
USING access_method AS opclass_item_list
|
||||
{
|
||||
CreateOpClassStmt *n = makeNode(CreateOpClassStmt);
|
||||
n->opclassname = $4;
|
||||
n->isDefault = $5;
|
||||
n->datatype = $8;
|
||||
n->amname = $10;
|
||||
n->items = $12;
|
||||
$$ = (Node *) n;
|
||||
}
|
||||
;
|
||||
|
||||
opclass_item_list:
|
||||
opclass_item { $$ = makeList1($1); }
|
||||
| opclass_item_list ',' opclass_item { $$ = lappend($1, $3); }
|
||||
;
|
||||
|
||||
opclass_item:
|
||||
OPERATOR Iconst any_operator opt_recheck
|
||||
{
|
||||
CreateOpClassItem *n = makeNode(CreateOpClassItem);
|
||||
n->itemtype = OPCLASS_ITEM_OPERATOR;
|
||||
n->name = $3;
|
||||
n->args = NIL;
|
||||
n->number = $2;
|
||||
n->recheck = $4;
|
||||
$$ = (Node *) n;
|
||||
}
|
||||
| OPERATOR Iconst any_operator '(' oper_argtypes ')' opt_recheck
|
||||
{
|
||||
CreateOpClassItem *n = makeNode(CreateOpClassItem);
|
||||
n->itemtype = OPCLASS_ITEM_OPERATOR;
|
||||
n->name = $3;
|
||||
n->args = $5;
|
||||
n->number = $2;
|
||||
n->recheck = $7;
|
||||
$$ = (Node *) n;
|
||||
}
|
||||
| FUNCTION Iconst func_name func_args
|
||||
{
|
||||
CreateOpClassItem *n = makeNode(CreateOpClassItem);
|
||||
n->itemtype = OPCLASS_ITEM_FUNCTION;
|
||||
n->name = $3;
|
||||
n->args = $4;
|
||||
n->number = $2;
|
||||
$$ = (Node *) n;
|
||||
}
|
||||
| STORAGE Typename
|
||||
{
|
||||
CreateOpClassItem *n = makeNode(CreateOpClassItem);
|
||||
n->itemtype = OPCLASS_ITEM_STORAGETYPE;
|
||||
n->storedtype = $2;
|
||||
$$ = (Node *) n;
|
||||
}
|
||||
;
|
||||
|
||||
opt_default: DEFAULT { $$ = TRUE; }
|
||||
| /*EMPTY*/ { $$ = FALSE; }
|
||||
;
|
||||
|
||||
opt_recheck: RECHECK { $$ = TRUE; }
|
||||
| /*EMPTY*/ { $$ = FALSE; }
|
||||
;
|
||||
|
||||
|
||||
DropOpClassStmt:
|
||||
DROP OPERATOR CLASS any_name USING access_method opt_drop_behavior
|
||||
{
|
||||
RemoveOpClassStmt *n = makeNode(RemoveOpClassStmt);
|
||||
n->opclassname = $4;
|
||||
n->amname = $6;
|
||||
n->behavior = $7;
|
||||
$$ = (Node *) n;
|
||||
}
|
||||
;
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* QUERY:
|
||||
@ -3655,10 +3744,6 @@ CreateConversionStmt:
|
||||
}
|
||||
;
|
||||
|
||||
opt_default: DEFAULT { $$ = TRUE; }
|
||||
| /*EMPTY*/ { $$ = FALSE; }
|
||||
;
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* QUERY:
|
||||
@ -6624,6 +6709,7 @@ unreserved_keyword:
|
||||
| CHAIN
|
||||
| CHARACTERISTICS
|
||||
| CHECKPOINT
|
||||
| CLASS
|
||||
| CLOSE
|
||||
| CLUSTER
|
||||
| COMMENT
|
||||
@ -6715,6 +6801,7 @@ unreserved_keyword:
|
||||
| PROCEDURAL
|
||||
| PROCEDURE
|
||||
| READ
|
||||
| RECHECK
|
||||
| REINDEX
|
||||
| RELATIVE
|
||||
| RENAME
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/keywords.c,v 1.122 2002/07/18 23:11:28 petere Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/keywords.c,v 1.123 2002/07/29 22:14:11 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -68,6 +68,7 @@ static const ScanKeyword ScanKeywords[] = {
|
||||
{"characteristics", CHARACTERISTICS},
|
||||
{"check", CHECK},
|
||||
{"checkpoint", CHECKPOINT},
|
||||
{"class", CLASS},
|
||||
{"close", CLOSE},
|
||||
{"cluster", CLUSTER},
|
||||
{"coalesce", COALESCE},
|
||||
@ -232,6 +233,7 @@ static const ScanKeyword ScanKeywords[] = {
|
||||
{"procedure", PROCEDURE},
|
||||
{"read", READ},
|
||||
{"real", REAL},
|
||||
{"recheck", RECHECK},
|
||||
{"references", REFERENCES},
|
||||
{"reindex", REINDEX},
|
||||
{"relative", RELATIVE},
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.272 2002/07/18 23:11:28 petere Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.273 2002/07/29 22:14:11 tgl Exp $
|
||||
*
|
||||
* NOTES
|
||||
* this is the "main" module of the postgres backend and
|
||||
@ -1693,7 +1693,7 @@ PostgresMain(int argc, char *argv[], const char *username)
|
||||
if (!IsUnderPostmaster)
|
||||
{
|
||||
puts("\nPOSTGRES backend interactive interface ");
|
||||
puts("$Revision: 1.272 $ $Date: 2002/07/18 23:11:28 $\n");
|
||||
puts("$Revision: 1.273 $ $Date: 2002/07/29 22:14:11 $\n");
|
||||
}
|
||||
|
||||
/*
|
||||
@ -2452,6 +2452,14 @@ CreateCommandTag(Node *parsetree)
|
||||
tag = "DROP CAST";
|
||||
break;
|
||||
|
||||
case T_CreateOpClassStmt:
|
||||
tag = "CREATE OPERATOR CLASS";
|
||||
break;
|
||||
|
||||
case T_RemoveOpClassStmt:
|
||||
tag = "DROP OPERATOR CLASS";
|
||||
break;
|
||||
|
||||
default:
|
||||
elog(LOG, "CreateCommandTag: unknown parse node type %d",
|
||||
nodeTag(parsetree));
|
||||
|
@ -10,7 +10,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.165 2002/07/25 10:07:11 ishii Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.166 2002/07/29 22:14:11 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -836,6 +836,14 @@ ProcessUtility(Node *parsetree,
|
||||
DropCast((DropCastStmt *) parsetree);
|
||||
break;
|
||||
|
||||
case T_CreateOpClassStmt:
|
||||
DefineOpClass((CreateOpClassStmt *) parsetree);
|
||||
break;
|
||||
|
||||
case T_RemoveOpClassStmt:
|
||||
RemoveOpClass((RemoveOpClassStmt *) parsetree);
|
||||
break;
|
||||
|
||||
default:
|
||||
elog(ERROR, "ProcessUtility: command #%d unsupported",
|
||||
nodeTag(parsetree));
|
||||
|
@ -13,7 +13,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/utils/adt/regproc.c,v 1.71 2002/07/20 05:16:58 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/utils/adt/regproc.c,v 1.72 2002/07/29 22:14:11 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -280,23 +280,19 @@ regprocedurein(PG_FUNCTION_ARGS)
|
||||
}
|
||||
|
||||
/*
|
||||
* regprocedureout - converts proc OID to "pro_name(args)"
|
||||
* format_procedure - converts proc OID to "pro_name(args)"
|
||||
*
|
||||
* This exports the useful functionality of regprocedureout for use
|
||||
* in other backend modules. The result is a palloc'd string.
|
||||
*/
|
||||
Datum
|
||||
regprocedureout(PG_FUNCTION_ARGS)
|
||||
char *
|
||||
format_procedure(Oid procedure_oid)
|
||||
{
|
||||
RegProcedure proid = PG_GETARG_OID(0);
|
||||
char *result;
|
||||
HeapTuple proctup;
|
||||
|
||||
if (proid == InvalidOid)
|
||||
{
|
||||
result = pstrdup("-");
|
||||
PG_RETURN_CSTRING(result);
|
||||
}
|
||||
|
||||
proctup = SearchSysCache(PROCOID,
|
||||
ObjectIdGetDatum(proid),
|
||||
ObjectIdGetDatum(procedure_oid),
|
||||
0, 0, 0);
|
||||
|
||||
if (HeapTupleIsValid(proctup))
|
||||
@ -316,7 +312,7 @@ regprocedureout(PG_FUNCTION_ARGS)
|
||||
* Would this proc be found (given the right args) by regprocedurein?
|
||||
* If not, we need to qualify it.
|
||||
*/
|
||||
if (FunctionIsVisible(proid))
|
||||
if (FunctionIsVisible(procedure_oid))
|
||||
nspname = NULL;
|
||||
else
|
||||
nspname = get_namespace_name(procform->pronamespace);
|
||||
@ -344,9 +340,26 @@ regprocedureout(PG_FUNCTION_ARGS)
|
||||
{
|
||||
/* If OID doesn't match any pg_proc entry, return it numerically */
|
||||
result = (char *) palloc(NAMEDATALEN);
|
||||
snprintf(result, NAMEDATALEN, "%u", proid);
|
||||
snprintf(result, NAMEDATALEN, "%u", procedure_oid);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* regprocedureout - converts proc OID to "pro_name(args)"
|
||||
*/
|
||||
Datum
|
||||
regprocedureout(PG_FUNCTION_ARGS)
|
||||
{
|
||||
RegProcedure proid = PG_GETARG_OID(0);
|
||||
char *result;
|
||||
|
||||
if (proid == InvalidOid)
|
||||
result = pstrdup("-");
|
||||
else
|
||||
result = format_procedure(proid);
|
||||
|
||||
PG_RETURN_CSTRING(result);
|
||||
}
|
||||
|
||||
@ -602,23 +615,19 @@ regoperatorin(PG_FUNCTION_ARGS)
|
||||
}
|
||||
|
||||
/*
|
||||
* regoperatorout - converts operator OID to "opr_name(args)"
|
||||
* format_operator - converts operator OID to "opr_name(args)"
|
||||
*
|
||||
* This exports the useful functionality of regoperatorout for use
|
||||
* in other backend modules. The result is a palloc'd string.
|
||||
*/
|
||||
Datum
|
||||
regoperatorout(PG_FUNCTION_ARGS)
|
||||
char *
|
||||
format_operator(Oid operator_oid)
|
||||
{
|
||||
Oid oprid = PG_GETARG_OID(0);
|
||||
char *result;
|
||||
HeapTuple opertup;
|
||||
|
||||
if (oprid == InvalidOid)
|
||||
{
|
||||
result = pstrdup("0");
|
||||
PG_RETURN_CSTRING(result);
|
||||
}
|
||||
|
||||
opertup = SearchSysCache(OPEROID,
|
||||
ObjectIdGetDatum(oprid),
|
||||
ObjectIdGetDatum(operator_oid),
|
||||
0, 0, 0);
|
||||
|
||||
if (HeapTupleIsValid(opertup))
|
||||
@ -636,7 +645,7 @@ regoperatorout(PG_FUNCTION_ARGS)
|
||||
* Would this oper be found (given the right args) by regoperatorin?
|
||||
* If not, we need to qualify it.
|
||||
*/
|
||||
if (!OperatorIsVisible(oprid))
|
||||
if (!OperatorIsVisible(operator_oid))
|
||||
{
|
||||
nspname = get_namespace_name(operform->oprnamespace);
|
||||
appendStringInfo(&buf, "%s.",
|
||||
@ -665,9 +674,26 @@ regoperatorout(PG_FUNCTION_ARGS)
|
||||
{
|
||||
/* If OID doesn't match any pg_operator entry, return it numerically */
|
||||
result = (char *) palloc(NAMEDATALEN);
|
||||
snprintf(result, NAMEDATALEN, "%u", oprid);
|
||||
snprintf(result, NAMEDATALEN, "%u", operator_oid);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* regoperatorout - converts operator OID to "opr_name(args)"
|
||||
*/
|
||||
Datum
|
||||
regoperatorout(PG_FUNCTION_ARGS)
|
||||
{
|
||||
Oid oprid = PG_GETARG_OID(0);
|
||||
char *result;
|
||||
|
||||
if (oprid == InvalidOid)
|
||||
result = pstrdup("0");
|
||||
else
|
||||
result = format_operator(oprid);
|
||||
|
||||
PG_RETURN_CSTRING(result);
|
||||
}
|
||||
|
||||
|
@ -27,7 +27,7 @@
|
||||
# Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
|
||||
# Portions Copyright (c) 1994, Regents of the University of California
|
||||
#
|
||||
# $Header: /cvsroot/pgsql/src/bin/initdb/Attic/initdb.sh,v 1.162 2002/07/24 19:11:11 petere Exp $
|
||||
# $Header: /cvsroot/pgsql/src/bin/initdb/Attic/initdb.sh,v 1.163 2002/07/29 22:14:11 tgl Exp $
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
|
||||
@ -708,14 +708,15 @@ $ECHO_N "initializing pg_depend... "$ECHO_C
|
||||
-- First delete any already-made entries; PINs override all else, and must
|
||||
-- be the only entries for their objects.
|
||||
DELETE FROM pg_depend;
|
||||
INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' FROM pg_cast;
|
||||
INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' FROM pg_class;
|
||||
INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' FROM pg_proc;
|
||||
INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' FROM pg_type;
|
||||
INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' FROM pg_cast;
|
||||
INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' FROM pg_constraint;
|
||||
INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' FROM pg_attrdef;
|
||||
INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' FROM pg_language;
|
||||
INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' FROM pg_operator;
|
||||
INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' FROM pg_opclass;
|
||||
INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' FROM pg_rewrite;
|
||||
INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' FROM pg_trigger;
|
||||
-- restriction here to avoid pinning the public namespace
|
||||
|
@ -8,7 +8,7 @@
|
||||
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: pg_am.h,v 1.22 2002/06/20 20:29:43 momjian Exp $
|
||||
* $Id: pg_am.h,v 1.23 2002/07/29 22:14:11 tgl Exp $
|
||||
*
|
||||
* NOTES
|
||||
* the genbki.sh script reads this file and generates .bki
|
||||
@ -107,5 +107,6 @@ DATA(insert OID = 405 ( hash PGUID 1 1 0 f f f t hashgettuple hashinsert hashbe
|
||||
DESCR("hash index access method");
|
||||
DATA(insert OID = 783 ( gist PGUID 100 7 0 f t f f gistgettuple gistinsert gistbeginscan gistrescan gistendscan gistmarkpos gistrestrpos gistbuild gistbulkdelete gistcostestimate ));
|
||||
DESCR("GiST index access method");
|
||||
#define GIST_AM_OID 783
|
||||
|
||||
#endif /* PG_AM_H */
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: defrem.h,v 1.42 2002/07/18 23:11:32 petere Exp $
|
||||
* $Id: defrem.h,v 1.43 2002/07/29 22:14:11 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -59,6 +59,10 @@ extern void RemoveTypeById(Oid typeOid);
|
||||
extern void DefineDomain(CreateDomainStmt *stmt);
|
||||
extern void RemoveDomain(List *names, DropBehavior behavior);
|
||||
|
||||
extern void DefineOpClass(CreateOpClassStmt *stmt);
|
||||
extern void RemoveOpClass(RemoveOpClassStmt *stmt);
|
||||
extern void RemoveOpClassById(Oid opclassOid);
|
||||
|
||||
|
||||
/* support routines in commands/define.c */
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: nodes.h,v 1.113 2002/07/18 23:11:32 petere Exp $
|
||||
* $Id: nodes.h,v 1.114 2002/07/29 22:14:11 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -201,6 +201,8 @@ typedef enum NodeTag
|
||||
T_CreateConversionStmt,
|
||||
T_CreateCastStmt,
|
||||
T_DropCastStmt,
|
||||
T_CreateOpClassStmt,
|
||||
T_RemoveOpClassStmt,
|
||||
|
||||
T_A_Expr = 700,
|
||||
T_ColumnRef,
|
||||
@ -235,6 +237,7 @@ typedef enum NodeTag
|
||||
T_FuncWithArgs,
|
||||
T_PrivTarget,
|
||||
T_InsertDefault,
|
||||
T_CreateOpClassItem,
|
||||
|
||||
/*
|
||||
* TAGS FOR FUNCTION-CALL CONTEXT AND RESULTINFO NODES (see fmgr.h)
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: parsenodes.h,v 1.194 2002/07/24 19:11:14 petere Exp $
|
||||
* $Id: parsenodes.h,v 1.195 2002/07/29 22:14:11 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -1115,6 +1115,37 @@ typedef struct CreateDomainStmt
|
||||
List *constraints; /* constraints (list of Constraint nodes) */
|
||||
} CreateDomainStmt;
|
||||
|
||||
/* ----------------------
|
||||
* Create Operator Class Statement
|
||||
* ----------------------
|
||||
*/
|
||||
typedef struct CreateOpClassStmt
|
||||
{
|
||||
NodeTag type;
|
||||
List *opclassname; /* qualified name (list of Value strings) */
|
||||
char *amname; /* name of index AM opclass is for */
|
||||
TypeName *datatype; /* datatype of indexed column */
|
||||
List *items; /* List of CreateOpClassItem nodes */
|
||||
bool isDefault; /* Should be marked as default for type? */
|
||||
} CreateOpClassStmt;
|
||||
|
||||
#define OPCLASS_ITEM_OPERATOR 1
|
||||
#define OPCLASS_ITEM_FUNCTION 2
|
||||
#define OPCLASS_ITEM_STORAGETYPE 3
|
||||
|
||||
typedef struct CreateOpClassItem
|
||||
{
|
||||
NodeTag type;
|
||||
int itemtype; /* see codes above */
|
||||
/* fields used for an operator or function item: */
|
||||
List *name; /* operator or function name */
|
||||
List *args; /* argument types */
|
||||
int number; /* strategy num or support proc num */
|
||||
bool recheck; /* only used for operators */
|
||||
/* fields used for a storagetype item: */
|
||||
TypeName *storedtype; /* datatype stored in index */
|
||||
} CreateOpClassItem;
|
||||
|
||||
/* ----------------------
|
||||
* Drop Table|Sequence|View|Index|Type|Domain|Conversion|Schema Statement
|
||||
* ----------------------
|
||||
@ -1288,6 +1319,18 @@ typedef struct RemoveOperStmt
|
||||
DropBehavior behavior; /* RESTRICT or CASCADE behavior */
|
||||
} RemoveOperStmt;
|
||||
|
||||
/* ----------------------
|
||||
* Drop Operator Class Statement
|
||||
* ----------------------
|
||||
*/
|
||||
typedef struct RemoveOpClassStmt
|
||||
{
|
||||
NodeTag type;
|
||||
List *opclassname; /* qualified name (list of Value strings) */
|
||||
char *amname; /* name of index AM opclass is for */
|
||||
DropBehavior behavior; /* RESTRICT or CASCADE behavior */
|
||||
} RemoveOpClassStmt;
|
||||
|
||||
/* ----------------------
|
||||
* Alter Object Rename Statement
|
||||
* ----------------------
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: acl.h,v 1.45 2002/06/20 20:29:52 momjian Exp $
|
||||
* $Id: acl.h,v 1.46 2002/07/29 22:14:11 tgl Exp $
|
||||
*
|
||||
* NOTES
|
||||
* For backward-compatibility purposes we have to allow there
|
||||
@ -209,5 +209,6 @@ extern bool pg_type_ownercheck(Oid type_oid, Oid userid);
|
||||
extern bool pg_oper_ownercheck(Oid oper_oid, Oid userid);
|
||||
extern bool pg_proc_ownercheck(Oid proc_oid, Oid userid);
|
||||
extern bool pg_namespace_ownercheck(Oid nsp_oid, Oid userid);
|
||||
extern bool pg_opclass_ownercheck(Oid opc_oid, Oid userid);
|
||||
|
||||
#endif /* ACL_H */
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: builtins.h,v 1.187 2002/07/20 05:49:28 momjian Exp $
|
||||
* $Id: builtins.h,v 1.188 2002/07/29 22:14:11 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -343,6 +343,8 @@ extern Datum regclassout(PG_FUNCTION_ARGS);
|
||||
extern Datum regtypein(PG_FUNCTION_ARGS);
|
||||
extern Datum regtypeout(PG_FUNCTION_ARGS);
|
||||
extern List *stringToQualifiedNameList(const char *string, const char *caller);
|
||||
extern char *format_procedure(Oid procedure_oid);
|
||||
extern char *format_operator(Oid operator_oid);
|
||||
|
||||
/* ruleutils.c */
|
||||
extern Datum pg_get_ruledef(PG_FUNCTION_ARGS);
|
||||
|
Loading…
x
Reference in New Issue
Block a user