From c590273fef87321b12ea56733d6bf49a66841431 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Mon, 19 Jun 2000 03:55:01 +0000 Subject: [PATCH] Clean up bogosities in pg_opclass, pg_amop, pg_amproc. There are amproc entries now for int8 and network hash indexes. int24_ops and int42_ops are gone. pg_opclass no longer contains multiple entries claiming to be the default opclass for the same datatype. opr_sanity regress test extended to catch errors like these in the future. --- doc/src/sgml/indices.sgml | 11 -- doc/src/sgml/ref/create_index.sgml | 13 +- src/backend/access/hash/hashfunc.c | 173 ++++++----------------- src/backend/access/nbtree/nbtcompare.c | 30 +--- src/backend/utils/adt/date.c | 30 +++- src/backend/utils/adt/timestamp.c | 19 ++- src/backend/utils/adt/varchar.c | 96 ++----------- src/backend/utils/cache/catcache.c | 4 +- src/include/access/hash.h | 9 +- src/include/catalog/catversion.h | 4 +- src/include/catalog/pg_amop.h | 52 +++---- src/include/catalog/pg_amproc.h | 26 ++-- src/include/catalog/pg_opclass.h | 12 +- src/include/catalog/pg_proc.h | 20 +-- src/include/utils/builtins.h | 9 +- src/include/utils/date.h | 3 +- src/include/utils/timestamp.h | 3 +- src/test/regress/expected/opr_sanity.out | 59 +++++++- src/test/regress/sql/opr_sanity.sql | 56 +++++++- 19 files changed, 272 insertions(+), 357 deletions(-) diff --git a/doc/src/sgml/indices.sgml b/doc/src/sgml/indices.sgml index 84cb5036d3..ab882c0a1b 100644 --- a/doc/src/sgml/indices.sgml +++ b/doc/src/sgml/indices.sgml @@ -130,17 +130,6 @@ bigbox_ops. - - - - The int24_ops - operator class is useful for constructing indices on int2 data, and - doing comparisons against int4 data in query qualifications. - Similarly, int42_ops - support indices on int4 data that is to be compared against int2 data - in queries. - - diff --git a/doc/src/sgml/ref/create_index.sgml b/doc/src/sgml/ref/create_index.sgml index 43d6ffe38c..1f63d4ce05 100644 --- a/doc/src/sgml/ref/create_index.sgml +++ b/doc/src/sgml/ref/create_index.sgml @@ -1,5 +1,5 @@ @@ -312,17 +312,6 @@ ERROR: Cannot create index: 'index_name' already exists. bigbox_ops. - - - - The int24_ops - operator class is useful for constructing indices on int2 data, and - doing comparisons against int4 data in query qualifications. - Similarly, int42_ops - support indices on int4 data that is to be compared against int2 data - in queries. - - diff --git a/src/backend/access/hash/hashfunc.c b/src/backend/access/hash/hashfunc.c index 9a6d36f205..362738e676 100644 --- a/src/backend/access/hash/hashfunc.c +++ b/src/backend/access/hash/hashfunc.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/hash/hashfunc.c,v 1.26 2000/06/05 07:28:35 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/hash/hashfunc.c,v 1.27 2000/06/19 03:54:17 tgl Exp $ * * NOTES * These functions are stored in pg_amproc. For each operator class @@ -21,10 +21,17 @@ #include "access/hash.h" + +Datum +hashchar(PG_FUNCTION_ARGS) +{ + PG_RETURN_UINT32(~ ((uint32) PG_GETARG_CHAR(0))); +} + Datum hashint2(PG_FUNCTION_ARGS) { - PG_RETURN_UINT32((uint32) ~ PG_GETARG_INT16(0)); + PG_RETURN_UINT32(~ ((uint32) PG_GETARG_INT16(0))); } Datum @@ -37,116 +44,37 @@ Datum hashint8(PG_FUNCTION_ARGS) { /* we just use the low 32 bits... */ - PG_RETURN_UINT32(~((uint32) PG_GETARG_INT64(0))); + PG_RETURN_UINT32(~ ((uint32) PG_GETARG_INT64(0))); +} + +Datum +hashoid(PG_FUNCTION_ARGS) +{ + PG_RETURN_UINT32(~ ((uint32) PG_GETARG_OID(0))); } -/* Hash function from Chris Torek. */ Datum hashfloat4(PG_FUNCTION_ARGS) { float4 key = PG_GETARG_FLOAT4(0); - char *kp = (char *) &key; - int len = sizeof(key); - int loop; - uint32 h; -#define HASH4a h = (h << 5) - h + *kp++; -#define HASH4b h = (h << 5) + h + *kp++; -#define HASH4 HASH4b - - h = 0; - /* - * This is a tad silly, given that we expect len = 4, but a smart - * compiler should be able to eliminate the redundant code... - */ - loop = (len + 8 - 1) >> 3; - - switch (len & (8 - 1)) - { - case 0: - do - { /* All fall throughs */ - HASH4; - case 7: - HASH4; - case 6: - HASH4; - case 5: - HASH4; - case 4: - HASH4; - case 3: - HASH4; - case 2: - HASH4; - case 1: - HASH4; - } while (--loop); - } - PG_RETURN_UINT32(h); + return hash_any((char *) &key, sizeof(key)); } Datum hashfloat8(PG_FUNCTION_ARGS) { float8 key = PG_GETARG_FLOAT8(0); - char *kp = (char *) &key; - int len = sizeof(key); - int loop; - uint32 h; -#define HASH4a h = (h << 5) - h + *kp++; -#define HASH4b h = (h << 5) + h + *kp++; -#define HASH4 HASH4b - - h = 0; - /* - * This is a tad silly, given that we expect len = 8, but a smart - * compiler should be able to eliminate the redundant code... - */ - loop = (len + 8 - 1) >> 3; - - switch (len & (8 - 1)) - { - case 0: - do - { /* All fall throughs */ - HASH4; - case 7: - HASH4; - case 6: - HASH4; - case 5: - HASH4; - case 4: - HASH4; - case 3: - HASH4; - case 2: - HASH4; - case 1: - HASH4; - } while (--loop); - } - PG_RETURN_UINT32(h); -} - -Datum -hashoid(PG_FUNCTION_ARGS) -{ - PG_RETURN_UINT32(~(uint32) PG_GETARG_OID(0)); + return hash_any((char *) &key, sizeof(key)); } Datum hashoidvector(PG_FUNCTION_ARGS) { Oid *key = (Oid *) PG_GETARG_POINTER(0); - int i; - uint32 result = 0; - for (i = INDEX_MAX_KEYS; --i >= 0;) - result = (result << 1) ^ (~(uint32) key[i]); - PG_RETURN_UINT32(result); + return hash_any((char *) key, INDEX_MAX_KEYS * sizeof(Oid)); } /* @@ -158,69 +86,53 @@ Datum hashint2vector(PG_FUNCTION_ARGS) { int16 *key = (int16 *) PG_GETARG_POINTER(0); - int i; - uint32 result = 0; - for (i = INDEX_MAX_KEYS; --i >= 0;) - result = (result << 1) ^ (~(uint32) key[i]); - PG_RETURN_UINT32(result); -} - - -#define PRIME1 37 -#define PRIME2 1048583 - -Datum -hashchar(PG_FUNCTION_ARGS) -{ - uint32 h; - - /* Convert char to integer */ - h = (PG_GETARG_CHAR(0) - ' '); - h %= PRIME2; - - PG_RETURN_UINT32(h); + return hash_any((char *) key, INDEX_MAX_KEYS * sizeof(int16)); } Datum hashname(PG_FUNCTION_ARGS) { char *key = NameStr(* PG_GETARG_NAME(0)); - int len = NAMEDATALEN; - uint32 h; - h = 0; - /* Convert string to integer */ - while (len--) - h = h * PRIME1 ^ (*key++ - ' '); - h %= PRIME2; - - PG_RETURN_UINT32(h); + return hash_any((char *) key, NAMEDATALEN); } /* + * hashvarlena() can be used for any varlena datatype in which there are + * no non-significant bits, ie, distinct bitpatterns never compare as equal. + */ +Datum +hashvarlena(PG_FUNCTION_ARGS) +{ + struct varlena *key = PG_GETARG_VARLENA_P(0); + + return hash_any(VARDATA(key), VARSIZE(key) - VARHDRSZ); +} + + +/* + * hash_any --- compute a hash function for any specified chunk of memory + * + * This can be used as the underlying hash function for any pass-by-reference + * data type in which there are no non-significant bits. + * * (Comment from the original db3 hashing code: ) * * "This is INCREDIBLY ugly, but fast. We break the string up into 8 byte * units. On the first time through the loop we get the 'leftover bytes' - * (strlen % 8). On every other iteration, we perform 8 HASHC's so we handle + * (strlen % 8). On every later iteration, we perform 8 HASHC's so we handle * all 8 bytes. Essentially, this saves us 7 cmp & branch instructions. If * this routine is heavily used enough, it's worth the ugly coding. * * "OZ's original sdbm hash" */ Datum -hashtext(PG_FUNCTION_ARGS) +hash_any(char *keydata, int keylen) { - text *key = PG_GETARG_TEXT_P(0); - int keylen; - char *keydata; uint32 n; int loop; - keydata = VARDATA(key); - keylen = VARSIZE(key) - VARHDRSZ; - #define HASHC n = *keydata++ + 65599 * n n = 0; @@ -251,5 +163,8 @@ hashtext(PG_FUNCTION_ARGS) } while (--loop); } } + +#undef HASHC + PG_RETURN_UINT32(n); } diff --git a/src/backend/access/nbtree/nbtcompare.c b/src/backend/access/nbtree/nbtcompare.c index 375fc127bb..73f52cb861 100644 --- a/src/backend/access/nbtree/nbtcompare.c +++ b/src/backend/access/nbtree/nbtcompare.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtcompare.c,v 1.37 2000/06/15 03:31:54 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtcompare.c,v 1.38 2000/06/19 03:54:22 tgl Exp $ * * NOTES * @@ -81,34 +81,6 @@ btint8cmp(PG_FUNCTION_ARGS) PG_RETURN_INT32(-1); } -Datum -btint24cmp(PG_FUNCTION_ARGS) -{ - int16 a = PG_GETARG_INT16(0); - int32 b = PG_GETARG_INT32(1); - - if (a > b) - PG_RETURN_INT32(1); - else if (a == b) - PG_RETURN_INT32(0); - else - PG_RETURN_INT32(-1); -} - -Datum -btint42cmp(PG_FUNCTION_ARGS) -{ - int32 a = PG_GETARG_INT32(0); - int16 b = PG_GETARG_INT16(1); - - if (a > b) - PG_RETURN_INT32(1); - else if (a == b) - PG_RETURN_INT32(0); - else - PG_RETURN_INT32(-1); -} - Datum btfloat4cmp(PG_FUNCTION_ARGS) { diff --git a/src/backend/utils/adt/date.c b/src/backend/utils/adt/date.c index 128216f2b8..952a8e6d4d 100644 --- a/src/backend/utils/adt/date.c +++ b/src/backend/utils/adt/date.c @@ -8,23 +8,27 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/date.c,v 1.47 2000/06/15 04:10:23 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/date.c,v 1.48 2000/06/19 03:54:27 tgl Exp $ * *------------------------------------------------------------------------- */ -#include -#include #include "postgres.h" + +#include +#include #ifdef HAVE_FLOAT_H #include #endif + +#include "access/hash.h" #include "miscadmin.h" #include "utils/date.h" #include "utils/nabstime.h" -static int - date2tm(DateADT dateVal, int *tzp, struct tm * tm, double *fsec, char **tzn); + +static int date2tm(DateADT dateVal, int *tzp, struct tm * tm, + double *fsec, char **tzn); /***************************************************************************** @@ -762,6 +766,22 @@ timetz_cmp(PG_FUNCTION_ARGS) PG_RETURN_INT32(0); } +/* + * timetz, being an unusual size, needs a specialized hash function. + */ +Datum +timetz_hash(PG_FUNCTION_ARGS) +{ + TimeTzADT *key = PG_GETARG_TIMETZADT_P(0); + + /* + * Specify hash length as sizeof(double) + sizeof(int4), not as + * sizeof(TimeTzADT), so that any garbage pad bytes in the structure + * won't be included in the hash! + */ + return hash_any((char *) key, sizeof(double) + sizeof(int4)); +} + Datum timetz_larger(PG_FUNCTION_ARGS) { diff --git a/src/backend/utils/adt/timestamp.c b/src/backend/utils/adt/timestamp.c index 7715942a28..71549bb925 100644 --- a/src/backend/utils/adt/timestamp.c +++ b/src/backend/utils/adt/timestamp.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/timestamp.c,v 1.29 2000/06/09 01:11:09 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/timestamp.c,v 1.30 2000/06/19 03:54:27 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -29,6 +29,7 @@ #include #endif +#include "access/hash.h" #include "access/xact.h" #include "miscadmin.h" #include "utils/builtins.h" @@ -816,6 +817,22 @@ interval_cmp(PG_FUNCTION_ARGS) PG_RETURN_INT32((span1 < span2) ? -1 : (span1 > span2) ? 1 : 0); } +/* + * interval, being an unusual size, needs a specialized hash function. + */ +Datum +interval_hash(PG_FUNCTION_ARGS) +{ + Interval *key = PG_GETARG_INTERVAL_P(0); + + /* + * Specify hash length as sizeof(double) + sizeof(int4), not as + * sizeof(Interval), so that any garbage pad bytes in the structure + * won't be included in the hash! + */ + return hash_any((char *) key, sizeof(double) + sizeof(int4)); +} + /* overlaps_timestamp() * Implements the SQL92 OVERLAPS operator. * Algorithm from Date and Darwen, 1997 diff --git a/src/backend/utils/adt/varchar.c b/src/backend/utils/adt/varchar.c index 00e4c8ef39..53c6ec4167 100644 --- a/src/backend/utils/adt/varchar.c +++ b/src/backend/utils/adt/varchar.c @@ -8,13 +8,14 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/varchar.c,v 1.65 2000/06/15 03:32:29 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/varchar.c,v 1.66 2000/06/19 03:54:28 tgl Exp $ * *------------------------------------------------------------------------- */ #include "postgres.h" +#include "access/hash.h" #include "catalog/pg_type.h" #include "utils/acl.h" #include "utils/builtins.h" @@ -797,94 +798,19 @@ varcharcmp(char *arg1, char *arg2) return (int32) (cmp); } -/***************************************************************************** - * Hash functions (modified from hashtext in access/hash/hashfunc.c) - *****************************************************************************/ - -uint32 -hashbpchar(struct varlena * key) +/* + * bpchar needs a specialized hash function because we want to ignore + * trailing blanks in comparisons. (varchar can use plain hashvarlena.) + */ +Datum +hashbpchar(PG_FUNCTION_ARGS) { - int keylen; + BpChar *key = PG_GETARG_BPCHAR_P(0); char *keydata; - uint32 n; - int loop; + int keylen; keydata = VARDATA(key); keylen = bcTruelen((char *) key); -#define HASHC n = *keydata++ + 65599 * n - - n = 0; - if (keylen > 0) - { - loop = (keylen + 8 - 1) >> 3; - - switch (keylen & (8 - 1)) - { - case 0: - do - { /* All fall throughs */ - HASHC; - case 7: - HASHC; - case 6: - HASHC; - case 5: - HASHC; - case 4: - HASHC; - case 3: - HASHC; - case 2: - HASHC; - case 1: - HASHC; - } while (--loop); - } - } - return n; -} - -uint32 -hashvarchar(struct varlena * key) -{ - int keylen; - char *keydata; - uint32 n; - int loop; - - keydata = VARDATA(key); - keylen = VARSIZE(key) - VARHDRSZ; - -#define HASHC n = *keydata++ + 65599 * n - - n = 0; - if (keylen > 0) - { - loop = (keylen + 8 - 1) >> 3; - - switch (keylen & (8 - 1)) - { - case 0: - do - { /* All fall throughs */ - HASHC; - case 7: - HASHC; - case 6: - HASHC; - case 5: - HASHC; - case 4: - HASHC; - case 3: - HASHC; - case 2: - HASHC; - case 1: - HASHC; - } while (--loop); - } - } - return n; + return hash_any(keydata, keylen); } diff --git a/src/backend/utils/cache/catcache.c b/src/backend/utils/cache/catcache.c index 52a16e5292..a1c2d5b7bb 100644 --- a/src/backend/utils/cache/catcache.c +++ b/src/backend/utils/cache/catcache.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/cache/catcache.c,v 1.66 2000/06/17 04:56:32 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/cache/catcache.c,v 1.67 2000/06/19 03:54:31 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -104,7 +104,7 @@ GetCCHashFunc(Oid keytype) case INT4OID: return hashint4; case TEXTOID: - return hashtext; + return hashvarlena; case REGPROCOID: case OIDOID: return hashoid; diff --git a/src/include/access/hash.h b/src/include/access/hash.h index 294531fdb3..aa461a75e2 100644 --- a/src/include/access/hash.h +++ b/src/include/access/hash.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: hash.h,v 1.33 2000/06/13 07:35:17 tgl Exp $ + * $Id: hash.h,v 1.34 2000/06/19 03:54:35 tgl Exp $ * * NOTES * modeled after Margo Seltzer's hash implementation for unix. @@ -264,17 +264,18 @@ extern Datum hashdelete(PG_FUNCTION_ARGS); * NOTE: some of these are also used by catcache operations, without * any direct connection to hash indexes. */ +extern Datum hashchar(PG_FUNCTION_ARGS); extern Datum hashint2(PG_FUNCTION_ARGS); extern Datum hashint4(PG_FUNCTION_ARGS); extern Datum hashint8(PG_FUNCTION_ARGS); +extern Datum hashoid(PG_FUNCTION_ARGS); extern Datum hashfloat4(PG_FUNCTION_ARGS); extern Datum hashfloat8(PG_FUNCTION_ARGS); -extern Datum hashoid(PG_FUNCTION_ARGS); extern Datum hashoidvector(PG_FUNCTION_ARGS); extern Datum hashint2vector(PG_FUNCTION_ARGS); -extern Datum hashchar(PG_FUNCTION_ARGS); -extern Datum hashtext(PG_FUNCTION_ARGS); extern Datum hashname(PG_FUNCTION_ARGS); +extern Datum hashvarlena(PG_FUNCTION_ARGS); +extern Datum hash_any(char *keydata, int keylen); /* private routines */ diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h index b0e958d8cf..186674fffd 100644 --- a/src/include/catalog/catversion.h +++ b/src/include/catalog/catversion.h @@ -37,7 +37,7 @@ * Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: catversion.h,v 1.32 2000/06/16 05:27:01 tgl Exp $ + * $Id: catversion.h,v 1.33 2000/06/19 03:54:45 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -53,6 +53,6 @@ */ /* yyyymmddN */ -#define CATALOG_VERSION_NO 200006161 +#define CATALOG_VERSION_NO 200006181 #endif diff --git a/src/include/catalog/pg_amop.h b/src/include/catalog/pg_amop.h index 0014725229..ff79f1d533 100644 --- a/src/include/catalog/pg_amop.h +++ b/src/include/catalog/pg_amop.h @@ -8,7 +8,7 @@ * Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: pg_amop.h,v 1.33 2000/04/12 17:16:28 momjian Exp $ + * $Id: pg_amop.h,v 1.34 2000/06/19 03:54:45 tgl Exp $ * * NOTES * the genbki.sh script reads this file and generates .bki @@ -33,10 +33,11 @@ */ CATALOG(pg_amop) { - Oid amopid; - Oid amopclaid; - Oid amopopr; - int2 amopstrategy; + Oid amopid; /* an index access method */ + Oid amopclaid; /* an index opclass */ + Oid amopopr; /* the operator OID to use */ + int2 amopstrategy; /* one of the strategy numbers defined + * by the AM */ } FormData_pg_amop; /* ---------------- @@ -102,16 +103,21 @@ DATA(insert OID = 0 ( 402 434 489 8 )); /* * rtree circle_ops (supports circles) + * + * XXX Diked out 2000-06-18 by tgl. Since we have no rtree support functions + * (union, intersection, size) for circles, we can't actually build rtree + * indexes on circles. These can be put back in someday if anyone ever + * writes such functions. */ -DATA(insert OID = 0 ( 402 714 1506 1 )); -DATA(insert OID = 0 ( 402 714 1507 2 )); -DATA(insert OID = 0 ( 402 714 1513 3 )); -DATA(insert OID = 0 ( 402 714 1508 4 )); -DATA(insert OID = 0 ( 402 714 1509 5 )); -DATA(insert OID = 0 ( 402 714 1512 6 )); -DATA(insert OID = 0 ( 402 714 1511 7 )); -DATA(insert OID = 0 ( 402 714 1510 8 )); +/* DATA(insert OID = 0 ( 402 714 1506 1 )); */ +/* DATA(insert OID = 0 ( 402 714 1507 2 )); */ +/* DATA(insert OID = 0 ( 402 714 1513 3 )); */ +/* DATA(insert OID = 0 ( 402 714 1508 4 )); */ +/* DATA(insert OID = 0 ( 402 714 1509 5 )); */ +/* DATA(insert OID = 0 ( 402 714 1512 6 )); */ +/* DATA(insert OID = 0 ( 402 714 1511 7 )); */ +/* DATA(insert OID = 0 ( 402 714 1510 8 )); */ /* * nbtree int2_ops @@ -133,26 +139,6 @@ DATA(insert OID = 0 ( 403 423 670 3 )); DATA(insert OID = 0 ( 403 423 675 4 )); DATA(insert OID = 0 ( 403 423 674 5 )); -/* - * nbtree int24_ops - */ - -DATA(insert OID = 0 ( 403 424 534 1 )); -DATA(insert OID = 0 ( 403 424 540 2 )); -DATA(insert OID = 0 ( 403 424 532 3 )); -DATA(insert OID = 0 ( 403 424 542 4 )); -DATA(insert OID = 0 ( 403 424 536 5 )); - -/* - * nbtree int42_ops - */ - -DATA(insert OID = 0 ( 403 425 535 1 )); -DATA(insert OID = 0 ( 403 425 541 2 )); -DATA(insert OID = 0 ( 403 425 533 3 )); -DATA(insert OID = 0 ( 403 425 543 4 )); -DATA(insert OID = 0 ( 403 425 537 5 )); - /* * nbtree int4_ops */ diff --git a/src/include/catalog/pg_amproc.h b/src/include/catalog/pg_amproc.h index a8cdb38d14..fda508e602 100644 --- a/src/include/catalog/pg_amproc.h +++ b/src/include/catalog/pg_amproc.h @@ -1,16 +1,16 @@ /*------------------------------------------------------------------------- * * pg_amproc.h - * definition of the system "amproc" relation (pg_amproce) + * definition of the system "amproc" relation (pg_amproc) * along with the relation's initial contents. The amproc - * catalog is used to store procedures used by indexed access + * catalog is used to store procedures used by index access * methods that aren't associated with operators. * * * Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: pg_amproc.h,v 1.22 2000/03/14 23:06:43 thomas Exp $ + * $Id: pg_amproc.h,v 1.23 2000/06/19 03:54:45 tgl Exp $ * * NOTES * the genbki.sh script reads this file and generates .bki @@ -35,10 +35,10 @@ */ CATALOG(pg_amproc) { - Oid amid; - Oid amopclaid; - Oid amproc; - int2 amprocnum; + Oid amid; /* the access method this proc is for */ + Oid amopclaid; /* the opclass this proc is for */ + Oid amproc; /* OID of the proc */ + int2 amprocnum; /* support procedure index */ } FormData_pg_amproc; /* ---------------- @@ -78,8 +78,6 @@ DATA(insert OID = 0 (402 434 199 3)); /* btree */ DATA(insert OID = 0 (403 421 350 1)); DATA(insert OID = 0 (403 423 355 1)); -DATA(insert OID = 0 (403 424 353 1)); -DATA(insert OID = 0 (403 425 352 1)); DATA(insert OID = 0 (403 426 351 1)); DATA(insert OID = 0 (403 427 356 1)); DATA(insert OID = 0 (403 428 354 1)); @@ -114,13 +112,17 @@ DATA(insert OID = 0 (405 428 451 1)); DATA(insert OID = 0 (405 429 454 1)); DATA(insert OID = 0 (405 431 456 1)); DATA(insert OID = 0 (405 435 457 1)); +DATA(insert OID = 0 (405 652 456 1)); +DATA(insert OID = 0 (405 754 949 1)); +DATA(insert OID = 0 (405 810 456 1)); +DATA(insert OID = 0 (405 935 456 1)); DATA(insert OID = 0 (405 1076 1080 1)); -DATA(insert OID = 0 (405 1077 1081 1)); +DATA(insert OID = 0 (405 1077 456 1)); DATA(insert OID = 0 (405 1114 450 1)); DATA(insert OID = 0 (405 1115 452 1)); DATA(insert OID = 0 (405 1181 455 1)); DATA(insert OID = 0 (405 1312 452 1)); -DATA(insert OID = 0 (405 1313 452 1)); -DATA(insert OID = 0 (405 1399 452 1)); +DATA(insert OID = 0 (405 1313 1697 1)); +DATA(insert OID = 0 (405 1399 1696 1)); #endif /* PG_AMPROC_H */ diff --git a/src/include/catalog/pg_opclass.h b/src/include/catalog/pg_opclass.h index 1ff443a53f..b6a8da30cd 100644 --- a/src/include/catalog/pg_opclass.h +++ b/src/include/catalog/pg_opclass.h @@ -8,7 +8,7 @@ * Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: pg_opclass.h,v 1.32 2000/04/12 17:16:28 momjian Exp $ + * $Id: pg_opclass.h,v 1.33 2000/06/19 03:54:45 tgl Exp $ * * NOTES * the genbki.sh script reads this file and generates .bki @@ -34,8 +34,8 @@ CATALOG(pg_opclass) { - NameData opcname; - Oid opcdeftype; + NameData opcname; /* name of opclass defined by this row */ + Oid opcdeftype; /* type that opclass is default for, or 0 */ } FormData_pg_opclass; /* ---------------- @@ -69,10 +69,6 @@ DATA(insert OID = 422 ( box_ops 603 )); DESCR(""); DATA(insert OID = 423 ( float8_ops 701 )); DESCR(""); -DATA(insert OID = 424 ( int24_ops 0 )); -DESCR(""); -DATA(insert OID = 425 ( int42_ops 0 )); -DESCR(""); DATA(insert OID = 426 ( int4_ops 23 )); DESCR(""); #define INT4_OPS_OID 426 @@ -86,7 +82,7 @@ DATA(insert OID = 431 ( text_ops 25 )); DESCR(""); DATA(insert OID = 432 ( abstime_ops 702 )); DESCR(""); -DATA(insert OID = 433 ( bigbox_ops 603 )); +DATA(insert OID = 433 ( bigbox_ops 0 )); DESCR(""); DATA(insert OID = 434 ( poly_ops 604 )); DESCR(""); diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h index d32a299799..3d700dcf2b 100644 --- a/src/include/catalog/pg_proc.h +++ b/src/include/catalog/pg_proc.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: pg_proc.h,v 1.140 2000/06/17 23:41:51 tgl Exp $ + * $Id: pg_proc.h,v 1.141 2000/06/19 03:54:45 tgl Exp $ * * NOTES * The script catalog/genbki.sh reads this file and generates .bki @@ -736,10 +736,6 @@ DATA(insert OID = 351 ( btint4cmp PGUID 12 f t t t 2 f 23 "23 23" 100 0 0 1 DESCR("btree less-equal-greater"); DATA(insert OID = 842 ( btint8cmp PGUID 12 f t t t 2 f 23 "20 20" 100 0 0 100 btint8cmp - )); DESCR("btree less-equal-greater"); -DATA(insert OID = 352 ( btint42cmp PGUID 12 f t t t 2 f 23 "23 21" 100 0 0 100 btint42cmp - )); -DESCR("btree less-equal-greater"); -DATA(insert OID = 353 ( btint24cmp PGUID 12 f t t t 2 f 23 "21 23" 100 0 0 100 btint24cmp - )); -DESCR("btree less-equal-greater"); DATA(insert OID = 354 ( btfloat4cmp PGUID 12 f t t t 2 f 23 "700 700" 100 0 0 100 btfloat4cmp - )); DESCR("btree less-equal-greater"); DATA(insert OID = 355 ( btfloat8cmp PGUID 12 f t t t 2 f 23 "701 701" 100 0 0 100 btfloat8cmp - )); @@ -832,8 +828,8 @@ DATA(insert OID = 454 ( hashchar PGUID 12 f t t t 1 f 23 "18" 100 0 0 100 DESCR("hash"); DATA(insert OID = 455 ( hashname PGUID 12 f t t t 1 f 23 "19" 100 0 0 100 hashname - )); DESCR("hash"); -DATA(insert OID = 456 ( hashtext PGUID 12 f t t t 1 f 23 "25" 100 0 0 100 hashtext - )); -DESCR("hash"); +DATA(insert OID = 456 ( hashvarlena PGUID 12 f t t t 1 f 23 "0" 100 0 0 100 hashvarlena - )); +DESCR("hash any varlena type"); DATA(insert OID = 457 ( hashoidvector PGUID 12 f t t t 1 f 23 "30" 100 0 0 100 hashoidvector - )); DESCR("hash"); DATA(insert OID = 458 ( text_larger PGUID 11 f t t t 2 f 25 "25 25" 100 0 0 100 text_larger - )); @@ -1332,9 +1328,7 @@ DATA(insert OID = 1078 ( bpcharcmp PGUID 11 f t t t 2 f 23 "1042 1042" 100 DESCR("less-equal-greater"); DATA(insert OID = 1079 ( varcharcmp PGUID 11 f t t t 2 f 23 "1043 1043" 100 0 0 100 varcharcmp - )); DESCR("less-equal-greater"); -DATA(insert OID = 1080 ( hashbpchar PGUID 11 f t t t 1 f 23 "1042" 100 0 0 100 hashbpchar - )); -DESCR("hash"); -DATA(insert OID = 1081 ( hashvarchar PGUID 11 f t t t 1 f 23 "1043" 100 0 0 100 hashvarchar - )); +DATA(insert OID = 1080 ( hashbpchar PGUID 12 f t t t 1 f 23 "1042" 100 0 0 100 hashbpchar - )); DESCR("hash"); DATA(insert OID = 1084 ( date_in PGUID 12 f t f t 1 f 1082 "0" 100 0 0 100 date_in - )); @@ -2312,6 +2306,12 @@ DESCR("greater-than-or-equal"); DATA(insert OID = 1693 ( btboolcmp PGUID 12 f t t t 2 f 23 "16 16" 100 0 0 100 btboolcmp - )); DESCR("btree less-equal-greater"); +DATA(insert OID = 1696 ( timetz_hash PGUID 12 f t t t 1 f 23 "1266" 100 0 0 100 timetz_hash - )); +DESCR("hash"); +DATA(insert OID = 1697 ( interval_hash PGUID 12 f t t t 1 f 23 "1186" 100 0 0 100 interval_hash - )); +DESCR("hash"); + + /* OID's 1700 - 1799 NUMERIC data type */ DATA(insert OID = 1701 ( numeric_in PGUID 12 f t t t 3 f 1700 "0 26 23" 100 0 0 100 numeric_in - )); DESCR("(internal)"); diff --git a/src/include/utils/builtins.h b/src/include/utils/builtins.h index 785c5a15bd..267d7c55d1 100644 --- a/src/include/utils/builtins.h +++ b/src/include/utils/builtins.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: builtins.h,v 1.117 2000/06/15 03:33:10 momjian Exp $ + * $Id: builtins.h,v 1.118 2000/06/19 03:54:48 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -160,14 +160,12 @@ extern void ltoa(int32 l, char *a); /* * Per-opclass comparison functions for new btrees. These are - * stored in pg_amproc and defined in nbtree/ + * stored in pg_amproc and defined in access/nbtree/nbtcompare.c */ extern Datum btboolcmp(PG_FUNCTION_ARGS); extern Datum btint2cmp(PG_FUNCTION_ARGS); extern Datum btint4cmp(PG_FUNCTION_ARGS); extern Datum btint8cmp(PG_FUNCTION_ARGS); -extern Datum btint24cmp(PG_FUNCTION_ARGS); -extern Datum btint42cmp(PG_FUNCTION_ARGS); extern Datum btfloat4cmp(PG_FUNCTION_ARGS); extern Datum btfloat8cmp(PG_FUNCTION_ARGS); extern Datum btoidcmp(PG_FUNCTION_ARGS); @@ -421,7 +419,7 @@ extern bool bpcharge(char *arg1, char *arg2); extern int32 bpcharcmp(char *arg1, char *arg2); extern int32 bpcharlen(char *arg); extern int32 bpcharoctetlen(char *arg); -extern uint32 hashbpchar(struct varlena * key); +extern Datum hashbpchar(PG_FUNCTION_ARGS); extern Datum varcharin(PG_FUNCTION_ARGS); extern Datum varcharout(PG_FUNCTION_ARGS); @@ -436,7 +434,6 @@ extern bool varcharge(char *arg1, char *arg2); extern int32 varcharcmp(char *arg1, char *arg2); extern int32 varcharlen(char *arg); extern int32 varcharoctetlen(char *arg); -extern uint32 hashvarchar(struct varlena * key); /* varlena.c */ extern text *textin(char *inputText); diff --git a/src/include/utils/date.h b/src/include/utils/date.h index e57fed3eeb..c33d27031c 100644 --- a/src/include/utils/date.h +++ b/src/include/utils/date.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: date.h,v 1.4 2000/06/09 01:11:15 tgl Exp $ + * $Id: date.h,v 1.5 2000/06/19 03:54:48 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -95,6 +95,7 @@ extern Datum timetz_le(PG_FUNCTION_ARGS); extern Datum timetz_gt(PG_FUNCTION_ARGS); extern Datum timetz_ge(PG_FUNCTION_ARGS); extern Datum timetz_cmp(PG_FUNCTION_ARGS); +extern Datum timetz_hash(PG_FUNCTION_ARGS); extern Datum overlaps_timetz(PG_FUNCTION_ARGS); extern Datum timetz_larger(PG_FUNCTION_ARGS); extern Datum timetz_smaller(PG_FUNCTION_ARGS); diff --git a/src/include/utils/timestamp.h b/src/include/utils/timestamp.h index 97f2612fc1..61db8e7d20 100644 --- a/src/include/utils/timestamp.h +++ b/src/include/utils/timestamp.h @@ -6,7 +6,7 @@ * Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: timestamp.h,v 1.7 2000/06/15 00:52:26 momjian Exp $ + * $Id: timestamp.h,v 1.8 2000/06/19 03:54:48 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -151,6 +151,7 @@ extern Datum interval_ge(PG_FUNCTION_ARGS); extern Datum interval_gt(PG_FUNCTION_ARGS); extern Datum interval_finite(PG_FUNCTION_ARGS); extern Datum interval_cmp(PG_FUNCTION_ARGS); +extern Datum interval_hash(PG_FUNCTION_ARGS); extern Datum interval_smaller(PG_FUNCTION_ARGS); extern Datum interval_larger(PG_FUNCTION_ARGS); diff --git a/src/test/regress/expected/opr_sanity.out b/src/test/regress/expected/opr_sanity.out index 974575e53b..893b4bca83 100644 --- a/src/test/regress/expected/opr_sanity.out +++ b/src/test/regress/expected/opr_sanity.out @@ -36,6 +36,8 @@ WHERE (p1.prolang = 0 OR p1.prorettype = 0 OR (0 rows) -- Look for conflicting proc definitions (same names and input datatypes). +-- (This test should be dead code now that we have the unique index +-- pg_proc_proname_narg_type_index, but I'll leave it in anyway.) SELECT p1.oid, p1.proname, p2.oid, p2.proname FROM pg_proc AS p1, pg_proc AS p2 WHERE p1.oid != p2.oid AND @@ -57,7 +59,8 @@ WHERE p1.oid != p2.oid AND p1.prosrc = p2.prosrc AND (p1.prolang = 11 OR p1.prolang = 12) AND (p2.prolang = 11 OR p2.prolang = 12) AND - (p1.proisinh != p2.proisinh OR + (p1.prolang != p2.prolang OR + p1.proisinh != p2.proisinh OR p1.proistrusted != p2.proistrusted OR p1.proiscachable != p2.proiscachable OR p1.pronargs != p2.pronargs OR @@ -522,6 +525,19 @@ WHERE p1.aggfinalfn = p2.oid AND -----+---------+-----+--------- (0 rows) +-- **************** pg_opclass **************** +-- There should not be multiple entries in pg_opclass with the same +-- nonzero opcdeftype value, because there can be only one default opclass +-- for a datatype. (But multiple entries with zero opcdeftype are OK.) +SELECT p1.oid, p2.oid +FROM pg_opclass AS p1, pg_opclass AS p2 +WHERE p1.oid != p2.oid AND + p1.opcdeftype = p2.opcdeftype AND + p1.opcdeftype != 0; + oid | oid +-----+----- +(0 rows) + -- **************** pg_amop **************** -- Look for illegal values in pg_amop fields SELECT p1.oid @@ -564,11 +580,14 @@ WHERE p1.amstrategies != (SELECT count(*) FROM pg_amop AS p3 -----+--------+-----+--------- (0 rows) --- Check that amopopr points at a reasonable-looking operator +-- Check that amopopr points at a reasonable-looking operator, ie a binary +-- operator yielding boolean. +-- NOTE: for 7.1, add restriction that operator inputs are of same type. +-- We used to have opclasses like "int24_ops" but these were broken. SELECT p1.oid, p2.oid, p2.oprname FROM pg_amop AS p1, pg_operator AS p2 WHERE p1.amopopr = p2.oid AND - (p2.oprkind != 'b' OR p2.oprresult != 16); + (p2.oprkind != 'b' OR p2.oprresult != 16 OR p2.oprleft != p2.oprright); oid | oid | oprname -----+-----+--------- (0 rows) @@ -640,3 +659,37 @@ WHERE p1.oid != p3.oid AND -----+-----+---------+-----+-----+--------- (0 rows) +-- Cross-check that each opclass that has any entries for a given AM +-- has all the entries that any other opclass does. This catches cases +-- where an opclass has pg_amop but not pg_amproc entries or vice versa. +-- (The above tests for missing pg_amop or pg_amproc entries are redundant +-- with this, but I'll leave them in place anyway.) +-- All the strategy index numbers used for each AM +CREATE TEMP TABLE amopstrategies AS + SELECT DISTINCT amopid, amopstrategy FROM pg_amop; +-- All the support proc numbers used for each AM +CREATE TEMP TABLE amprocnums AS + SELECT DISTINCT amid, amprocnum FROM pg_amproc; +-- All the opclasses that claim to have support for each AM in either table. +-- UNION implies DISTINCT, so we do not need DISTINCT in the sub-selects. +CREATE TEMP TABLE amopclassids AS + SELECT amid, amopclaid FROM pg_amproc UNION + SELECT amopid, amopclaid FROM pg_amop; +-- Look for AMs that are missing one or more strategy operators +SELECT * FROM amopclassids c, amopstrategies s +WHERE c.amid = s.amopid AND NOT EXISTS + (SELECT 1 FROM pg_amop a WHERE a.amopid = c.amid AND + a.amopclaid = c.amopclaid AND a.amopstrategy = s.amopstrategy); + amid | amopclaid | amopid | amopstrategy +------+-----------+--------+-------------- +(0 rows) + +-- Look for AMs that are missing one or more support procs +SELECT * FROM amopclassids c, amprocnums p +WHERE c.amid = p.amid AND NOT EXISTS + (SELECT 1 FROM pg_amproc a WHERE a.amid = c.amid AND + a.amopclaid = c.amopclaid AND a.amprocnum = p.amprocnum); + amid | amopclaid | amid | amprocnum +------+-----------+------+----------- +(0 rows) + diff --git a/src/test/regress/sql/opr_sanity.sql b/src/test/regress/sql/opr_sanity.sql index d87702f0e3..40fa91bf46 100644 --- a/src/test/regress/sql/opr_sanity.sql +++ b/src/test/regress/sql/opr_sanity.sql @@ -36,6 +36,8 @@ WHERE (p1.prolang = 0 OR p1.prorettype = 0 OR AND p1.proname != 'update_pg_pwd'; -- Look for conflicting proc definitions (same names and input datatypes). +-- (This test should be dead code now that we have the unique index +-- pg_proc_proname_narg_type_index, but I'll leave it in anyway.) SELECT p1.oid, p1.proname, p2.oid, p2.proname FROM pg_proc AS p1, pg_proc AS p2 @@ -56,7 +58,8 @@ WHERE p1.oid != p2.oid AND p1.prosrc = p2.prosrc AND (p1.prolang = 11 OR p1.prolang = 12) AND (p2.prolang = 11 OR p2.prolang = 12) AND - (p1.proisinh != p2.proisinh OR + (p1.prolang != p2.prolang OR + p1.proisinh != p2.proisinh OR p1.proistrusted != p2.proistrusted OR p1.proiscachable != p2.proiscachable OR p1.pronargs != p2.pronargs OR @@ -432,6 +435,18 @@ WHERE p1.aggfinalfn = p2.oid AND p1.aggtranstype1 != p2.proargtypes[0] OR p1.aggtranstype2 != p2.proargtypes[1]); +-- **************** pg_opclass **************** + +-- There should not be multiple entries in pg_opclass with the same +-- nonzero opcdeftype value, because there can be only one default opclass +-- for a datatype. (But multiple entries with zero opcdeftype are OK.) + +SELECT p1.oid, p2.oid +FROM pg_opclass AS p1, pg_opclass AS p2 +WHERE p1.oid != p2.oid AND + p1.opcdeftype = p2.opcdeftype AND + p1.opcdeftype != 0; + -- **************** pg_amop **************** -- Look for illegal values in pg_amop fields @@ -467,12 +482,15 @@ WHERE p1.amstrategies != (SELECT count(*) FROM pg_amop AS p3 AND EXISTS (SELECT * FROM pg_amop AS p3 WHERE p3.amopid = p1.oid AND p3.amopclaid = p2.oid); --- Check that amopopr points at a reasonable-looking operator +-- Check that amopopr points at a reasonable-looking operator, ie a binary +-- operator yielding boolean. +-- NOTE: for 7.1, add restriction that operator inputs are of same type. +-- We used to have opclasses like "int24_ops" but these were broken. SELECT p1.oid, p2.oid, p2.oprname FROM pg_amop AS p1, pg_operator AS p2 WHERE p1.amopopr = p2.oid AND - (p2.oprkind != 'b' OR p2.oprresult != 16); + (p2.oprkind != 'b' OR p2.oprresult != 16 OR p2.oprleft != p2.oprright); -- If opclass is for a specific type, operator inputs should be of that type @@ -529,3 +547,35 @@ WHERE p1.oid != p3.oid AND p1.amid = p3.amid AND p1.amprocnum = p3.amprocnum AND p1.amproc = p2.oid AND p3.amproc = p4.oid AND (p2.proretset OR p4.proretset OR p2.pronargs != p4.pronargs); + +-- Cross-check that each opclass that has any entries for a given AM +-- has all the entries that any other opclass does. This catches cases +-- where an opclass has pg_amop but not pg_amproc entries or vice versa. +-- (The above tests for missing pg_amop or pg_amproc entries are redundant +-- with this, but I'll leave them in place anyway.) + +-- All the strategy index numbers used for each AM +CREATE TEMP TABLE amopstrategies AS + SELECT DISTINCT amopid, amopstrategy FROM pg_amop; + +-- All the support proc numbers used for each AM +CREATE TEMP TABLE amprocnums AS + SELECT DISTINCT amid, amprocnum FROM pg_amproc; + +-- All the opclasses that claim to have support for each AM in either table. +-- UNION implies DISTINCT, so we do not need DISTINCT in the sub-selects. +CREATE TEMP TABLE amopclassids AS + SELECT amid, amopclaid FROM pg_amproc UNION + SELECT amopid, amopclaid FROM pg_amop; + +-- Look for AMs that are missing one or more strategy operators +SELECT * FROM amopclassids c, amopstrategies s +WHERE c.amid = s.amopid AND NOT EXISTS + (SELECT 1 FROM pg_amop a WHERE a.amopid = c.amid AND + a.amopclaid = c.amopclaid AND a.amopstrategy = s.amopstrategy); + +-- Look for AMs that are missing one or more support procs +SELECT * FROM amopclassids c, amprocnums p +WHERE c.amid = p.amid AND NOT EXISTS + (SELECT 1 FROM pg_amproc a WHERE a.amid = c.amid AND + a.amopclaid = c.amopclaid AND a.amprocnum = p.amprocnum);