commit 5916d188be1cfff798845720d6e955327aa8c693 Author: Anastasia Date: Mon Sep 30 19:31:40 2019 +0300 Opclass bitwise equality check diff --git a/doc/src/sgml/ref/create_opclass.sgml b/doc/src/sgml/ref/create_opclass.sgml index dd5252f..eb2e086 100644 --- a/doc/src/sgml/ref/create_opclass.sgml +++ b/doc/src/sgml/ref/create_opclass.sgml @@ -21,7 +21,7 @@ PostgreSQL documentation -CREATE OPERATOR CLASS name [ DEFAULT ] FOR TYPE data_type +CREATE OPERATOR CLASS name [ DEFAULT | NOT BITWISE ] FOR TYPE data_type USING index_method [ FAMILY family_name ] AS { OPERATOR strategy_number operator_name [ ( op_type, op_type ) ] [ FOR SEARCH | FOR ORDER BY sort_family_name ] | FUNCTION support_number [ ( op_type [ , op_type ] ) ] function_name ( argument_type [, ...] ) @@ -106,6 +106,18 @@ CREATE OPERATOR CLASS name [ DEFAUL + + NOT BITWISE + + + If present, the operator class equality is not the same as equivalence. + For example, two numerics can compare equal but have different scales. + Most opclasses implement bitwise equal comparison, alternative behaviour + must be set explicitly. + + + + data_type diff --git a/src/backend/commands/opclasscmds.c b/src/backend/commands/opclasscmds.c index 6a1ccde..bb6a0a7 100644 --- a/src/backend/commands/opclasscmds.c +++ b/src/backend/commands/opclasscmds.c @@ -654,6 +654,7 @@ DefineOpClass(CreateOpClassStmt *stmt) values[Anum_pg_opclass_opcintype - 1] = ObjectIdGetDatum(typeoid); values[Anum_pg_opclass_opcdefault - 1] = BoolGetDatum(stmt->isDefault); values[Anum_pg_opclass_opckeytype - 1] = ObjectIdGetDatum(storageoid); + values[Anum_pg_opclass_opcisbitwise - 1] = BoolGetDatum(!stmt->isNotBitwise); tup = heap_form_tuple(rel->rd_att, values, nulls); diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c index 3432bb9..c2cf06e 100644 --- a/src/backend/nodes/copyfuncs.c +++ b/src/backend/nodes/copyfuncs.c @@ -3785,6 +3785,7 @@ _copyCreateOpClassStmt(const CreateOpClassStmt *from) COPY_NODE_FIELD(datatype); COPY_NODE_FIELD(items); COPY_SCALAR_FIELD(isDefault); + COPY_SCALAR_FIELD(isNotBitwise); return newnode; } diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c index 18cb014..52e8f0b 100644 --- a/src/backend/nodes/equalfuncs.c +++ b/src/backend/nodes/equalfuncs.c @@ -1607,6 +1607,7 @@ _equalCreateOpClassStmt(const CreateOpClassStmt *a, const CreateOpClassStmt *b) COMPARE_NODE_FIELD(datatype); COMPARE_NODE_FIELD(items); COMPARE_SCALAR_FIELD(isDefault); + COMPARE_SCALAR_FIELD(isNotBitwise); return true; } diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index 3f67aaf..45a4f8a 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -590,6 +590,8 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query); %type hash_partbound %type hash_partbound_elem +%type opt_not_bitwise + /* * Non-keyword token types. These are hard-wired into the "flex" lexer. * They must be listed first so that their numeric codes do not depend on @@ -616,7 +618,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query); AGGREGATE ALL ALSO ALTER ALWAYS ANALYSE ANALYZE AND ANY ARRAY AS ASC ASSERTION ASSIGNMENT ASYMMETRIC AT ATTACH ATTRIBUTE AUTHORIZATION - BACKWARD BEFORE BEGIN_P BETWEEN BIGINT BINARY BIT + BACKWARD BEFORE BEGIN_P BETWEEN BIGINT BINARY BIT BITWISE BOOLEAN_P BOTH BY CACHE CALL CALLED CASCADE CASCADED CASE CAST CATALOG_P CHAIN CHAR_P @@ -5951,16 +5953,17 @@ opt_if_not_exists: IF_P NOT EXISTS { $$ = true; } *****************************************************************************/ CreateOpClassStmt: - CREATE OPERATOR CLASS any_name opt_default FOR TYPE_P Typename + CREATE OPERATOR CLASS any_name opt_default opt_not_bitwise FOR TYPE_P Typename USING access_method opt_opfamily AS opclass_item_list { CreateOpClassStmt *n = makeNode(CreateOpClassStmt); n->opclassname = $4; n->isDefault = $5; - n->datatype = $8; - n->amname = $10; - n->opfamilyname = $11; - n->items = $13; + n->isNotBitwise = $6; + n->datatype = $9; + n->amname = $11; + n->opfamilyname = $12; + n->items = $14; $$ = (Node *) n; } ; @@ -6023,6 +6026,10 @@ opt_default: DEFAULT { $$ = true; } | /*EMPTY*/ { $$ = false; } ; +opt_not_bitwise: NOT BITWISE { $$ = true; } + | /*EMPTY*/ { $$ = false; } + ; + opt_opfamily: FAMILY any_name { $$ = $2; } | /*EMPTY*/ { $$ = NIL; } ; diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h index c689b8f..84f867a 100644 --- a/src/include/catalog/catversion.h +++ b/src/include/catalog/catversion.h @@ -53,6 +53,6 @@ */ /* yyyymmddN */ -#define CATALOG_VERSION_NO 201909251 +#define CATALOG_VERSION_NO 201909301 #endif diff --git a/src/include/catalog/pg_opclass.dat b/src/include/catalog/pg_opclass.dat index 2d57510..51fccae 100644 --- a/src/include/catalog/pg_opclass.dat +++ b/src/include/catalog/pg_opclass.dat @@ -44,14 +44,14 @@ { opcmethod => 'hash', opcname => 'date_ops', opcfamily => 'hash/date_ops', opcintype => 'date' }, { opcmethod => 'btree', opcname => 'float4_ops', opcfamily => 'btree/float_ops', - opcintype => 'float4' }, + opcintype => 'float4', opcisbitwise => 'f' }, { opcmethod => 'hash', opcname => 'float4_ops', opcfamily => 'hash/float_ops', - opcintype => 'float4' }, + opcintype => 'float4', opcisbitwise => 'f' }, { oid => '3123', oid_symbol => 'FLOAT8_BTREE_OPS_OID', opcmethod => 'btree', opcname => 'float8_ops', opcfamily => 'btree/float_ops', - opcintype => 'float8' }, + opcintype => 'float8', opcisbitwise => 'f' }, { opcmethod => 'hash', opcname => 'float8_ops', opcfamily => 'hash/float_ops', - opcintype => 'float8' }, + opcintype => 'float8', opcisbitwise => 'f' }, { opcmethod => 'btree', opcname => 'inet_ops', opcfamily => 'btree/network_ops', opcintype => 'inet' }, { opcmethod => 'hash', opcname => 'inet_ops', opcfamily => 'hash/network_ops', @@ -100,9 +100,11 @@ opcintype => 'name' }, { oid => '3125', oid_symbol => 'NUMERIC_BTREE_OPS_OID', opcmethod => 'btree', opcname => 'numeric_ops', - opcfamily => 'btree/numeric_ops', opcintype => 'numeric' }, + opcfamily => 'btree/numeric_ops', opcintype => 'numeric', + opcisbitwise => 'f'}, { opcmethod => 'hash', opcname => 'numeric_ops', - opcfamily => 'hash/numeric_ops', opcintype => 'numeric' }, + opcfamily => 'hash/numeric_ops', opcintype => 'numeric', + opcisbitwise => 'f'}, { oid => '1981', oid_symbol => 'OID_BTREE_OPS_OID', opcmethod => 'btree', opcname => 'oid_ops', opcfamily => 'btree/oid_ops', opcintype => 'oid' }, diff --git a/src/include/catalog/pg_opclass.h b/src/include/catalog/pg_opclass.h index 84853c1..374ac4f 100644 --- a/src/include/catalog/pg_opclass.h +++ b/src/include/catalog/pg_opclass.h @@ -73,6 +73,9 @@ CATALOG(pg_opclass,2616,OperatorClassRelationId) /* type of data in index, or InvalidOid */ Oid opckeytype BKI_DEFAULT(0) BKI_LOOKUP(pg_type); + + /* T if opclass equality also means "bitwise equality" */ + bool opcisbitwise BKI_DEFAULT(t); } FormData_pg_opclass; /* ---------------- diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h index d93a79a..cd390a2 100644 --- a/src/include/nodes/parsenodes.h +++ b/src/include/nodes/parsenodes.h @@ -2577,6 +2577,7 @@ typedef struct CreateOpClassStmt TypeName *datatype; /* datatype of indexed column */ List *items; /* List of CreateOpClassItem nodes */ bool isDefault; /* Should be marked as default for type? */ + bool isNotBitwise; /* Is opclass equality bitwise? */ } CreateOpClassStmt; #define OPCLASS_ITEM_OPERATOR 1 diff --git a/src/include/parser/kwlist.h b/src/include/parser/kwlist.h index 00ace84..d6a8e8f 100644 --- a/src/include/parser/kwlist.h +++ b/src/include/parser/kwlist.h @@ -58,6 +58,7 @@ PG_KEYWORD("between", BETWEEN, COL_NAME_KEYWORD) PG_KEYWORD("bigint", BIGINT, COL_NAME_KEYWORD) PG_KEYWORD("binary", BINARY, TYPE_FUNC_NAME_KEYWORD) PG_KEYWORD("bit", BIT, COL_NAME_KEYWORD) +PG_KEYWORD("bitwise", BITWISE, UNRESERVED_KEYWORD) PG_KEYWORD("boolean", BOOLEAN_P, COL_NAME_KEYWORD) PG_KEYWORD("both", BOTH, RESERVED_KEYWORD) PG_KEYWORD("by", BY, UNRESERVED_KEYWORD)