diff options
Diffstat (limited to 'src/backend/commands')
-rw-r--r-- | src/backend/commands/amcmds.c | 28 | ||||
-rw-r--r-- | src/backend/commands/cluster.c | 1 | ||||
-rw-r--r-- | src/backend/commands/createas.c | 1 | ||||
-rw-r--r-- | src/backend/commands/tablecmds.c | 40 |
4 files changed, 60 insertions, 10 deletions
diff --git a/src/backend/commands/amcmds.c b/src/backend/commands/amcmds.c index c84507b5d03..24ca18018e1 100644 --- a/src/backend/commands/amcmds.c +++ b/src/backend/commands/amcmds.c @@ -30,7 +30,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); @@ -74,7 +74,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. @@ -229,6 +229,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); @@ -243,10 +245,11 @@ 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}; + Oid funcargtypes[1] = {INTERNALOID}; + Oid expectedType = InvalidOid; if (handler_name == NIL) ereport(ERROR, @@ -260,16 +263,21 @@ lookup_index_am_handler_func(List *handler_name, char amtype) switch (amtype) { case AMTYPE_INDEX: - if (get_func_rettype(handlerOid) != INDEX_AM_HANDLEROID) - ereport(ERROR, - (errcode(ERRCODE_WRONG_OBJECT_TYPE), - errmsg("function %s must return type %s", - NameListToString(handler_name), - "index_am_handler"))); + expectedType = INDEX_AM_HANDLEROID; + break; + case AMTYPE_TABLE: + expectedType = TABLE_AM_HANDLEROID; break; default: elog(ERROR, "unrecognized access method type \"%c\"", amtype); } + if (get_func_rettype(handlerOid) != expectedType) + ereport(ERROR, + (errcode(ERRCODE_WRONG_OBJECT_TYPE), + errmsg("function %s must return type %s", + get_func_name(handlerOid), + format_type_extended(expectedType, -1, 0)))); + return handlerOid; } diff --git a/src/backend/commands/cluster.c b/src/backend/commands/cluster.c index a74af4c1716..4d6453d9241 100644 --- a/src/backend/commands/cluster.c +++ b/src/backend/commands/cluster.c @@ -682,6 +682,7 @@ make_new_heap(Oid OIDOldHeap, Oid NewTableSpace, char relpersistence, InvalidOid, InvalidOid, OldHeap->rd_rel->relowner, + OldHeap->rd_rel->relam, OldHeapDesc, NIL, RELKIND_RELATION, diff --git a/src/backend/commands/createas.c b/src/backend/commands/createas.c index 6517ecb738a..36e3d44aad6 100644 --- a/src/backend/commands/createas.c +++ b/src/backend/commands/createas.c @@ -108,6 +108,7 @@ create_ctas_internal(List *attrList, IntoClause *into) create->oncommit = into->onCommit; create->tablespacename = into->tableSpaceName; create->if_not_exists = false; + create->accessMethod = into->accessMethod; /* * Create the relation. (This will error out if there's an existing view, diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index a93b13c2fe4..788544ec928 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -21,6 +21,7 @@ #include "access/reloptions.h" #include "access/relscan.h" #include "access/sysattr.h" +#include "access/tableam.h" #include "access/tupconvert.h" #include "access/xact.h" #include "access/xlog.h" @@ -537,6 +538,8 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId, Oid ofTypeId; ObjectAddress address; LOCKMODE parentLockmode; + const char *accessMethod = NULL; + Oid accessMethodId = InvalidOid; /* * Truncate relname to appropriate length (probably a waste of time, as @@ -778,6 +781,42 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId, } /* + * If the statement hasn't specified an access method, but we're defining + * a type of relation that needs one, use the default. + */ + if (stmt->accessMethod != NULL) + { + accessMethod = stmt->accessMethod; + + if (relkind == RELKIND_PARTITIONED_TABLE) + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("specifying a table access method is not supported on a partitioned table"))); + + } + else if (relkind == RELKIND_RELATION || + relkind == RELKIND_TOASTVALUE || + relkind == RELKIND_MATVIEW) + accessMethod = default_table_access_method; + + /* + * look up the access method, verify it can handle the requested features + */ + if (accessMethod != NULL) + { + HeapTuple tuple; + + tuple = SearchSysCache1(AMNAME, PointerGetDatum(accessMethod)); + if (!HeapTupleIsValid(tuple)) + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("table access method \"%s\" does not exist", + accessMethod))); + accessMethodId = ((Form_pg_am) GETSTRUCT(tuple))->oid; + ReleaseSysCache(tuple); + } + + /* * Create the relation. Inherited defaults and constraints are passed in * for immediate handling --- since they don't need parsing, they can be * stored immediately. @@ -789,6 +828,7 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId, InvalidOid, ofTypeId, ownerId, + accessMethodId, descriptor, list_concat(cookedDefaults, old_constraints), |