modules_poc_3.patch
application/octet-stream
Filename: modules_poc_3.patch
Type: application/octet-stream
Part: 2
Message:
Support for CREATE MODULE?
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: unified
| File | + | − |
|---|---|---|
| src/backend/catalog/pg_operator.c | 2 | 1 |
| src/backend/commands/aggregatecmds.c | 1 | 1 |
| src/backend/commands/alter.c | 1 | 0 |
| src/backend/commands/collationcmds.c | 1 | 1 |
| src/backend/commands/conversioncmds.c | 1 | 1 |
| src/backend/commands/event_trigger.c | 5 | 0 |
| src/backend/commands/functioncmds.c | 2 | 2 |
| src/backend/commands/indexcmds.c | 2 | 2 |
| src/backend/commands/opclasscmds.c | 4 | 4 |
| src/backend/commands/operatorcmds.c | 1 | 1 |
| src/backend/commands/seclabel.c | 1 | 0 |
| src/backend/commands/statscmds.c | 2 | 2 |
| src/backend/commands/tsearchcmds.c | 4 | 4 |
| src/backend/commands/typecmds.c | 5 | 5 |
| src/backend/parser/gram.y | 116 | 4 |
| src/backend/parser/parse_func.c | 12 | 3 |
| src/backend/parser/parse_oper.c | 1 | 1 |
| src/backend/parser/parse_type.c | 1 | 1 |
| src/backend/parser/parse_utilcmd.c | 72 | 0 |
| src/backend/tcop/utility.c | 29 | 0 |
| src/include/nodes/nodes.h | 1 | 0 |
| src/include/nodes/parsenodes.h | 19 | 0 |
| src/include/parser/kwlist.h | 1 | 0 |
| src/include/parser/parse_utilcmd.h | 1 | 0 |
| src/include/tcop/cmdtaglist.h | 3 | 0 |
unchanged:
--- a/src/backend/catalog/pg_operator.c
+++ b/src/backend/catalog/pg_operator.c
@@ -604,7 +604,8 @@ get_other_operator(List *otherOp, Oid otherLeftTypeId, Oid otherRightTypeId,
}
otherNamespace = QualifiedNameGetCreationNamespace(otherOp,
- &otherName);
+ &otherName,
+ false);
if (strcmp(otherName, operatorName) == 0 &&
otherNamespace == operatorNamespace &&
unchanged:
--- a/src/backend/commands/aggregatecmds.c
+++ b/src/backend/commands/aggregatecmds.c
@@ -101,7 +101,7 @@ DefineAggregate(ParseState *pstate,
ListCell *pl;
/* Convert list of names to a name and namespace */
- aggNamespace = QualifiedNameGetCreationNamespace(name, &aggName);
+ aggNamespace = QualifiedNameGetCreationNamespace(name, &aggName, false);
/* Check we have creation rights in target namespace */
aclresult = pg_namespace_aclcheck(aggNamespace, GetUserId(), ACL_CREATE);
unchanged:
--- a/src/backend/commands/alter.c
+++ b/src/backend/commands/alter.c
@@ -384,6 +384,7 @@ ExecRenameStmt(RenameStmt *stmt)
case OBJECT_OPCLASS:
case OBJECT_OPFAMILY:
case OBJECT_LANGUAGE:
+ case OBJECT_MODULE:
case OBJECT_PROCEDURE:
case OBJECT_ROUTINE:
case OBJECT_STATISTIC_EXT:
unchanged:
--- a/src/backend/commands/collationcmds.c
+++ b/src/backend/commands/collationcmds.c
@@ -73,7 +73,7 @@ DefineCollation(ParseState *pstate, List *names, List *parameters, bool if_not_e
Oid newoid;
ObjectAddress address;
- collNamespace = QualifiedNameGetCreationNamespace(names, &collName);
+ collNamespace = QualifiedNameGetCreationNamespace(names, &collName, false);
aclresult = pg_namespace_aclcheck(collNamespace, GetUserId(), ACL_CREATE);
if (aclresult != ACLCHECK_OK)
unchanged:
--- a/src/backend/commands/conversioncmds.c
+++ b/src/backend/commands/conversioncmds.c
@@ -51,7 +51,7 @@ CreateConversionCommand(CreateConversionStmt *stmt)
/* Convert list of names to a name and namespace */
namespaceId = QualifiedNameGetCreationNamespace(stmt->conversion_name,
- &conversion_name);
+ &conversion_name, false);
/* Check we have creation rights in target namespace */
aclresult = pg_namespace_aclcheck(namespaceId, GetUserId(), ACL_CREATE);
unchanged:
--- a/src/backend/commands/event_trigger.c
+++ b/src/backend/commands/event_trigger.c
@@ -967,6 +967,7 @@ EventTriggerSupportsObjectType(ObjectType obtype)
case OBJECT_LANGUAGE:
case OBJECT_LARGEOBJECT:
case OBJECT_MATVIEW:
+ case OBJECT_MODULE:
case OBJECT_OPCLASS:
case OBJECT_OPERATOR:
case OBJECT_OPFAMILY:
@@ -2087,6 +2088,8 @@ stringify_grant_objtype(ObjectType objtype)
return "LANGUAGE";
case OBJECT_LARGEOBJECT:
return "LARGE OBJECT";
+ case OBJECT_MODULE:
+ return "MODULE";
case OBJECT_SCHEMA:
return "SCHEMA";
case OBJECT_PROCEDURE:
@@ -2169,6 +2172,8 @@ stringify_adefprivs_objtype(ObjectType objtype)
return "LANGUAGES";
case OBJECT_LARGEOBJECT:
return "LARGE OBJECTS";
+ case OBJECT_MODULE:
+ return "MODULES";
case OBJECT_SCHEMA:
return "SCHEMAS";
case OBJECT_PROCEDURE:
unchanged:
--- a/src/backend/commands/functioncmds.c
+++ b/src/backend/commands/functioncmds.c
@@ -148,7 +148,7 @@ compute_return_type(TypeName *returnType, Oid languageOid,
errmsg("type \"%s\" is not yet defined", typnam),
errdetail("Creating a shell type definition.")));
namespaceId = QualifiedNameGetCreationNamespace(returnType->names,
- &typname);
+ &typname, false);
aclresult = pg_namespace_aclcheck(namespaceId, GetUserId(),
ACL_CREATE);
if (aclresult != ACLCHECK_OK)
@@ -1050,7 +1050,7 @@ CreateFunction(ParseState *pstate, CreateFunctionStmt *stmt)
/* Convert list of names to a name and namespace */
namespaceId = QualifiedNameGetCreationNamespace(stmt->funcname,
- &funcname);
+ &funcname, true);
/* Check we have creation rights in target namespace */
aclresult = pg_namespace_aclcheck(namespaceId, GetUserId(), ACL_CREATE);
unchanged:
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -2039,7 +2039,7 @@ ResolveOpClass(List *opclass, Oid attrType,
*/
/* deconstruct the name list */
- DeconstructQualifiedName(opclass, &schemaname, &opcname);
+ DeconstructQualifiedName(opclass, &schemaname, NULL, &opcname, false);
if (schemaname)
{
@@ -2787,7 +2787,7 @@ ReindexMultipleTables(const char *objectName, ReindexObjectType objectKind,
*/
if (objectKind == REINDEX_OBJECT_SCHEMA)
{
- objectOid = get_namespace_oid(objectName, false);
+ objectOid = get_namespace_oid(objectName, InvalidOid, false);
if (!pg_namespace_ownercheck(objectOid, GetUserId()))
aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_SCHEMA,
unchanged:
--- a/src/backend/commands/opclasscmds.c
+++ b/src/backend/commands/opclasscmds.c
@@ -85,7 +85,7 @@ OpFamilyCacheLookup(Oid amID, List *opfamilyname, bool missing_ok)
HeapTuple htup;
/* deconstruct the name list */
- DeconstructQualifiedName(opfamilyname, &schemaname, &opfname);
+ DeconstructQualifiedName(opfamilyname, &schemaname, NULL, &opfname, false);
if (schemaname)
{
@@ -166,7 +166,7 @@ OpClassCacheLookup(Oid amID, List *opclassname, bool missing_ok)
HeapTuple htup;
/* deconstruct the name list */
- DeconstructQualifiedName(opclassname, &schemaname, &opcname);
+ DeconstructQualifiedName(opclassname, &schemaname, NULL, &opcname, false);
if (schemaname)
{
@@ -354,7 +354,7 @@ DefineOpClass(CreateOpClassStmt *stmt)
/* Convert list of names to a name and namespace */
namespaceoid = QualifiedNameGetCreationNamespace(stmt->opclassname,
- &opcname);
+ &opcname, false);
/* Check we have creation rights in target namespace */
aclresult = pg_namespace_aclcheck(namespaceoid, GetUserId(), ACL_CREATE);
@@ -769,7 +769,7 @@ DefineOpFamily(CreateOpFamilyStmt *stmt)
/* Convert list of names to a name and namespace */
namespaceoid = QualifiedNameGetCreationNamespace(stmt->opfamilyname,
- &opfname);
+ &opfname, false);
/* Check we have creation rights in target namespace */
aclresult = pg_namespace_aclcheck(namespaceoid, GetUserId(), ACL_CREATE);
unchanged:
--- a/src/backend/commands/operatorcmds.c
+++ b/src/backend/commands/operatorcmds.c
@@ -87,7 +87,7 @@ DefineOperator(List *names, List *parameters)
ListCell *pl;
/* Convert list of names to a name and namespace */
- oprNamespace = QualifiedNameGetCreationNamespace(names, &oprName);
+ oprNamespace = QualifiedNameGetCreationNamespace(names, &oprName, false);
/* Check we have creation rights in target namespace */
aclresult = pg_namespace_aclcheck(oprNamespace, GetUserId(), ACL_CREATE);
unchanged:
--- a/src/backend/commands/seclabel.c
+++ b/src/backend/commands/seclabel.c
@@ -48,6 +48,7 @@ SecLabelSupportsObjectType(ObjectType objtype)
case OBJECT_LANGUAGE:
case OBJECT_LARGEOBJECT:
case OBJECT_MATVIEW:
+ case OBJECT_MODULE:
case OBJECT_PROCEDURE:
case OBJECT_PUBLICATION:
case OBJECT_ROLE:
unchanged:
--- a/src/backend/commands/statscmds.c
+++ b/src/backend/commands/statscmds.c
@@ -163,7 +163,7 @@ CreateStatistics(CreateStatsStmt *stmt)
*/
if (stmt->defnames)
namespaceId = QualifiedNameGetCreationNamespace(stmt->defnames,
- &namestr);
+ &namestr, false);
else
{
namespaceId = RelationGetNamespace(rel);
@@ -630,7 +630,7 @@ AlterStatistics(AlterStatsStmt *stmt)
Assert(stmt->missing_ok);
- DeconstructQualifiedName(stmt->defnames, &schemaname, &statname);
+ DeconstructQualifiedName(stmt->defnames, &schemaname, NULL, &statname, false);
if (schemaname)
ereport(NOTICE,
unchanged:
--- a/src/backend/commands/tsearchcmds.c
+++ b/src/backend/commands/tsearchcmds.c
@@ -196,7 +196,7 @@ DefineTSParser(List *names, List *parameters)
prsRel = table_open(TSParserRelationId, RowExclusiveLock);
/* Convert list of names to a name and namespace */
- namespaceoid = QualifiedNameGetCreationNamespace(names, &prsname);
+ namespaceoid = QualifiedNameGetCreationNamespace(names, &prsname, false);
/* initialize tuple fields with name/namespace */
memset(values, 0, sizeof(values));
@@ -405,7 +405,7 @@ DefineTSDictionary(List *names, List *parameters)
ObjectAddress address;
/* Convert list of names to a name and namespace */
- namespaceoid = QualifiedNameGetCreationNamespace(names, &dictname);
+ namespaceoid = QualifiedNameGetCreationNamespace(names, &dictname, false);
/* Check we have creation rights in target namespace */
aclresult = pg_namespace_aclcheck(namespaceoid, GetUserId(), ACL_CREATE);
@@ -701,7 +701,7 @@ DefineTSTemplate(List *names, List *parameters)
errmsg("must be superuser to create text search templates")));
/* Convert list of names to a name and namespace */
- namespaceoid = QualifiedNameGetCreationNamespace(names, &tmplname);
+ namespaceoid = QualifiedNameGetCreationNamespace(names, &tmplname, false);
tmplRel = table_open(TSTemplateRelationId, RowExclusiveLock);
@@ -908,7 +908,7 @@ DefineTSConfiguration(List *names, List *parameters, ObjectAddress *copied)
ObjectAddress address;
/* Convert list of names to a name and namespace */
- namespaceoid = QualifiedNameGetCreationNamespace(names, &cfgname);
+ namespaceoid = QualifiedNameGetCreationNamespace(names, &cfgname, false);
/* Check we have creation rights in target namespace */
aclresult = pg_namespace_aclcheck(namespaceoid, GetUserId(), ACL_CREATE);
unchanged:
--- a/src/backend/commands/typecmds.c
+++ b/src/backend/commands/typecmds.c
@@ -217,7 +217,7 @@ DefineType(ParseState *pstate, List *names, List *parameters)
errmsg("must be superuser to create a base type")));
/* Convert list of names to a name and namespace */
- typeNamespace = QualifiedNameGetCreationNamespace(names, &typeName);
+ typeNamespace = QualifiedNameGetCreationNamespace(names, &typeName, false);
#ifdef NOT_USED
/* XXX this is unnecessary given the superuser check above */
@@ -733,7 +733,7 @@ DefineDomain(CreateDomainStmt *stmt)
/* Convert list of names to a name and namespace */
domainNamespace = QualifiedNameGetCreationNamespace(stmt->domainname,
- &domainName);
+ &domainName, false);
/* Check we have creation rights in target namespace */
aclresult = pg_namespace_aclcheck(domainNamespace, GetUserId(),
@@ -1149,7 +1149,7 @@ DefineEnum(CreateEnumStmt *stmt)
/* Convert list of names to a name and namespace */
enumNamespace = QualifiedNameGetCreationNamespace(stmt->typeName,
- &enumName);
+ &enumName, false);
/* Check we have creation rights in target namespace */
aclresult = pg_namespace_aclcheck(enumNamespace, GetUserId(), ACL_CREATE);
@@ -1369,7 +1369,7 @@ DefineRange(CreateRangeStmt *stmt)
/* Convert list of names to a name and namespace */
typeNamespace = QualifiedNameGetCreationNamespace(stmt->typeName,
- &typeName);
+ &typeName, false);
/* Check we have creation rights in target namespace */
aclresult = pg_namespace_aclcheck(typeNamespace, GetUserId(), ACL_CREATE);
@@ -1457,7 +1457,7 @@ DefineRange(CreateRangeStmt *stmt)
errmsg("conflicting or redundant options")));
/* we can look up the subtype name immediately */
multirangeNamespace = QualifiedNameGetCreationNamespace(defGetQualifiedName(defel),
- &multirangeTypeName);
+ &multirangeTypeName, false);
}
else
ereport(ERROR,
unchanged:
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -262,7 +262,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
struct GroupClause *groupclause;
}
-%type <node> stmt toplevel_stmt schema_stmt routine_body_stmt
+%type <node> stmt toplevel_stmt schema_stmt routine_body_stmt module_stmt
AlterEventTrigStmt AlterCollationStmt
AlterDatabaseStmt AlterDatabaseSetStmt AlterDomainStmt AlterEnumStmt
AlterFdwStmt AlterForeignServerStmt AlterGroupStmt
@@ -301,6 +301,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
CreateMatViewStmt RefreshMatViewStmt CreateAmStmt
CreatePublicationStmt AlterPublicationStmt
CreateSubscriptionStmt AlterSubscriptionStmt DropSubscriptionStmt
+ CreateModuleStmt
%type <node> select_no_parens select_with_parens select_clause
simple_select values_clause
@@ -344,7 +345,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
%type <str> opt_in_database
%type <str> OptSchemaName
-%type <list> OptSchemaEltList
+%type <list> OptSchemaEltList OptModuleEltList
%type <chr> am_type
@@ -368,7 +369,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
%type <list> func_name handler_name qual_Op qual_all_Op subquery_Op
opt_class opt_inline_handler opt_validator validator_clause
- opt_collate
+ opt_collate module_name
%type <range> qualified_name insert_target OptConstrFromTable
@@ -681,7 +682,8 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
LEADING LEAKPROOF LEAST LEFT LEVEL LIKE LIMIT LISTEN LOAD LOCAL
LOCALTIME LOCALTIMESTAMP LOCATION LOCK_P LOCKED LOGGED
- MAPPING MATCH MATERIALIZED MAXVALUE METHOD MINUTE_P MINVALUE MODE MONTH_P MOVE
+ MAPPING MATCH MATERIALIZED MAXVALUE METHOD MINUTE_P MINVALUE MODE MODULE
+ MONTH_P MOVE
NAME_P NAMES NATIONAL NATURAL NCHAR NEW NEXT NFC NFD NFKC NFKD NO NONE
NORMALIZE NORMALIZED
@@ -954,6 +956,7 @@ stmt:
| CreateFunctionStmt
| CreateGroupStmt
| CreateMatViewStmt
+ | CreateModuleStmt
| CreateOpClassStmt
| CreateOpFamilyStmt
| CreatePublicationStmt
@@ -1466,6 +1469,84 @@ schema_stmt:
| ViewStmt
;
+/*****************************************************************************
+ *
+ * Manipulate a module
+ *
+ *****************************************************************************/
+
+CreateModuleStmt:
+ CREATE MODULE module_name OptModuleEltList
+ {
+ CreateModuleStmt *n = makeNode(CreateModuleStmt);
+ n->modulename = $3;
+ n->authrole = NULL;
+ n->moduleElts = $4;
+ n->if_not_exists = false;
+ $$ = (Node *)n;
+ }
+ | CREATE MODULE module_name OWNER RoleSpec OptModuleEltList
+ {
+ CreateModuleStmt *n = makeNode(CreateModuleStmt);
+ n->modulename = $3;
+ n->authrole = $5;
+ n->moduleElts = $6;
+ n->if_not_exists = false;
+ $$ = (Node *)n;
+ }
+ | CREATE MODULE IF_P NOT EXISTS module_name OptModuleEltList
+ {
+ CreateModuleStmt *n = makeNode(CreateModuleStmt);
+ n->modulename = $6;
+ n->authrole = NULL;
+ if ($7 != NIL)
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("CREATE MODULE IF NOT EXISTS cannot include module elements"),
+ parser_errposition(@7)));
+ n->moduleElts = $7;
+ n->if_not_exists = true;
+ $$ = (Node *)n;
+ }
+ | CREATE MODULE IF_P NOT EXISTS module_name OWNER RoleSpec OptModuleEltList
+ {
+ CreateModuleStmt *n = makeNode(CreateModuleStmt);
+ n->modulename = $6;
+ n->authrole = $8;
+ if ($9 != NIL)
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("CREATE MODULE IF NOT EXISTS cannot include module elements"),
+ parser_errposition(@9)));
+ n->moduleElts = $9;
+ n->if_not_exists = true;
+ $$ = (Node *)n;
+ }
+ ;
+
+module_name:
+ name { $$ = list_make1(makeString($1)); }
+ | name attrs { $$ = lcons(makeString($1), $2); }
+ ;
+
+OptModuleEltList:
+ OptModuleEltList module_stmt
+ {
+ if (@$ < 0) /* see comments for YYLLOC_DEFAULT */
+ @$ = @2;
+ $$ = lappend($1, $2);
+ }
+ | /* EMPTY */
+ { $$ = NIL; }
+ ;
+
+/*
+ * module_stmt are the ones that can show up inside a CREATE MODULE statement.
+ */
+module_stmt:
+ CreateFunctionStmt
+ ;
+
/*****************************************************************************
*
@@ -6308,6 +6389,26 @@ DropStmt: DROP object_type_any_name IF_P EXISTS any_name_list opt_drop_behavior
n->concurrent = true;
$$ = (Node *)n;
}
+ | DROP MODULE any_name_list opt_drop_behavior
+ {
+ DropStmt *n = makeNode(DropStmt);
+ n->removeType = OBJECT_MODULE;
+ n->objects = $3;
+ n->behavior = $4;
+ n->missing_ok = false;
+ n->concurrent = false;
+ $$ = (Node *)n;
+ }
+ | DROP MODULE IF_P EXISTS any_name_list opt_drop_behavior
+ {
+ DropStmt *n = makeNode(DropStmt);
+ n->removeType = OBJECT_MODULE;
+ n->objects = $5;
+ n->behavior = $6;
+ n->missing_ok = true;
+ n->concurrent = false;
+ $$ = (Node *)n;
+ }
;
/* object types taking any_name/any_name_list */
@@ -8569,6 +8670,15 @@ RenameStmt: ALTER AGGREGATE aggregate_with_argtypes RENAME TO name
n->missing_ok = false;
$$ = (Node *)n;
}
+ | ALTER MODULE module_name RENAME TO name
+ {
+ RenameStmt *n = makeNode(RenameStmt);
+ n->renameType = OBJECT_MODULE;
+ n->object = (Node *) $3;
+ n->newname = $6;
+ n->missing_ok = false;
+ $$ = (Node *)n;
+ }
| ALTER opt_procedural LANGUAGE name RENAME TO name
{
RenameStmt *n = makeNode(RenameStmt);
@@ -15639,6 +15749,7 @@ unreserved_keyword:
| MINUTE_P
| MINVALUE
| MODE
+ | MODULE
| MONTH_P
| MOVE
| NAME_P
@@ -16205,6 +16316,7 @@ bare_label_keyword:
| METHOD
| MINVALUE
| MODE
+ | MODULE
| MOVE
| NAME_P
| NAMES
unchanged:
--- a/src/backend/parser/parse_func.c
+++ b/src/backend/parser/parse_func.c
@@ -18,8 +18,10 @@
#include "catalog/pg_aggregate.h"
#include "catalog/pg_proc.h"
#include "catalog/pg_type.h"
+#include "commands/dbcommands.h"
#include "funcapi.h"
#include "lib/stringinfo.h"
+#include "miscadmin.h"
#include "nodes/makefuncs.h"
#include "nodes/nodeFuncs.h"
#include "parser/parse_agg.h"
@@ -1421,7 +1423,6 @@ func_get_detail(List *funcname,
raw_candidates = FuncnameGetCandidates(funcname, nargs, fargnames,
expand_variadic, expand_defaults,
false);
-
/*
* Quickly check if there is an exact match to the input datatypes (there
* can be only one)
@@ -1549,7 +1550,6 @@ func_get_detail(List *funcname,
/* one match only? then run with it... */
if (ncandidates == 1)
best_candidate = current_candidates;
-
/*
* multiple candidates? then better decide or throw an error...
*/
@@ -1882,6 +1882,16 @@ FuncNameAsType(List *funcname)
Oid result;
Type typtup;
+ /*
+ * check if this may be in a module. If it could be, don't check if it
+ * may be a type since they can not be in a module
+ */
+ if (list_length(funcname) == 3)
+ {
+ if (strcmp(strVal(linitial(funcname)), get_database_name(MyDatabaseId)) != 0)
+ return InvalidOid;
+ }
+
/*
* temp_ok=false protects the <refsect1 id="sql-createfunction-security">
* contract for writing SECURITY DEFINER functions safely.
@@ -2058,7 +2068,6 @@ LookupFuncNameInternal(List *funcname, int nargs, const Oid *argtypes,
clist = FuncnameGetCandidates(funcname, nargs, NIL, false, false,
missing_ok);
-
/*
* If no arguments were specified, the name must yield a unique candidate.
*/
unchanged:
--- a/src/backend/parser/parse_oper.c
+++ b/src/backend/parser/parse_oper.c
@@ -954,7 +954,7 @@ make_oper_cache_key(ParseState *pstate, OprCacheKey *key, List *opname,
char *opername;
/* deconstruct the name list */
- DeconstructQualifiedName(opname, &schemaname, &opername);
+ DeconstructQualifiedName(opname, &schemaname, NULL, &opername, false);
/* ensure zero-fill for stable hashing */
MemSet(key, 0, sizeof(OprCacheKey));
unchanged:
--- a/src/backend/parser/parse_type.c
+++ b/src/backend/parser/parse_type.c
@@ -166,7 +166,7 @@ LookupTypeNameExtended(ParseState *pstate,
char *typname;
/* deconstruct the name list */
- DeconstructQualifiedName(typeName->names, &schemaname, &typname);
+ DeconstructQualifiedName(typeName->names, &schemaname, NULL, &typname, false);
if (schemaname)
{
unchanged:
--- a/src/backend/parser/parse_utilcmd.c
+++ b/src/backend/parser/parse_utilcmd.c
@@ -113,6 +113,14 @@ typedef struct
List *grants; /* GRANT items */
} CreateSchemaStmtContext;
+/* State shared by transformCreateModuleStmt and its subroutines */
+typedef struct
+{
+ const char *stmtType; /* "CREATE MODULE" or "ALTER MODULE" */
+ List *modulename; /* name of module */
+ RoleSpec *authrole; /* owner of module */
+ List *functions; /* CREATE FUNCTION items */
+} CreateModuleStmtContext;
static void transformColumnDefinition(CreateStmtContext *cxt,
ColumnDef *column);
@@ -3944,6 +3952,70 @@ transformCreateSchemaStmt(CreateSchemaStmt *stmt)
return result;
}
+/*
+ * transformCreateModuleStmt -
+ * analyzes the CREATE MODULE statement
+ *
+ * Split the module element list into individual commands and place
+ * them in the result list in an order such that there are no forward
+ * references. Currently there are only functions allowed in modules
+ * but the spec allows variables and temp tables so this provides a
+ * way to have them created before the functions that could use them.
+ *
+ * The functions are also checked to make sure there is not an explicit
+ * namespace attempted to be used.
+ */
+List *
+transformCreateModuleStmt(CreateModuleStmt *stmt)
+{
+ CreateModuleStmtContext cxt;
+ List *result;
+ ListCell *elements;
+
+
+ cxt.stmtType = "CREATE MODULE";
+ cxt.modulename = stmt->modulename;
+ cxt.authrole = (RoleSpec *) stmt->authrole;
+ cxt.functions = NIL;
+
+ /*
+ * Run through each module element in the module element list. Separate
+ * statements by type, and do preliminary analysis.
+ */
+ foreach(elements, stmt->moduleElts)
+ {
+ Node *element = lfirst(elements);
+
+ switch (nodeTag(element))
+ {
+ case T_CreateFunctionStmt:
+ {
+ CreateFunctionStmt *elp = (CreateFunctionStmt *) element;
+
+ if (list_length(elp->funcname) > 1)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_SCHEMA_DEFINITION),
+ errmsg("CREATE FUNCTION (%s) specifies a "
+ "namespace inside of CREATE MODULE (%s)",
+ NameListToString(elp->funcname),
+ NameListToString(cxt.modulename))));
+
+ cxt.functions = lappend(cxt.functions, element);
+ }
+ break;
+
+ default:
+ elog(ERROR, "unrecognized node type: %d",
+ (int) nodeTag(element));
+ }
+ }
+
+ result = NIL;
+ result = list_concat(result, cxt.functions);
+
+ return result;
+}
+
/*
* setSchemaName
* Set or check schema name in an element of a CREATE SCHEMA command
unchanged:
--- a/src/backend/tcop/utility.c
+++ b/src/backend/tcop/utility.c
@@ -42,6 +42,7 @@
#include "commands/extension.h"
#include "commands/lockcmds.h"
#include "commands/matview.h"
+#include "commands/modulecmds.h"
#include "commands/policy.h"
#include "commands/portalcmds.h"
#include "commands/prepare.h"
@@ -178,6 +179,7 @@ ClassifyUtilityCommandAsReadOnly(Node *parsetree)
case T_CreateForeignServerStmt:
case T_CreateForeignTableStmt:
case T_CreateFunctionStmt:
+ case T_CreateModuleStmt:
case T_CreateOpClassStmt:
case T_CreateOpFamilyStmt:
case T_CreatePLangStmt:
@@ -1097,6 +1099,19 @@ ProcessUtilitySlow(ParseState *pstate,
commandCollected = true;
break;
+ case T_CreateModuleStmt: /* CREATE Module */
+ CreateModuleCommand(pstate, (CreateModuleStmt *) parsetree,
+ queryString,
+ pstmt->stmt_location,
+ pstmt->stmt_len);
+ /*
+ * EventTriggerCollectSimpleCommand called by
+ * CreateModuleCommand
+ */
+ commandCollected = true;
+ break;
+
+
case T_CreateStmt:
case T_CreateForeignTableStmt:
{
@@ -2280,6 +2295,9 @@ AlterObjectTypeCommandTag(ObjectType objtype)
case OBJECT_STATISTIC_EXT:
tag = CMDTAG_ALTER_STATISTICS;
break;
+ case OBJECT_MODULE:
+ tag = CMDTAG_ALTER_MODULE;
+ break;
default:
tag = CMDTAG_UNKNOWN;
break;
@@ -2584,6 +2602,9 @@ CreateCommandTag(Node *parsetree)
case OBJECT_STATISTIC_EXT:
tag = CMDTAG_DROP_STATISTICS;
break;
+ case OBJECT_MODULE:
+ tag = CMDTAG_DROP_MODULE;
+ break;
default:
tag = CMDTAG_UNKNOWN;
}
@@ -2739,6 +2760,10 @@ CreateCommandTag(Node *parsetree)
tag = CMDTAG_CREATE_FUNCTION;
break;
+ case T_CreateModuleStmt:
+ tag = CMDTAG_CREATE_MODULE;
+ break;
+
case T_IndexStmt:
tag = CMDTAG_CREATE_INDEX;
break;
@@ -3382,6 +3407,10 @@ GetCommandLogLevel(Node *parsetree)
lev = LOGSTMT_DDL;
break;
+ case T_CreateModuleStmt:
+ lev = LOGSTMT_DDL;
+ break;
+
case T_IndexStmt:
lev = LOGSTMT_DDL;
break;
only in patch2:
unchanged:
--- a/src/include/nodes/nodes.h
+++ b/src/include/nodes/nodes.h
@@ -432,6 +432,7 @@ typedef enum NodeTag
T_AlterCollationStmt,
T_CallStmt,
T_AlterStatsStmt,
+ T_CreateModuleStmt,
/*
* TAGS FOR PARSE TREE NODES (parsenodes.h)
only in patch2:
unchanged:
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -1798,6 +1798,7 @@ typedef enum ObjectType
OBJECT_LANGUAGE,
OBJECT_LARGEOBJECT,
OBJECT_MATVIEW,
+ OBJECT_MODULE,
OBJECT_OPCLASS,
OBJECT_OPERATOR,
OBJECT_OPFAMILY,
@@ -2975,6 +2976,24 @@ typedef struct AlterFunctionStmt
List *actions; /* list of DefElem */
} AlterFunctionStmt;
+/* ----------------------
+ * Create Module Statement
+ *
+ * NOTE: the moduleElts list contains raw parsetrees for component statements
+ * of the schema, such as CREATE FUNCTION, CREATE PROCEDURE, etc. These are
+ * analyzed and executed after the module itself is created.
+ * ----------------------
+ */
+typedef struct CreateModuleStmt
+{
+ NodeTag type;
+ List *modulename; /* the name of the schema to create */
+ RoleSpec *authrole; /* the owner of the created schema */
+ List *moduleElts; /* module components (list of parsenodes) */
+ bool if_not_exists; /* just do nothing if module already exists? */
+} CreateModuleStmt;
+
+
/* ----------------------
* DO Statement
*
only in patch2:
unchanged:
--- a/src/include/parser/kwlist.h
+++ b/src/include/parser/kwlist.h
@@ -257,6 +257,7 @@ PG_KEYWORD("method", METHOD, UNRESERVED_KEYWORD, BARE_LABEL)
PG_KEYWORD("minute", MINUTE_P, UNRESERVED_KEYWORD, AS_LABEL)
PG_KEYWORD("minvalue", MINVALUE, UNRESERVED_KEYWORD, BARE_LABEL)
PG_KEYWORD("mode", MODE, UNRESERVED_KEYWORD, BARE_LABEL)
+PG_KEYWORD("module", MODULE, UNRESERVED_KEYWORD, BARE_LABEL)
PG_KEYWORD("month", MONTH_P, UNRESERVED_KEYWORD, AS_LABEL)
PG_KEYWORD("move", MOVE, UNRESERVED_KEYWORD, BARE_LABEL)
PG_KEYWORD("name", NAME_P, UNRESERVED_KEYWORD, BARE_LABEL)
only in patch2:
unchanged:
--- a/src/include/parser/parse_utilcmd.h
+++ b/src/include/parser/parse_utilcmd.h
@@ -31,6 +31,7 @@ extern CreateStatsStmt *transformStatsStmt(Oid relid, CreateStatsStmt *stmt,
extern void transformRuleStmt(RuleStmt *stmt, const char *queryString,
List **actions, Node **whereClause);
extern List *transformCreateSchemaStmt(CreateSchemaStmt *stmt);
+extern List *transformCreateModuleStmt(CreateModuleStmt *stmt);
extern PartitionBoundSpec *transformPartitionBound(ParseState *pstate, Relation parent,
PartitionBoundSpec *spec);
extern List *expandTableLikeClause(RangeVar *heapRel,
only in patch2:
unchanged:
--- a/src/include/tcop/cmdtaglist.h
+++ b/src/include/tcop/cmdtaglist.h
@@ -43,6 +43,7 @@ PG_CMDTAG(CMDTAG_ALTER_INDEX, "ALTER INDEX", true, false, false)
PG_CMDTAG(CMDTAG_ALTER_LANGUAGE, "ALTER LANGUAGE", true, false, false)
PG_CMDTAG(CMDTAG_ALTER_LARGE_OBJECT, "ALTER LARGE OBJECT", true, false, false)
PG_CMDTAG(CMDTAG_ALTER_MATERIALIZED_VIEW, "ALTER MATERIALIZED VIEW", true, false, false)
+PG_CMDTAG(CMDTAG_ALTER_MODULE, "ALTER MODULE", true, false, false)
PG_CMDTAG(CMDTAG_ALTER_OPERATOR, "ALTER OPERATOR", true, false, false)
PG_CMDTAG(CMDTAG_ALTER_OPERATOR_CLASS, "ALTER OPERATOR CLASS", true, false, false)
PG_CMDTAG(CMDTAG_ALTER_OPERATOR_FAMILY, "ALTER OPERATOR FAMILY", true, false, false)
@@ -98,6 +99,7 @@ PG_CMDTAG(CMDTAG_CREATE_FUNCTION, "CREATE FUNCTION", true, false, false)
PG_CMDTAG(CMDTAG_CREATE_INDEX, "CREATE INDEX", true, false, false)
PG_CMDTAG(CMDTAG_CREATE_LANGUAGE, "CREATE LANGUAGE", true, false, false)
PG_CMDTAG(CMDTAG_CREATE_MATERIALIZED_VIEW, "CREATE MATERIALIZED VIEW", true, false, false)
+PG_CMDTAG(CMDTAG_CREATE_MODULE, "CREATE MODULE", true, false, false)
PG_CMDTAG(CMDTAG_CREATE_OPERATOR, "CREATE OPERATOR", true, false, false)
PG_CMDTAG(CMDTAG_CREATE_OPERATOR_CLASS, "CREATE OPERATOR CLASS", true, false, false)
PG_CMDTAG(CMDTAG_CREATE_OPERATOR_FAMILY, "CREATE OPERATOR FAMILY", true, false, false)
@@ -150,6 +152,7 @@ PG_CMDTAG(CMDTAG_DROP_FUNCTION, "DROP FUNCTION", true, false, false)
PG_CMDTAG(CMDTAG_DROP_INDEX, "DROP INDEX", true, false, false)
PG_CMDTAG(CMDTAG_DROP_LANGUAGE, "DROP LANGUAGE", true, false, false)
PG_CMDTAG(CMDTAG_DROP_MATERIALIZED_VIEW, "DROP MATERIALIZED VIEW", true, false, false)
+PG_CMDTAG(CMDTAG_DROP_MODULE, "DROP MODULE", true, false, false)
PG_CMDTAG(CMDTAG_DROP_OPERATOR, "DROP OPERATOR", true, false, false)
PG_CMDTAG(CMDTAG_DROP_OPERATOR_CLASS, "DROP OPERATOR CLASS", true, false, false)
PG_CMDTAG(CMDTAG_DROP_OPERATOR_FAMILY, "DROP OPERATOR FAMILY", true, false, false)