mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-12-21 08:29:39 +08:00
f933766ba7
pgsql-hackers. pg_opclass now has a row for each opclass supported by each index AM, not a row for each opclass name. This allows pg_opclass to show directly whether an AM supports an opclass, and furthermore makes it possible to store additional information about an opclass that might be AM-dependent. pg_opclass and pg_amop now store "lossy" and "haskeytype" information that we previously expected the user to remember to provide in CREATE INDEX commands. Lossiness is no longer an index-level property, but is associated with the use of a particular operator in a particular index opclass. Along the way, IndexSupportInitialize now uses the syscaches to retrieve pg_amop and pg_amproc entries. I find this reduces backend launch time by about ten percent, at the cost of a couple more special cases in catcache.c's IndexScanOK. Initial work by Oleg Bartunov and Teodor Sigaev, further hacking by Tom Lane. initdb forced.
395 lines
11 KiB
MySQL
395 lines
11 KiB
MySQL
-- Create the user-defined type for 1-D floating point intervals (seg)
|
|
--
|
|
BEGIN TRANSACTION;
|
|
|
|
CREATE FUNCTION seg_in(opaque)
|
|
RETURNS opaque
|
|
AS 'MODULE_PATHNAME'
|
|
LANGUAGE 'c';
|
|
|
|
CREATE FUNCTION seg_out(opaque)
|
|
RETURNS opaque
|
|
AS 'MODULE_PATHNAME'
|
|
LANGUAGE 'c';
|
|
|
|
CREATE TYPE seg (
|
|
internallength = 12,
|
|
input = seg_in,
|
|
output = seg_out
|
|
);
|
|
|
|
COMMENT ON TYPE seg IS
|
|
'floating point interval ''FLOAT .. FLOAT'', ''.. FLOAT'', ''FLOAT ..'' or ''FLOAT''';
|
|
|
|
--
|
|
-- External C-functions for R-tree methods
|
|
--
|
|
|
|
-- Left/Right methods
|
|
|
|
CREATE FUNCTION seg_over_left(seg, seg) RETURNS bool
|
|
AS 'MODULE_PATHNAME' LANGUAGE 'c' with (isstrict);
|
|
|
|
COMMENT ON FUNCTION seg_over_left(seg, seg) IS
|
|
'is over and left of';
|
|
|
|
CREATE FUNCTION seg_over_right(seg, seg) RETURNS bool
|
|
AS 'MODULE_PATHNAME' LANGUAGE 'c' with (isstrict);
|
|
|
|
COMMENT ON FUNCTION seg_over_right(seg, seg) IS
|
|
'is over and right of';
|
|
|
|
CREATE FUNCTION seg_left(seg, seg) RETURNS bool
|
|
AS 'MODULE_PATHNAME' LANGUAGE 'c' with (isstrict);
|
|
|
|
COMMENT ON FUNCTION seg_left(seg, seg) IS
|
|
'is left of';
|
|
|
|
CREATE FUNCTION seg_right(seg, seg) RETURNS bool
|
|
AS 'MODULE_PATHNAME' LANGUAGE 'c' with (isstrict);
|
|
|
|
COMMENT ON FUNCTION seg_right(seg, seg) IS
|
|
'is right of';
|
|
|
|
|
|
-- Comparison methods
|
|
|
|
CREATE FUNCTION seg_lt(seg, seg) RETURNS bool
|
|
AS 'MODULE_PATHNAME' LANGUAGE 'c' with (isstrict);
|
|
|
|
COMMENT ON FUNCTION seg_lt(seg, seg) IS
|
|
'less than';
|
|
|
|
CREATE FUNCTION seg_le(seg, seg) RETURNS bool
|
|
AS 'MODULE_PATHNAME' LANGUAGE 'c' with (isstrict);
|
|
|
|
COMMENT ON FUNCTION seg_le(seg, seg) IS
|
|
'less than or equal';
|
|
|
|
CREATE FUNCTION seg_gt(seg, seg) RETURNS bool
|
|
AS 'MODULE_PATHNAME' LANGUAGE 'c' with (isstrict);
|
|
|
|
COMMENT ON FUNCTION seg_gt(seg, seg) IS
|
|
'greater than';
|
|
|
|
CREATE FUNCTION seg_ge(seg, seg) RETURNS bool
|
|
AS 'MODULE_PATHNAME' LANGUAGE 'c' with (isstrict);
|
|
|
|
COMMENT ON FUNCTION seg_ge(seg, seg) IS
|
|
'greater than or equal';
|
|
|
|
CREATE FUNCTION seg_contains(seg, seg) RETURNS bool
|
|
AS 'MODULE_PATHNAME' LANGUAGE 'c' with (isstrict);
|
|
|
|
COMMENT ON FUNCTION seg_contains(seg, seg) IS
|
|
'contains';
|
|
|
|
CREATE FUNCTION seg_contained(seg, seg) RETURNS bool
|
|
AS 'MODULE_PATHNAME' LANGUAGE 'c' with (isstrict);
|
|
|
|
COMMENT ON FUNCTION seg_contained(seg, seg) IS
|
|
'contained in';
|
|
|
|
CREATE FUNCTION seg_overlap(seg, seg) RETURNS bool
|
|
AS 'MODULE_PATHNAME' LANGUAGE 'c' with (isstrict);
|
|
|
|
COMMENT ON FUNCTION seg_overlap(seg, seg) IS
|
|
'overlaps';
|
|
|
|
CREATE FUNCTION seg_same(seg, seg) RETURNS bool
|
|
AS 'MODULE_PATHNAME' LANGUAGE 'c' with (isstrict);
|
|
|
|
COMMENT ON FUNCTION seg_same(seg, seg) IS
|
|
'same as';
|
|
|
|
CREATE FUNCTION seg_different(seg, seg) RETURNS bool
|
|
AS 'MODULE_PATHNAME' LANGUAGE 'c' with (isstrict);
|
|
|
|
COMMENT ON FUNCTION seg_different(seg, seg) IS
|
|
'different';
|
|
|
|
-- support routines for indexing
|
|
|
|
CREATE FUNCTION seg_union(seg, seg) RETURNS seg
|
|
AS 'MODULE_PATHNAME' LANGUAGE 'c' with (isstrict);
|
|
|
|
CREATE FUNCTION seg_inter(seg, seg) RETURNS seg
|
|
AS 'MODULE_PATHNAME' LANGUAGE 'c' with (isstrict);
|
|
|
|
CREATE FUNCTION seg_size(seg) RETURNS float4
|
|
AS 'MODULE_PATHNAME' LANGUAGE 'c' with (isstrict);
|
|
|
|
-- miscellaneous
|
|
|
|
CREATE FUNCTION seg_upper(seg) RETURNS float4
|
|
AS 'MODULE_PATHNAME' LANGUAGE 'c' with (isstrict);
|
|
|
|
CREATE FUNCTION seg_lower(seg) RETURNS float4
|
|
AS 'MODULE_PATHNAME' LANGUAGE 'c' with (isstrict);
|
|
|
|
|
|
--
|
|
-- OPERATORS
|
|
--
|
|
|
|
CREATE OPERATOR < (
|
|
LEFTARG = seg, RIGHTARG = seg, PROCEDURE = seg_lt,
|
|
COMMUTATOR = '>', NEGATOR = '>=',
|
|
RESTRICT = scalarltsel, JOIN = scalarltjoinsel
|
|
);
|
|
|
|
CREATE OPERATOR <= (
|
|
LEFTARG = seg, RIGHTARG = seg, PROCEDURE = seg_le,
|
|
COMMUTATOR = '>=', NEGATOR = '>',
|
|
RESTRICT = scalarltsel, JOIN = scalarltjoinsel
|
|
);
|
|
|
|
CREATE OPERATOR > (
|
|
LEFTARG = seg, RIGHTARG = seg, PROCEDURE = seg_gt,
|
|
COMMUTATOR = '<', NEGATOR = '<=',
|
|
RESTRICT = scalargtsel, JOIN = scalargtjoinsel
|
|
);
|
|
|
|
CREATE OPERATOR >= (
|
|
LEFTARG = seg, RIGHTARG = seg, PROCEDURE = seg_ge,
|
|
COMMUTATOR = '<=', NEGATOR = '<',
|
|
RESTRICT = scalargtsel, JOIN = scalargtjoinsel
|
|
);
|
|
|
|
CREATE OPERATOR << (
|
|
LEFTARG = seg, RIGHTARG = seg, PROCEDURE = seg_left,
|
|
COMMUTATOR = '>>',
|
|
RESTRICT = positionsel, JOIN = positionjoinsel
|
|
);
|
|
|
|
CREATE OPERATOR &< (
|
|
LEFTARG = seg, RIGHTARG = seg, PROCEDURE = seg_over_left,
|
|
COMMUTATOR = '&>',
|
|
RESTRICT = positionsel, JOIN = positionjoinsel
|
|
);
|
|
|
|
CREATE OPERATOR && (
|
|
LEFTARG = seg, RIGHTARG = seg, PROCEDURE = seg_overlap,
|
|
COMMUTATOR = '&&',
|
|
RESTRICT = positionsel, JOIN = positionjoinsel
|
|
);
|
|
|
|
CREATE OPERATOR &> (
|
|
LEFTARG = seg, RIGHTARG = seg, PROCEDURE = seg_over_right,
|
|
COMMUTATOR = '&<',
|
|
RESTRICT = positionsel, JOIN = positionjoinsel
|
|
);
|
|
|
|
CREATE OPERATOR >> (
|
|
LEFTARG = seg, RIGHTARG = seg, PROCEDURE = seg_right,
|
|
COMMUTATOR = '<<',
|
|
RESTRICT = positionsel, JOIN = positionjoinsel
|
|
);
|
|
|
|
CREATE OPERATOR = (
|
|
LEFTARG = seg, RIGHTARG = seg, PROCEDURE = seg_same,
|
|
COMMUTATOR = '=', NEGATOR = '<>',
|
|
RESTRICT = eqsel, JOIN = eqjoinsel,
|
|
SORT1 = '<', SORT2 = '<'
|
|
);
|
|
|
|
CREATE OPERATOR <> (
|
|
LEFTARG = seg, RIGHTARG = seg, PROCEDURE = seg_different,
|
|
COMMUTATOR = '<>', NEGATOR = '=',
|
|
RESTRICT = neqsel, JOIN = neqjoinsel
|
|
);
|
|
|
|
CREATE OPERATOR @ (
|
|
LEFTARG = seg, RIGHTARG = seg, PROCEDURE = seg_contains,
|
|
COMMUTATOR = '~',
|
|
RESTRICT = contsel, JOIN = contjoinsel
|
|
);
|
|
|
|
CREATE OPERATOR ~ (
|
|
LEFTARG = seg, RIGHTARG = seg, PROCEDURE = seg_contained,
|
|
COMMUTATOR = '@',
|
|
RESTRICT = contsel, JOIN = contjoinsel
|
|
);
|
|
|
|
|
|
-- define the GiST support methods
|
|
CREATE FUNCTION gseg_consistent(opaque,seg,int4) RETURNS bool
|
|
AS 'MODULE_PATHNAME' LANGUAGE 'c';
|
|
|
|
CREATE FUNCTION gseg_compress(opaque) RETURNS opaque
|
|
AS 'MODULE_PATHNAME' LANGUAGE 'c';
|
|
|
|
CREATE FUNCTION gseg_decompress(opaque) RETURNS opaque
|
|
AS 'MODULE_PATHNAME' LANGUAGE 'c';
|
|
|
|
CREATE FUNCTION gseg_penalty(opaque,opaque,opaque) RETURNS opaque
|
|
AS 'MODULE_PATHNAME' LANGUAGE 'c' with (isstrict);
|
|
|
|
CREATE FUNCTION gseg_picksplit(opaque, opaque) RETURNS opaque
|
|
AS 'MODULE_PATHNAME' LANGUAGE 'c';
|
|
|
|
CREATE FUNCTION gseg_union(bytea, opaque) RETURNS seg
|
|
AS 'MODULE_PATHNAME' LANGUAGE 'c';
|
|
|
|
CREATE FUNCTION gseg_same(seg, seg, opaque) RETURNS opaque
|
|
AS 'MODULE_PATHNAME' LANGUAGE 'c';
|
|
|
|
|
|
-- register the default opclass for indexing
|
|
INSERT INTO pg_opclass (opcamid, opcname, opcintype, opcdefault, opckeytype)
|
|
VALUES (
|
|
(SELECT oid FROM pg_am WHERE amname = 'gist'),
|
|
'gist_seg_ops',
|
|
(SELECT oid FROM pg_type WHERE typname = 'seg'),
|
|
true,
|
|
0);
|
|
|
|
|
|
-- get the comparators for segments and store them in a tmp table
|
|
SELECT o.oid AS opoid, o.oprname
|
|
INTO TEMP TABLE seg_ops_tmp
|
|
FROM pg_operator o, pg_type t
|
|
WHERE o.oprleft = t.oid and o.oprright = t.oid
|
|
and t.typname = 'seg';
|
|
|
|
-- make sure we have the right operators
|
|
-- SELECT * from seg_ops_tmp;
|
|
|
|
-- using the tmp table, generate the amop entries
|
|
|
|
-- seg_left
|
|
INSERT INTO pg_amop (amopclaid, amopstrategy, amopreqcheck, amopopr)
|
|
SELECT opcl.oid, 1, false, c.opoid
|
|
FROM pg_opclass opcl, seg_ops_tmp c
|
|
WHERE
|
|
opcamid = (SELECT oid FROM pg_am WHERE amname = 'gist')
|
|
and opcname = 'gist_seg_ops'
|
|
and c.oprname = '<<';
|
|
|
|
-- seg_overleft
|
|
INSERT INTO pg_amop (amopclaid, amopstrategy, amopreqcheck, amopopr)
|
|
SELECT opcl.oid, 2, false, c.opoid
|
|
FROM pg_opclass opcl, seg_ops_tmp c
|
|
WHERE
|
|
opcamid = (SELECT oid FROM pg_am WHERE amname = 'gist')
|
|
and opcname = 'gist_seg_ops'
|
|
and c.oprname = '&<';
|
|
|
|
-- seg_overlap
|
|
INSERT INTO pg_amop (amopclaid, amopstrategy, amopreqcheck, amopopr)
|
|
SELECT opcl.oid, 3, false, c.opoid
|
|
FROM pg_opclass opcl, seg_ops_tmp c
|
|
WHERE
|
|
opcamid = (SELECT oid FROM pg_am WHERE amname = 'gist')
|
|
and opcname = 'gist_seg_ops'
|
|
and c.oprname = '&&';
|
|
|
|
-- seg_overright
|
|
INSERT INTO pg_amop (amopclaid, amopstrategy, amopreqcheck, amopopr)
|
|
SELECT opcl.oid, 4, false, c.opoid
|
|
FROM pg_opclass opcl, seg_ops_tmp c
|
|
WHERE
|
|
opcamid = (SELECT oid FROM pg_am WHERE amname = 'gist')
|
|
and opcname = 'gist_seg_ops'
|
|
and c.oprname = '&>';
|
|
|
|
-- seg_right
|
|
INSERT INTO pg_amop (amopclaid, amopstrategy, amopreqcheck, amopopr)
|
|
SELECT opcl.oid, 5, false, c.opoid
|
|
FROM pg_opclass opcl, seg_ops_tmp c
|
|
WHERE
|
|
opcamid = (SELECT oid FROM pg_am WHERE amname = 'gist')
|
|
and opcname = 'gist_seg_ops'
|
|
and c.oprname = '>>';
|
|
|
|
-- seg_same
|
|
INSERT INTO pg_amop (amopclaid, amopstrategy, amopreqcheck, amopopr)
|
|
SELECT opcl.oid, 6, false, c.opoid
|
|
FROM pg_opclass opcl, seg_ops_tmp c
|
|
WHERE
|
|
opcamid = (SELECT oid FROM pg_am WHERE amname = 'gist')
|
|
and opcname = 'gist_seg_ops'
|
|
and c.oprname = '=';
|
|
|
|
-- seg_contains
|
|
INSERT INTO pg_amop (amopclaid, amopstrategy, amopreqcheck, amopopr)
|
|
SELECT opcl.oid, 7, false, c.opoid
|
|
FROM pg_opclass opcl, seg_ops_tmp c
|
|
WHERE
|
|
opcamid = (SELECT oid FROM pg_am WHERE amname = 'gist')
|
|
and opcname = 'gist_seg_ops'
|
|
and c.oprname = '@';
|
|
|
|
-- seg_contained
|
|
INSERT INTO pg_amop (amopclaid, amopstrategy, amopreqcheck, amopopr)
|
|
SELECT opcl.oid, 8, false, c.opoid
|
|
FROM pg_opclass opcl, seg_ops_tmp c
|
|
WHERE
|
|
opcamid = (SELECT oid FROM pg_am WHERE amname = 'gist')
|
|
and opcname = 'gist_seg_ops'
|
|
and c.oprname = '~';
|
|
|
|
DROP TABLE seg_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_seg_ops'
|
|
and proname = 'gseg_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_seg_ops'
|
|
and proname = 'gseg_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_seg_ops'
|
|
and proname = 'gseg_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_seg_ops'
|
|
and proname = 'gseg_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_seg_ops'
|
|
and proname = 'gseg_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_seg_ops'
|
|
and proname = 'gseg_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_seg_ops'
|
|
and proname = 'gseg_same';
|
|
|
|
END TRANSACTION;
|