diff --git a/src/backend/catalog/objectaddress.c b/src/backend/catalog/objectaddress.c index 6cac2df..46b72b4 100644 --- a/src/backend/catalog/objectaddress.c +++ b/src/backend/catalog/objectaddress.c @@ -721,7 +721,8 @@ const ObjectAddress InvalidObjectAddress = InvalidOid, 0 }; - +static ObjectAddress get_object_address_database(ObjectType objtype, + DBSpecName * object, bool missing_ok); static ObjectAddress get_object_address_unqualified(ObjectType objtype, Value *strval, bool missing_ok); static ObjectAddress get_relation_by_qualified_name(ObjectType objtype, @@ -865,6 +866,8 @@ get_object_address(ObjectType objtype, Node *object, } break; case OBJECT_DATABASE: + address = get_object_address_database(objtype, (DBSpecName*)object, missing_ok); + break; case OBJECT_EXTENSION: case OBJECT_TABLESPACE: case OBJECT_ROLE: @@ -1108,6 +1111,28 @@ get_object_address_rv(ObjectType objtype, RangeVar *rel, List *object, /* * Find an ObjectAddress for a type of object that is identified by an + * database name + */ +static ObjectAddress +get_object_address_database(ObjectType objtype, DBSpecName * object, bool missing_ok) +{ + char *dbname; + ObjectAddress address; + + if (object && object->dbnametype == DBSPEC_CURRENT_DATABASE ) + dbname = get_database_name(MyDatabaseId); + else + dbname = object->dbname; + + address.classId = DatabaseRelationId; + address.objectId = get_database_oid(dbname, missing_ok); + address.objectSubId = 0; + + return address; +} + +/* + * Find an ObjectAddress for a type of object that is identified by an * unqualified name. */ static ObjectAddress @@ -2241,8 +2266,20 @@ check_object_ownership(Oid roleid, ObjectType objtype, ObjectAddress address, break; case OBJECT_DATABASE: if (!pg_database_ownercheck(address.objectId, roleid)) - aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_DATABASE, - strVal((Value *) object)); + { + char *dbname; + DBSpecName *dbspecname; + + /* Format is valid, extract the actual name. */ + dbspecname = (DBSpecName*)object; + + if (dbspecname->dbnametype == DBSPEC_CURRENT_DATABASE ) + dbname = get_database_name(MyDatabaseId); + else + dbname = dbspecname->dbname; + + aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_DATABASE,dbname); + } break; case OBJECT_TYPE: case OBJECT_DOMAIN: diff --git a/src/backend/commands/alter.c b/src/backend/commands/alter.c index 4f81479..ec5ca7e 100644 --- a/src/backend/commands/alter.c +++ b/src/backend/commands/alter.c @@ -802,7 +802,7 @@ ExecAlterOwnerStmt(AlterOwnerStmt *stmt) switch (stmt->objectType) { case OBJECT_DATABASE: - return AlterDatabaseOwner(strVal((Value *) stmt->object), newowner); + return AlterDatabaseOwner((DBSpecName*) stmt->object, newowner); case OBJECT_SCHEMA: return AlterSchemaOwner(strVal((Value *) stmt->object), newowner); diff --git a/src/backend/commands/comment.c b/src/backend/commands/comment.c index 1c17927..7e01943a 100644 --- a/src/backend/commands/comment.c +++ b/src/backend/commands/comment.c @@ -52,13 +52,20 @@ CommentObject(CommentStmt *stmt) */ if (stmt->objtype == OBJECT_DATABASE) { - char *database = strVal((Value *) stmt->object); + char *dbname = NULL; + DBSpecName *dbspecname = NULL; - if (!OidIsValid(get_database_oid(database, true))) + dbspecname = (DBSpecName*)stmt->object; + + if (dbspecname->dbnametype == DBSPEC_CURRENT_DATABASE ) + dbname = get_database_name(MyDatabaseId); + else + dbname = dbspecname->dbname; + if (!OidIsValid(get_database_oid(dbname, true))) { ereport(WARNING, (errcode(ERRCODE_UNDEFINED_DATABASE), - errmsg("database \"%s\" does not exist", database))); + errmsg("database \"%s\" does not exist", dbname))); return address; } } diff --git a/src/backend/commands/dbcommands.c b/src/backend/commands/dbcommands.c index e138539..c1ac129 100644 --- a/src/backend/commands/dbcommands.c +++ b/src/backend/commands/dbcommands.c @@ -1413,6 +1413,15 @@ AlterDatabase(ParseState *pstate, AlterDatabaseStmt *stmt, bool isTopLevel) Datum new_record[Natts_pg_database]; bool new_record_nulls[Natts_pg_database]; bool new_record_repl[Natts_pg_database]; + char *dbname = NULL; + DBSpecName *dbspecname = NULL; + + dbspecname = (DBSpecName*)stmt->dbspec; + + if (dbspecname->dbnametype == DBSPEC_CURRENT_DATABASE ) + dbname = get_database_name(MyDatabaseId); + else + dbname = dbspecname->dbname; /* Extract options from the statement node tree */ foreach(option, stmt->options) @@ -1477,7 +1486,7 @@ AlterDatabase(ParseState *pstate, AlterDatabaseStmt *stmt, bool isTopLevel) parser_errposition(pstate, dtablespace->location))); /* this case isn't allowed within a transaction block */ PreventTransactionChain(isTopLevel, "ALTER DATABASE SET TABLESPACE"); - movedb(stmt->dbname, defGetString(dtablespace)); + movedb(dbname, defGetString(dtablespace)); return InvalidOid; } @@ -1503,20 +1512,20 @@ AlterDatabase(ParseState *pstate, AlterDatabaseStmt *stmt, bool isTopLevel) ScanKeyInit(&scankey, Anum_pg_database_datname, BTEqualStrategyNumber, F_NAMEEQ, - CStringGetDatum(stmt->dbname)); + CStringGetDatum(dbname)); scan = systable_beginscan(rel, DatabaseNameIndexId, true, NULL, 1, &scankey); tuple = systable_getnext(scan); if (!HeapTupleIsValid(tuple)) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_DATABASE), - errmsg("database \"%s\" does not exist", stmt->dbname))); + errmsg("database \"%s\" does not exist", dbname))); dboid = HeapTupleGetOid(tuple); if (!pg_database_ownercheck(HeapTupleGetOid(tuple), GetUserId())) aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_DATABASE, - stmt->dbname); + dbname); /* * In order to avoid getting locked out and having to go through @@ -1574,7 +1583,18 @@ AlterDatabase(ParseState *pstate, AlterDatabaseStmt *stmt, bool isTopLevel) Oid AlterDatabaseSet(AlterDatabaseSetStmt *stmt) { - Oid datid = get_database_oid(stmt->dbname, false); + Oid datid; + char *dbname; + DBSpecName *dbspecname; + + dbspecname = (DBSpecName*)stmt->dbspec; + + if (dbspecname->dbnametype == DBSPEC_CURRENT_DATABASE ) + dbname = get_database_name(MyDatabaseId); + else + dbname = dbspecname->dbname; + + datid = get_database_oid(dbname, false); /* * Obtain a lock on the database and make sure it didn't go away in the @@ -1584,7 +1604,7 @@ AlterDatabaseSet(AlterDatabaseSetStmt *stmt) if (!pg_database_ownercheck(datid, GetUserId())) aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_DATABASE, - stmt->dbname); + dbname); AlterSetting(datid, InvalidOid, stmt->setstmt); @@ -1598,7 +1618,7 @@ AlterDatabaseSet(AlterDatabaseSetStmt *stmt) * ALTER DATABASE name OWNER TO newowner */ ObjectAddress -AlterDatabaseOwner(const char *dbname, Oid newOwnerId) +AlterDatabaseOwner(const DBSpecName *dbspec, Oid newOwnerId) { Oid db_id; HeapTuple tuple; @@ -1607,6 +1627,12 @@ AlterDatabaseOwner(const char *dbname, Oid newOwnerId) SysScanDesc scan; Form_pg_database datForm; ObjectAddress address; + char *dbname; + + if (dbspec->dbnametype == DBSPEC_CURRENT_DATABASE) + dbname = get_database_name(MyDatabaseId); + else + dbname = dbspec->dbname; /* * Get the old tuple. We don't need a lock on the database per se, diff --git a/src/backend/executor/execExprInterp.c b/src/backend/executor/execExprInterp.c index 83e0447..f56c302 100644 --- a/src/backend/executor/execExprInterp.c +++ b/src/backend/executor/execExprInterp.c @@ -1950,6 +1950,7 @@ ExecEvalSQLValueFunction(ExprState *state, ExprEvalStep *op) *op->resnull = fcinfo.isnull; break; case SVFOP_CURRENT_CATALOG: + case SVFOP_CURRENT_DATABASE: InitFunctionCallInfoData(fcinfo, NULL, 0, InvalidOid, NULL, NULL); *op->resvalue = current_database(&fcinfo); *op->resnull = fcinfo.isnull; diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c index f9ddf4e..2139c9c 100644 --- a/src/backend/nodes/copyfuncs.c +++ b/src/backend/nodes/copyfuncs.c @@ -2921,6 +2921,18 @@ _copyTriggerTransition(const TriggerTransition *from) return newnode; } +static DBSpecName * +_copyDatabaseSpec(const DBSpecName *from) +{ + DBSpecName *newnode = makeNode(DBSpecName); + + COPY_SCALAR_FIELD(dbnametype); + COPY_STRING_FIELD(dbname); + COPY_LOCATION_FIELD(location); + + return newnode; +} + static Query * _copyQuery(const Query *from) { @@ -3732,7 +3744,7 @@ _copyAlterDatabaseStmt(const AlterDatabaseStmt *from) { AlterDatabaseStmt *newnode = makeNode(AlterDatabaseStmt); - COPY_STRING_FIELD(dbname); + COPY_NODE_FIELD(dbspec); COPY_NODE_FIELD(options); return newnode; @@ -3743,7 +3755,7 @@ _copyAlterDatabaseSetStmt(const AlterDatabaseSetStmt *from) { AlterDatabaseSetStmt *newnode = makeNode(AlterDatabaseSetStmt); - COPY_STRING_FIELD(dbname); + COPY_NODE_FIELD(dbspec); COPY_NODE_FIELD(setstmt); return newnode; @@ -5529,7 +5541,9 @@ copyObjectImpl(const void *from) case T_PartitionCmd: retval = _copyPartitionCmd(from); break; - + case T_DBSpecName: + retval = _copyDatabaseSpec(from); + break; /* * MISCELLANEOUS NODES */ diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c index 8d92c03..e679ec5 100644 --- a/src/backend/nodes/equalfuncs.c +++ b/src/backend/nodes/equalfuncs.c @@ -1635,7 +1635,7 @@ _equalCreatedbStmt(const CreatedbStmt *a, const CreatedbStmt *b) static bool _equalAlterDatabaseStmt(const AlterDatabaseStmt *a, const AlterDatabaseStmt *b) { - COMPARE_STRING_FIELD(dbname); + COMPARE_NODE_FIELD(dbspec); COMPARE_NODE_FIELD(options); return true; @@ -1644,7 +1644,7 @@ _equalAlterDatabaseStmt(const AlterDatabaseStmt *a, const AlterDatabaseStmt *b) static bool _equalAlterDatabaseSetStmt(const AlterDatabaseSetStmt *a, const AlterDatabaseSetStmt *b) { - COMPARE_STRING_FIELD(dbname); + COMPARE_NODE_FIELD(dbspec); COMPARE_NODE_FIELD(setstmt); return true; @@ -2865,6 +2865,16 @@ _equalPartitionCmd(const PartitionCmd *a, const PartitionCmd *b) return true; } +static bool +_equalDatabaseSpec(const DBSpecName *a, const DBSpecName *b) +{ + COMPARE_SCALAR_FIELD(dbnametype); + COMPARE_STRING_FIELD(dbname); + COMPARE_LOCATION_FIELD(location); + + return true; +} + /* * Stuff from pg_list.h */ @@ -3675,6 +3685,9 @@ equal(const void *a, const void *b) case T_PartitionCmd: retval = _equalPartitionCmd(a, b); break; + case T_DBSpecName: + retval = _equalDatabaseSpec(a, b); + break; default: elog(ERROR, "unrecognized node type: %d", diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index 7d0de99..57516d5 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -187,7 +187,7 @@ static void processCASbits(int cas_bits, int location, const char *constrType, bool *deferrable, bool *initdeferred, bool *not_valid, bool *no_inherit, core_yyscan_t yyscanner); static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query); - +static Node *makeDBSpecName(DBSpecNameType type, int location); %} %pure-parser @@ -570,6 +570,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query); opt_frame_clause frame_extent frame_bound %type opt_existing_window_name %type opt_if_not_exists +%type db_spec_name %type generated_when override_kind %type PartitionSpec OptPartitionSpec %type part_strategy @@ -614,7 +615,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query); COMMITTED CONCURRENTLY CONFIGURATION CONFLICT CONNECTION CONSTRAINT CONSTRAINTS CONTENT_P CONTINUE_P CONVERSION_P COPY COST CREATE CROSS CSV CUBE CURRENT_P - CURRENT_CATALOG CURRENT_DATE CURRENT_ROLE CURRENT_SCHEMA + CURRENT_CATALOG CURRENT_DATABASE CURRENT_DATE CURRENT_ROLE CURRENT_SCHEMA CURRENT_TIME CURRENT_TIMESTAMP CURRENT_USER CURSOR CYCLE DATA_P DATABASE DAY_P DEALLOCATE DEC DECIMAL_P DECLARE DEFAULT DEFAULTS @@ -6264,6 +6265,14 @@ CommentStmt: n->comment = $6; $$ = (Node *) n; } + | COMMENT ON DATABASE db_spec_name IS comment_text + { + CommentStmt *n = makeNode(CommentStmt); + n->objtype = OBJECT_DATABASE; + n->object = (Node *) $4; + n->comment = $6; + $$ = (Node *) n; + } | COMMENT ON TYPE_P Typename IS comment_text { CommentStmt *n = makeNode(CommentStmt); @@ -6412,7 +6421,6 @@ comment_type_any_name: /* object types taking name */ comment_type_name: ACCESS METHOD { $$ = OBJECT_ACCESS_METHOD; } - | DATABASE { $$ = OBJECT_DATABASE; } | EVENT TRIGGER { $$ = OBJECT_EVENT_TRIGGER; } | EXTENSION { $$ = OBJECT_EXTENSION; } | FOREIGN DATA_P WRAPPER { $$ = OBJECT_FDW; } @@ -6461,6 +6469,16 @@ SecLabelStmt: n->label = $8; $$ = (Node *) n; } + | SECURITY LABEL opt_provider ON DATABASE db_spec_name + IS security_label + { + SecLabelStmt *n = makeNode(SecLabelStmt); + n->provider = $3; + n->objtype = OBJECT_DATABASE; + n->object = (Node *) $6; + n->label = $8; + $$ = (Node *) n; + } | SECURITY LABEL opt_provider ON TYPE_P Typename IS security_label { @@ -6529,8 +6547,7 @@ security_label_type_any_name: /* object types taking name */ security_label_type_name: - DATABASE { $$ = OBJECT_DATABASE; } - | EVENT TRIGGER { $$ = OBJECT_EVENT_TRIGGER; } + EVENT TRIGGER { $$ = OBJECT_EVENT_TRIGGER; } | opt_procedural LANGUAGE { $$ = OBJECT_LANGUAGE; } | PUBLICATION { $$ = OBJECT_PUBLICATION; } | ROLE { $$ = OBJECT_ROLE; } @@ -8959,11 +8976,11 @@ AlterOwnerStmt: ALTER AGGREGATE aggregate_with_argtypes OWNER TO RoleSpec n->newowner = $6; $$ = (Node *)n; } - | ALTER DATABASE database_name OWNER TO RoleSpec + | ALTER DATABASE db_spec_name OWNER TO RoleSpec { AlterOwnerStmt *n = makeNode(AlterOwnerStmt); n->objectType = OBJECT_DATABASE; - n->object = (Node *) makeString($3); + n->object = (Node *) $3; n->newowner = $6; $$ = (Node *)n; } @@ -9769,24 +9786,24 @@ opt_equal: '=' {} *****************************************************************************/ AlterDatabaseStmt: - ALTER DATABASE database_name WITH createdb_opt_list + ALTER DATABASE db_spec_name WITH createdb_opt_list { AlterDatabaseStmt *n = makeNode(AlterDatabaseStmt); - n->dbname = $3; + n->dbspec = $3; n->options = $5; $$ = (Node *)n; } - | ALTER DATABASE database_name createdb_opt_list + | ALTER DATABASE db_spec_name createdb_opt_list { AlterDatabaseStmt *n = makeNode(AlterDatabaseStmt); - n->dbname = $3; + n->dbspec = $3; n->options = $4; $$ = (Node *)n; } - | ALTER DATABASE database_name SET TABLESPACE name + | ALTER DATABASE db_spec_name SET TABLESPACE name { AlterDatabaseStmt *n = makeNode(AlterDatabaseStmt); - n->dbname = $3; + n->dbspec = $3; n->options = list_make1(makeDefElem("tablespace", (Node *)makeString($6), @6)); $$ = (Node *)n; @@ -9794,10 +9811,10 @@ AlterDatabaseStmt: ; AlterDatabaseSetStmt: - ALTER DATABASE database_name SetResetClause + ALTER DATABASE db_spec_name SetResetClause { AlterDatabaseSetStmt *n = makeNode(AlterDatabaseSetStmt); - n->dbname = $3; + n->dbspec = $3; n->setstmt = $4; $$ = (Node *)n; } @@ -13345,6 +13362,10 @@ func_expr_common_subexpr: { $$ = makeSQLValueFunction(SVFOP_SESSION_USER, -1, @1); } + | CURRENT_DATABASE + { + $$ = makeSQLValueFunction(SVFOP_CURRENT_DATABASE, -1, @1); + } | USER { $$ = makeSQLValueFunction(SVFOP_USER, -1, @1); @@ -14315,8 +14336,31 @@ name_list: name name: ColId { $$ = $1; }; database_name: - ColId { $$ = $1; }; + ColId + { $$ = $1; } + | CURRENT_DATABASE + { + ereport(ERROR, + (errcode(ERRCODE_RESERVED_NAME), + errmsg("%s cannot be used as a database name here", + "CURRENT_DATABASE"), + parser_errposition(@1))); + } + ; +db_spec_name: + ColId + { + DBSpecName *n = (DBSpecName *) makeDBSpecName(DBSPEC_CSTRING, @1); + n->dbname = pstrdup($1); + $$ = (Node *)n; + } + | CURRENT_DATABASE + { + $$ = (Node *) makeDBSpecName(DBSPEC_CURRENT_DATABASE, @1); + } + ; + access_method: ColId { $$ = $1; }; @@ -14341,6 +14385,8 @@ func_name: type_function_name $$ = check_func_name(lcons(makeString($1), $2), yyscanner); } + | CURRENT_DATABASE + { $$ = list_make1(makeString("current_database")); } ; @@ -14992,6 +15038,7 @@ reserved_keyword: | CONSTRAINT | CREATE | CURRENT_CATALOG + | CURRENT_DATABASE | CURRENT_DATE | CURRENT_ROLE | CURRENT_TIME @@ -15903,6 +15950,20 @@ makeRecursiveViewSelect(char *relname, List *aliases, Node *query) return (Node *) s; } +/* makeDBSpecName + * Create a DBSpecName with the given type + */ +static Node * +makeDBSpecName(DBSpecNameType type, int location) +{ + DBSpecName *spec = makeNode(DBSpecName); + + spec->dbnametype = type; + spec->location = location; + + return (Node *) spec; +} + /* parser_init() * Initialize to parse one query string */ diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c index 6d8cb07..504f049 100644 --- a/src/backend/parser/parse_expr.c +++ b/src/backend/parser/parse_expr.c @@ -2328,6 +2328,7 @@ transformSQLValueFunction(ParseState *pstate, SQLValueFunction *svf) case SVFOP_SESSION_USER: case SVFOP_CURRENT_CATALOG: case SVFOP_CURRENT_SCHEMA: + case SVFOP_CURRENT_DATABASE: svf->type = NAMEOID; break; } diff --git a/src/backend/parser/parse_target.c b/src/backend/parser/parse_target.c index c3cb035..d0c9d99 100644 --- a/src/backend/parser/parse_target.c +++ b/src/backend/parser/parse_target.c @@ -1873,6 +1873,10 @@ FigureColnameInternal(Node *node, char **name) case SVFOP_CURRENT_SCHEMA: *name = "current_schema"; return 2; + case SVFOP_CURRENT_DATABASE: + *name = "current_database"; + return 2; + } break; case T_XmlExpr: diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c index 43646d2..1adfbcc 100644 --- a/src/backend/utils/adt/ruleutils.c +++ b/src/backend/utils/adt/ruleutils.c @@ -8343,6 +8343,10 @@ get_rule_expr(Node *node, deparse_context *context, case SVFOP_CURRENT_SCHEMA: appendStringInfoString(buf, "CURRENT_SCHEMA"); break; + case SVFOP_CURRENT_DATABASE: + appendStringInfoString(buf, "CURRENT_DATABASE"); + break; + } } break; diff --git a/src/include/commands/dbcommands.h b/src/include/commands/dbcommands.h index f42c8cd..d6d9f9e 100644 --- a/src/include/commands/dbcommands.h +++ b/src/include/commands/dbcommands.h @@ -24,7 +24,8 @@ extern void dropdb(const char *dbname, bool missing_ok); extern ObjectAddress RenameDatabase(const char *oldname, const char *newname); extern Oid AlterDatabase(ParseState *pstate, AlterDatabaseStmt *stmt, bool isTopLevel); extern Oid AlterDatabaseSet(AlterDatabaseSetStmt *stmt); -extern ObjectAddress AlterDatabaseOwner(const char *dbname, Oid newOwnerId); +extern ObjectAddress AlterDatabaseOwner(const DBSpecName *dbspec, Oid newOwnerId); + extern Oid get_database_oid(const char *dbname, bool missingok); extern char *get_database_name(Oid dbid); diff --git a/src/include/nodes/nodes.h b/src/include/nodes/nodes.h index 27bd4f3..3ca8f74 100644 --- a/src/include/nodes/nodes.h +++ b/src/include/nodes/nodes.h @@ -462,6 +462,7 @@ typedef enum NodeTag T_OnConflictClause, T_CommonTableExpr, T_RoleSpec, + T_DBSpecName, T_TriggerTransition, T_PartitionElem, T_PartitionSpec, diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h index 5f2a4a7..e6379ee 100644 --- a/src/include/nodes/parsenodes.h +++ b/src/include/nodes/parsenodes.h @@ -3008,6 +3008,24 @@ typedef struct LoadStmt char *filename; /* file to load */ } LoadStmt; + +/* + * DBSpecType - The type of a database name. + */ +typedef enum DBSpecNameType +{ + DBSPEC_CSTRING, /* database name is stored as a C string */ + DBSPEC_CURRENT_DATABASE /* database name is CURRENT_DATABASE */ +} DBSpecNameType; + +typedef struct DBSpecName +{ + NodeTag type; + DBSpecNameType dbnametype; /* Type of the database */ + char *dbname; /* filled only for DBSPEC_CSTRING */ + int location; /* token location, or -1 if unknown */ +} DBSpecName; + /* ---------------------- * Createdb Statement * ---------------------- @@ -3026,14 +3044,14 @@ typedef struct CreatedbStmt typedef struct AlterDatabaseStmt { NodeTag type; - char *dbname; /* name of database to alter */ - List *options; /* List of DefElem nodes */ + Node *dbspec; /* name of database to alter, DBSpecName */ + List *options; /* List of DefElem nodes */ } AlterDatabaseStmt; typedef struct AlterDatabaseSetStmt { NodeTag type; - char *dbname; /* database name */ + Node *dbspec; /* database name, DBSpecName */ VariableSetStmt *setstmt; /* SET or RESET subcommand */ } AlterDatabaseSetStmt; diff --git a/src/include/nodes/primnodes.h b/src/include/nodes/primnodes.h index 8c536a8..7d56d4a 100644 --- a/src/include/nodes/primnodes.h +++ b/src/include/nodes/primnodes.h @@ -1095,7 +1095,8 @@ typedef enum SQLValueFunctionOp SVFOP_USER, SVFOP_SESSION_USER, SVFOP_CURRENT_CATALOG, - SVFOP_CURRENT_SCHEMA + SVFOP_CURRENT_SCHEMA, + SVFOP_CURRENT_DATABASE } SQLValueFunctionOp; typedef struct SQLValueFunction diff --git a/src/include/parser/kwlist.h b/src/include/parser/kwlist.h index f50e45e..a022826 100644 --- a/src/include/parser/kwlist.h +++ b/src/include/parser/kwlist.h @@ -104,6 +104,7 @@ PG_KEYWORD("csv", CSV, UNRESERVED_KEYWORD) PG_KEYWORD("cube", CUBE, UNRESERVED_KEYWORD) PG_KEYWORD("current", CURRENT_P, UNRESERVED_KEYWORD) PG_KEYWORD("current_catalog", CURRENT_CATALOG, RESERVED_KEYWORD) +PG_KEYWORD("current_database", CURRENT_DATABASE, RESERVED_KEYWORD) PG_KEYWORD("current_date", CURRENT_DATE, RESERVED_KEYWORD) PG_KEYWORD("current_role", CURRENT_ROLE, RESERVED_KEYWORD) PG_KEYWORD("current_schema", CURRENT_SCHEMA, TYPE_FUNC_NAME_KEYWORD) diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule index 2fd3f2b..3a0e1f9 100644 --- a/src/test/regress/parallel_schedule +++ b/src/test/regress/parallel_schedule @@ -121,3 +121,4 @@ test: event_trigger # run stats by itself because its delay may be insufficient under heavy load test: stats +test: dbname \ No newline at end of file diff --git a/src/test/regress/serial_schedule b/src/test/regress/serial_schedule index 76b0de3..0047794 100644 --- a/src/test/regress/serial_schedule +++ b/src/test/regress/serial_schedule @@ -179,3 +179,4 @@ test: with test: xml test: event_trigger test: stats +test: dbname