From 5ac450114cd8398c5141e7e711db2694e37b6818 Mon Sep 17 00:00:00 2001 From: Hari Babu Date: Thu, 29 Mar 2018 16:17:54 +1100 Subject: [PATCH 01/16] Change Create Access method to include table handler Add the support of table access method. --- src/backend/commands/amcmds.c | 17 ++++++++++++++--- src/backend/parser/gram.y | 11 +++++++++-- src/backend/utils/adt/pseudotypes.c | 1 + src/include/catalog/pg_am.h | 1 + src/include/catalog/pg_proc.dat | 7 +++++++ src/include/catalog/pg_type.dat | 5 +++++ src/test/regress/expected/opr_sanity.out | 19 ++++++++++++++++--- src/test/regress/sql/opr_sanity.sql | 16 +++++++++++++--- 8 files changed, 66 insertions(+), 11 deletions(-) diff --git a/src/backend/commands/amcmds.c b/src/backend/commands/amcmds.c index f2173450ad..00563b9b73 100644 --- a/src/backend/commands/amcmds.c +++ b/src/backend/commands/amcmds.c @@ -29,7 +29,7 @@ #include "utils/syscache.h" -static Oid lookup_index_am_handler_func(List *handler_name, char amtype); +static Oid lookup_am_handler_func(List *handler_name, char amtype); static const char *get_am_type_string(char amtype); @@ -72,7 +72,7 @@ CreateAccessMethod(CreateAmStmt *stmt) /* * Get the handler function oid, verifying the AM type while at it. */ - amhandler = lookup_index_am_handler_func(stmt->handler_name, stmt->amtype); + amhandler = lookup_am_handler_func(stmt->handler_name, stmt->amtype); /* * Insert tuple into pg_am. @@ -225,6 +225,8 @@ get_am_type_string(char amtype) { case AMTYPE_INDEX: return "INDEX"; + case AMTYPE_TABLE: + return "TABLE"; default: /* shouldn't happen */ elog(ERROR, "invalid access method type '%c'", amtype); @@ -239,7 +241,7 @@ get_am_type_string(char amtype) * This function either return valid function Oid or throw an error. */ static Oid -lookup_index_am_handler_func(List *handler_name, char amtype) +lookup_am_handler_func(List *handler_name, char amtype) { Oid handlerOid; static const Oid funcargtypes[1] = {INTERNALOID}; @@ -263,6 +265,15 @@ lookup_index_am_handler_func(List *handler_name, char amtype) NameListToString(handler_name), "index_am_handler"))); break; + /* XXX refactor duplicate error */ + case AMTYPE_TABLE: + if (get_func_rettype(handlerOid) != TABLE_AM_HANDLEROID) + ereport(ERROR, + (errcode(ERRCODE_WRONG_OBJECT_TYPE), + errmsg("function %s must return type %s", + NameListToString(handler_name), + "storage_am_handler"))); + break; default: elog(ERROR, "unrecognized access method type \"%c\"", amtype); } diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index 90dfac2cb1..c29a50194d 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -322,6 +322,8 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query); %type OptSchemaName %type OptSchemaEltList +%type am_type + %type TriggerForSpec TriggerForType %type TriggerActionTime %type TriggerEvents TriggerOneEvent @@ -5324,16 +5326,21 @@ row_security_cmd: * *****************************************************************************/ -CreateAmStmt: CREATE ACCESS METHOD name TYPE_P INDEX HANDLER handler_name +CreateAmStmt: CREATE ACCESS METHOD name TYPE_P am_type HANDLER handler_name { CreateAmStmt *n = makeNode(CreateAmStmt); n->amname = $4; n->handler_name = $8; - n->amtype = AMTYPE_INDEX; + n->amtype = $6; $$ = (Node *) n; } ; +am_type: + INDEX { $$ = AMTYPE_INDEX; } + | TABLE { $$ = AMTYPE_TABLE; } + ; + /***************************************************************************** * * QUERIES : diff --git a/src/backend/utils/adt/pseudotypes.c b/src/backend/utils/adt/pseudotypes.c index dbe67cdb4c..89aac13c80 100644 --- a/src/backend/utils/adt/pseudotypes.c +++ b/src/backend/utils/adt/pseudotypes.c @@ -418,3 +418,4 @@ PSEUDOTYPE_DUMMY_IO_FUNCS(internal); PSEUDOTYPE_DUMMY_IO_FUNCS(opaque); PSEUDOTYPE_DUMMY_IO_FUNCS(anyelement); PSEUDOTYPE_DUMMY_IO_FUNCS(anynonarray); +PSEUDOTYPE_DUMMY_IO_FUNCS(table_am_handler); diff --git a/src/include/catalog/pg_am.h b/src/include/catalog/pg_am.h index 26cb234987..2bdbe2fe35 100644 --- a/src/include/catalog/pg_am.h +++ b/src/include/catalog/pg_am.h @@ -51,6 +51,7 @@ typedef FormData_pg_am *Form_pg_am; * Allowed values for amtype */ #define AMTYPE_INDEX 'i' /* index access method */ +#define AMTYPE_TABLE 't' /* table access method */ #endif /* EXPOSE_TO_CLIENT_CODE */ diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat index 66c6c224a8..1dbc1ddcc8 100644 --- a/src/include/catalog/pg_proc.dat +++ b/src/include/catalog/pg_proc.dat @@ -7084,6 +7084,13 @@ { oid => '3312', descr => 'I/O', proname => 'tsm_handler_out', prorettype => 'cstring', proargtypes => 'tsm_handler', prosrc => 'tsm_handler_out' }, +{ oid => '3425', descr => 'I/O', + proname => 'table_am_handler_in', proisstrict => 'f', + prorettype => 'table_am_handler', proargtypes => 'cstring', + prosrc => 'table_am_handler_in' }, +{ oid => '3426', descr => 'I/O', + proname => 'table_am_handler_out', prorettype => 'cstring', + proargtypes => 'table_am_handler', prosrc => 'table_am_handler_out' }, # tablesample method handlers { oid => '3313', descr => 'BERNOULLI tablesample method handler', diff --git a/src/include/catalog/pg_type.dat b/src/include/catalog/pg_type.dat index 48e01cd694..152b4b680d 100644 --- a/src/include/catalog/pg_type.dat +++ b/src/include/catalog/pg_type.dat @@ -934,6 +934,11 @@ typcategory => 'P', typinput => 'tsm_handler_in', typoutput => 'tsm_handler_out', typreceive => '-', typsend => '-', typalign => 'i' }, +{ oid => '3998', + typname => 'table_am_handler', typlen => '4', typbyval => 't', typtype => 'p', + typcategory => 'P', typinput => 'table_am_handler_in', + typoutput => 'table_am_handler_out', typreceive => '-', typsend => '-', + typalign => 'i' }, { oid => '3831', typname => 'anyrange', typlen => '-1', typbyval => 'f', typtype => 'p', typcategory => 'P', typinput => 'anyrange_in', typoutput => 'anyrange_out', diff --git a/src/test/regress/expected/opr_sanity.out b/src/test/regress/expected/opr_sanity.out index a1e18a6ceb..78d8011469 100644 --- a/src/test/regress/expected/opr_sanity.out +++ b/src/test/regress/expected/opr_sanity.out @@ -1721,11 +1721,24 @@ WHERE p1.amhandler = 0; -----+-------- (0 rows) --- Check for amhandler functions with the wrong signature +-- Check for index amhandler functions with the wrong signature SELECT p1.oid, p1.amname, p2.oid, p2.proname FROM pg_am AS p1, pg_proc AS p2 -WHERE p2.oid = p1.amhandler AND - (p2.prorettype != 'index_am_handler'::regtype OR p2.proretset +WHERE p2.oid = p1.amhandler AND p1.amtype = 'i' AND + (p2.prorettype != 'index_am_handler'::regtype + OR p2.proretset + OR p2.pronargs != 1 + OR p2.proargtypes[0] != 'internal'::regtype); + oid | amname | oid | proname +-----+--------+-----+--------- +(0 rows) + +-- Check for table amhandler functions with the wrong signature +SELECT p1.oid, p1.amname, p2.oid, p2.proname +FROM pg_am AS p1, pg_proc AS p2 +WHERE p2.oid = p1.amhandler AND p1.amtype = 's' AND + (p2.prorettype != 'table_am_handler'::regtype + OR p2.proretset OR p2.pronargs != 1 OR p2.proargtypes[0] != 'internal'::regtype); oid | amname | oid | proname diff --git a/src/test/regress/sql/opr_sanity.sql b/src/test/regress/sql/opr_sanity.sql index a593d37643..20bba26052 100644 --- a/src/test/regress/sql/opr_sanity.sql +++ b/src/test/regress/sql/opr_sanity.sql @@ -1156,15 +1156,25 @@ SELECT p1.oid, p1.amname FROM pg_am AS p1 WHERE p1.amhandler = 0; --- Check for amhandler functions with the wrong signature +-- Check for index amhandler functions with the wrong signature SELECT p1.oid, p1.amname, p2.oid, p2.proname FROM pg_am AS p1, pg_proc AS p2 -WHERE p2.oid = p1.amhandler AND - (p2.prorettype != 'index_am_handler'::regtype OR p2.proretset +WHERE p2.oid = p1.amhandler AND p1.amtype = 'i' AND + (p2.prorettype != 'index_am_handler'::regtype + OR p2.proretset OR p2.pronargs != 1 OR p2.proargtypes[0] != 'internal'::regtype); +-- Check for table amhandler functions with the wrong signature + +SELECT p1.oid, p1.amname, p2.oid, p2.proname +FROM pg_am AS p1, pg_proc AS p2 +WHERE p2.oid = p1.amhandler AND p1.amtype = 's' AND + (p2.prorettype != 'table_am_handler'::regtype + OR p2.proretset + OR p2.pronargs != 1 + OR p2.proargtypes[0] != 'internal'::regtype); -- **************** pg_amop **************** -- 2.16.1.windows.4