Hi all, The attached patch is to support the feature "COMMENT ON DATABASE CURRENT_DATABASE". The solution is based on the previous discussion in [2] .
Can't find the previous link in my email history list so create a new topic here. By using the patch the CURRENT_DATABASE as a keyword can be used in the following SQL commands: 1. COMMENT ON DATABASE CURRENT_DATABASE is ... 2. ALTER DATABASE CURRENT_DATABASE OWNER to ... 3. ALTER DATABASE CURRENT_DATABASE SET parameter ... 4. ALTER DATABASE CURRENT_DATABASE RESET parameter ... 5. SELECT CURRENT_DATABASE [1] https://www.postgresql.org/message-id/20150317171836.gc10...@momjian.us [2] https://www.postgresql.org/message-id/flat/CAB7nPqSTXUWAx-C5Pgw%2Bdu5jxu4QZ%3DaxQq165McmyT3UggWmuQ%40mail.gmail.com#CAB7nPqSTXUWAx-C5Pgw+du5jxu4QZ=axqq165mcmyt3uggw...@mail.gmail.com -- Regards, Jing Wang Fujitsu Australia
diff --git a/src/backend/catalog/objectaddress.c b/src/backend/catalog/objectaddress.c index e60e8e8..8895980 100644 --- a/src/backend/catalog/objectaddress.c +++ b/src/backend/catalog/objectaddress.c @@ -665,7 +665,8 @@ const ObjectAddress InvalidObjectAddress = InvalidOid, 0 }; - +static ObjectAddress get_object_address_database(ObjectType objtype, + List * objname, bool missing_ok); static ObjectAddress get_object_address_unqualified(ObjectType objtype, List *qualname, bool missing_ok); static ObjectAddress get_relation_by_qualified_name(ObjectType objtype, @@ -803,6 +804,8 @@ get_object_address(ObjectType objtype, List *objname, List *objargs, } break; case OBJECT_DATABASE: + address = get_object_address_database(objtype, objname, missing_ok); + break; case OBJECT_EXTENSION: case OBJECT_TABLESPACE: case OBJECT_ROLE: @@ -1042,6 +1045,44 @@ get_object_address_rv(ObjectType objtype, RangeVar *rel, List *objname, /* * Find an ObjectAddress for a type of object that is identified by an + * database name + */ +static ObjectAddress +get_object_address_database(ObjectType objtype, List * objname, bool missing_ok) +{ + const char *name; + char *dbname; + DBSpecName *dbspecname; + ObjectAddress address; + + if (list_length(objname) != 1) + { + const char *msg; + + msg = gettext_noop("database name cannot be qualified"); + + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("%s", _(msg)))); + } + + /* Format is valid, extract the actual name. */ + dbspecname = (DBSpecName*)linitial(objname); + + if (dbspecname->dbnametype == DBSPEC_CURRENT_DATABASE ) + dbname = get_database_name(MyDatabaseId); + else + dbname = dbspecname->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 @@ -2086,8 +2127,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, - NameListToString(objname)); + { + char *dbname; + DBSpecName *dbspecname; + + /* Format is valid, extract the actual name. */ + dbspecname = (DBSpecName*)linitial(objname); + + 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 1301bcb..78f6dfb 100644 --- a/src/backend/commands/alter.c +++ b/src/backend/commands/alter.c @@ -749,7 +749,7 @@ ExecAlterOwnerStmt(AlterOwnerStmt *stmt) switch (stmt->objectType) { case OBJECT_DATABASE: - return AlterDatabaseOwner(strVal(linitial(stmt->object)), newowner); + return AlterDatabaseOwner(linitial(stmt->object), newowner); case OBJECT_SCHEMA: return AlterSchemaOwner(strVal(linitial(stmt->object)), newowner); diff --git a/src/backend/commands/comment.c b/src/backend/commands/comment.c index a0d3f8d..f2f27d7 100644 --- a/src/backend/commands/comment.c +++ b/src/backend/commands/comment.c @@ -53,13 +53,21 @@ CommentObject(CommentStmt *stmt) */ if (stmt->objtype == OBJECT_DATABASE && list_length(stmt->objname) == 1) { - char *database = strVal(linitial(stmt->objname)); + char *dbname = NULL; + DBSpecName *dbspecname = NULL; - if (!OidIsValid(get_database_oid(database, true))) + dbspecname = (DBSpecName*)linitial(stmt->objname); + + 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 f47a13d..a5c71b2 100644 --- a/src/backend/commands/dbcommands.c +++ b/src/backend/commands/dbcommands.c @@ -1383,6 +1383,15 @@ AlterDatabase(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) @@ -1441,7 +1450,7 @@ AlterDatabase(AlterDatabaseStmt *stmt, bool isTopLevel) dtablespace->defname))); /* 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; } @@ -1467,20 +1476,20 @@ AlterDatabase(AlterDatabaseStmt *stmt, bool isTopLevel) ScanKeyInit(&scankey, Anum_pg_database_datname, BTEqualStrategyNumber, F_NAMEEQ, - NameGetDatum(stmt->dbname)); + NameGetDatum(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 @@ -1541,7 +1550,18 @@ AlterDatabase(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 @@ -1551,7 +1571,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); @@ -1565,7 +1585,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; @@ -1574,6 +1594,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/parser/gram.y b/src/backend/parser/gram.y index 080d444..784eb7e 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -177,7 +177,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 @@ -539,6 +539,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query); opt_frame_clause frame_extent frame_bound %type <str> opt_existing_window_name %type <boolean> opt_if_not_exists +%type <node> db_spec_name /* * Non-keyword token types. These are hard-wired into the "flex" lexer. @@ -575,7 +576,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 @@ -5737,6 +5738,15 @@ CommentStmt: n->comment = $6; $$ = (Node *) n; } + | COMMENT ON DATABASE db_spec_name IS comment_text + { + CommentStmt *n = makeNode(CommentStmt); + n->objtype = OBJECT_DATABASE; + n->objname = list_make1($4); + n->objargs = NIL; + n->comment = $6; + $$ = (Node *) n; + } | COMMENT ON TYPE_P Typename IS comment_text { CommentStmt *n = makeNode(CommentStmt); @@ -5900,7 +5910,6 @@ CommentStmt: comment_type: ACCESS METHOD { $$ = OBJECT_ACCESS_METHOD; } | COLUMN { $$ = OBJECT_COLUMN; } - | DATABASE { $$ = OBJECT_DATABASE; } | SCHEMA { $$ = OBJECT_SCHEMA; } | INDEX { $$ = OBJECT_INDEX; } | SEQUENCE { $$ = OBJECT_SEQUENCE; } @@ -8372,11 +8381,11 @@ AlterOwnerStmt: ALTER AGGREGATE func_name aggr_args 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 = list_make1(makeString($3)); + n->object = list_make1($3); n->newowner = $6; $$ = (Node *)n; } @@ -8975,24 +8984,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))); $$ = (Node *)n; @@ -9000,10 +9009,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; } @@ -12465,6 +12474,10 @@ func_expr_common_subexpr: { $$ = (Node *) makeFuncCall(SystemFuncName("session_user"), NIL, @1); } + | CURRENT_DATABASE + { + $$ = (Node *) makeFuncCall(SystemFuncName("current_database"), NIL, @1); + } | USER { $$ = (Node *) makeFuncCall(SystemFuncName("current_user"), NIL, @1); @@ -13465,8 +13478,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 = (Node *) makeDBSpecName(DBSPEC_CSTRING, @1); + n->dbname = pstrdup($1); + $$ = n; + } + | CURRENT_DATABASE + { + $$ = (Node *) makeDBSpecName(DBSPEC_CURRENT_DATABASE, @1); + } + ; + access_method: ColId { $$ = $1; }; @@ -13491,6 +13527,8 @@ func_name: type_function_name $$ = check_func_name(lcons(makeString($1), $2), yyscanner); } + | CURRENT_DATABASE + { $$ = list_make1(makeString("current_database")); } ; @@ -14129,6 +14167,7 @@ reserved_keyword: | CONSTRAINT | CREATE | CURRENT_CATALOG + | CURRENT_DATABASE | CURRENT_DATE | CURRENT_ROLE | CURRENT_TIME @@ -15001,6 +15040,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/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c index ea64c77..b79d3e1 100644 --- a/src/bin/pg_dump/pg_dump.c +++ b/src/bin/pg_dump/pg_dump.c @@ -2717,10 +2717,20 @@ dumpDatabase(Archive *fout) resetPQExpBuffer(dbQry); /* - * Generates warning when loaded into a differently-named - * database. - */ - appendPQExpBuffer(dbQry, "COMMENT ON DATABASE %s IS ", fmtId(datname)); + * Use the new form (COMMENT ON CURRENT DATABASE) for new version + */ + if (fout->remoteVersion >= 100000) + { + appendPQExpBuffer(dbQry, "COMMENT ON DATABASE CURRENT_DATABASE IS "); + } + else + { + /* + * Generates warning when loaded into a differently-named + * database. + */ + appendPQExpBuffer(dbQry, "COMMENT ON DATABASE %s IS ", fmtId(datname)); + } appendStringLiteralAH(dbQry, comment, fout); appendPQExpBufferStr(dbQry, ";\n"); diff --git a/src/include/commands/dbcommands.h b/src/include/commands/dbcommands.h index b6436f1..84b6743 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(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 d3fdf55..53a638e 100644 --- a/src/include/nodes/nodes.h +++ b/src/include/nodes/nodes.h @@ -452,6 +452,7 @@ typedef enum NodeTag T_OnConflictClause, T_CommonTableExpr, T_RoleSpec, + T_DBSpecName, /* * TAGS FOR REPLICATION GRAMMAR PARSE NODES (replnodes.h) diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h index 1481fff..06c9804 100644 --- a/src/include/nodes/parsenodes.h +++ b/src/include/nodes/parsenodes.h @@ -2745,6 +2745,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 * ---------------------- @@ -2763,14 +2781,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/parser/kwlist.h b/src/include/parser/kwlist.h index 17ffef5..484539e 100644 --- a/src/include/parser/kwlist.h +++ b/src/include/parser/kwlist.h @@ -102,6 +102,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/expected/dbname.out b/src/test/regress/expected/dbname.out new file mode 100644 index 0000000..954b3f9 --- /dev/null +++ b/src/test/regress/expected/dbname.out @@ -0,0 +1,128 @@ +CREATE ROLE dbuser1 with LOGIN; +CREATE ROLE dbuser2 with SUPERUSER LOGIN; +CREATE ROLE dbuser3 with SUPERUSER LOGIN; +CREATE DATABASE mydb1; +CREATE DATABASE "current_database"; +CREATE DATABASE current_database; +ERROR: CURRENT_DATABASE cannot be used as a database name here +LINE 1: CREATE DATABASE current_database; + ^ +\l+ + List of databases + Name | Owner | Encoding | Collate | Ctype | Access privileges | Size | Tablespace | Description +------------------+-------+----------+-------------+-------------+-------------------+---------+------------+-------------------------------------------- + current_database | wangj | UTF8 | en_US.UTF-8 | en_US.UTF-8 | | 7233 kB | pg_default | + mydb1 | wangj | UTF8 | en_US.UTF-8 | en_US.UTF-8 | | 7233 kB | pg_default | + postgres | wangj | UTF8 | en_US.UTF-8 | en_US.UTF-8 | | 7343 kB | pg_default | default administrative connection database + regression | wangj | UTF8 | en_US.UTF-8 | en_US.UTF-8 | =Tc/wangj +| 63 MB | pg_default | + | | | | | wangj=CTc/wangj | | | + template0 | wangj | UTF8 | en_US.UTF-8 | en_US.UTF-8 | =c/wangj +| 7233 kB | pg_default | unmodifiable empty database + | | | | | wangj=CTc/wangj | | | + template1 | wangj | UTF8 | en_US.UTF-8 | en_US.UTF-8 | =c/wangj +| 7233 kB | pg_default | default template for new databases + | | | | | wangj=CTc/wangj | | | +(6 rows) + +\c mydb1; +SELECT CURRENT_DATABASE; + current_database +------------------ + mydb1 +(1 row) + +COMMENT ON DATABASE current_database IS 'db1'; +COMMENT ON DATABASE "current_database" IS 'db2'; +\l+ + List of databases + Name | Owner | Encoding | Collate | Ctype | Access privileges | Size | Tablespace | Description +------------------+-------+----------+-------------+-------------+-------------------+---------+------------+-------------------------------------------- + current_database | wangj | UTF8 | en_US.UTF-8 | en_US.UTF-8 | | 7233 kB | pg_default | db2 + mydb1 | wangj | UTF8 | en_US.UTF-8 | en_US.UTF-8 | | 7343 kB | pg_default | db1 + postgres | wangj | UTF8 | en_US.UTF-8 | en_US.UTF-8 | | 7343 kB | pg_default | default administrative connection database + regression | wangj | UTF8 | en_US.UTF-8 | en_US.UTF-8 | =Tc/wangj +| 63 MB | pg_default | + | | | | | wangj=CTc/wangj | | | + template0 | wangj | UTF8 | en_US.UTF-8 | en_US.UTF-8 | =c/wangj +| 7233 kB | pg_default | unmodifiable empty database + | | | | | wangj=CTc/wangj | | | + template1 | wangj | UTF8 | en_US.UTF-8 | en_US.UTF-8 | =c/wangj +| 7233 kB | pg_default | default template for new databases + | | | | | wangj=CTc/wangj | | | +(6 rows) + +-- test alter owner +ALTER DATABASE current_database OWNER to dbuser2; +ALTER DATABASE "current_database" OWNER to dbuser2; +-- test alter database tablespace +ALTER DATABASE current_database SET TABLESPACE pg_default; +ERROR: cannot change the tablespace of the currently open database +ALTER DATABASE "current_database" SET TABLESPACE pg_default; +-- test alter database rename +ALTER DATABASE current_database RENAME TO newdb1; +ERROR: CURRENT_DATABASE cannot be used as a database name here +LINE 1: ALTER DATABASE current_database RENAME TO newdb1; + ^ +ALTER DATABASE "current_database" RENAME TO mydb2; +\l+ + List of databases + Name | Owner | Encoding | Collate | Ctype | Access privileges | Size | Tablespace | Description +------------+---------+----------+-------------+-------------+-------------------+---------+------------+-------------------------------------------- + mydb1 | dbuser2 | UTF8 | en_US.UTF-8 | en_US.UTF-8 | | 7343 kB | pg_default | db1 + mydb2 | dbuser2 | UTF8 | en_US.UTF-8 | en_US.UTF-8 | | 7233 kB | pg_default | db2 + postgres | wangj | UTF8 | en_US.UTF-8 | en_US.UTF-8 | | 7343 kB | pg_default | default administrative connection database + regression | wangj | UTF8 | en_US.UTF-8 | en_US.UTF-8 | =Tc/wangj +| 63 MB | pg_default | + | | | | | wangj=CTc/wangj | | | + template0 | wangj | UTF8 | en_US.UTF-8 | en_US.UTF-8 | =c/wangj +| 7233 kB | pg_default | unmodifiable empty database + | | | | | wangj=CTc/wangj | | | + template1 | wangj | UTF8 | en_US.UTF-8 | en_US.UTF-8 | =c/wangj +| 7233 kB | pg_default | default template for new databases + | | | | | wangj=CTc/wangj | | | +(6 rows) + +ALTER DATABASE mydb2 rename to current_database; +ERROR: CURRENT_DATABASE cannot be used as a database name here +LINE 1: ALTER DATABASE mydb2 rename to current_database; + ^ +ALTER DATABASE mydb2 rename to "current_database"; +\l+ + List of databases + Name | Owner | Encoding | Collate | Ctype | Access privileges | Size | Tablespace | Description +------------------+---------+----------+-------------+-------------+-------------------+---------+------------+-------------------------------------------- + current_database | dbuser2 | UTF8 | en_US.UTF-8 | en_US.UTF-8 | | 7233 kB | pg_default | db2 + mydb1 | dbuser2 | UTF8 | en_US.UTF-8 | en_US.UTF-8 | | 7343 kB | pg_default | db1 + postgres | wangj | UTF8 | en_US.UTF-8 | en_US.UTF-8 | | 7343 kB | pg_default | default administrative connection database + regression | wangj | UTF8 | en_US.UTF-8 | en_US.UTF-8 | =Tc/wangj +| 63 MB | pg_default | + | | | | | wangj=CTc/wangj | | | + template0 | wangj | UTF8 | en_US.UTF-8 | en_US.UTF-8 | =c/wangj +| 7233 kB | pg_default | unmodifiable empty database + | | | | | wangj=CTc/wangj | | | + template1 | wangj | UTF8 | en_US.UTF-8 | en_US.UTF-8 | =c/wangj +| 7233 kB | pg_default | default template for new databases + | | | | | wangj=CTc/wangj | | | +(6 rows) + +-- test alter database set parameter +ALTER DATABASE current_database SET parallel_tuple_cost=0.3; +\c mydb1 +show parallel_tuple_cost; + parallel_tuple_cost +--------------------- + 0.3 +(1 row) + +ALTER DATABASE current_database RESET parallel_tuple_cost; +\c mydb1 +show parallel_tuple_cost; + parallel_tuple_cost +--------------------- + 0.1 +(1 row) + +-- clean up +\c postgres +DROP DATABASE "current_database"; +DROP DATABASE current_database; +ERROR: CURRENT_DATABASE cannot be used as a database name here +LINE 1: DROP DATABASE current_database; + ^ +DROP ROLE dbuser1; +DROP ROLE dbuser2; +ERROR: role "dbuser2" cannot be dropped because some objects depend on it +DETAIL: owner of database mydb1 +DROP ROLE dbuser3; +DROP DATABASE mydb1; +DROP DATABASE mydb2; +ERROR: database "mydb2" does not exist diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule index 3815182..a99d2ff 100644 --- a/src/test/regress/parallel_schedule +++ b/src/test/regress/parallel_schedule @@ -110,3 +110,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 8958d8c..0363c44 100644 --- a/src/test/regress/serial_schedule +++ b/src/test/regress/serial_schedule @@ -168,3 +168,4 @@ test: with test: xml test: event_trigger test: stats +test: dbname diff --git a/src/test/regress/sql/dbname.sql b/src/test/regress/sql/dbname.sql new file mode 100644 index 0000000..ef9d93d --- /dev/null +++ b/src/test/regress/sql/dbname.sql @@ -0,0 +1,57 @@ +CREATE ROLE dbuser1 with LOGIN; +CREATE ROLE dbuser2 with SUPERUSER LOGIN; +CREATE ROLE dbuser3 with SUPERUSER LOGIN; + +CREATE DATABASE mydb1; +CREATE DATABASE "current_database"; +CREATE DATABASE current_database; + +\l+ + +\c mydb1; +SELECT CURRENT_DATABASE; + + +COMMENT ON DATABASE current_database IS 'db1'; +COMMENT ON DATABASE "current_database" IS 'db2'; + +\l+ + +-- test alter owner +ALTER DATABASE current_database OWNER to dbuser2; +ALTER DATABASE "current_database" OWNER to dbuser2; + + + +-- test alter database tablespace +ALTER DATABASE current_database SET TABLESPACE pg_default; +ALTER DATABASE "current_database" SET TABLESPACE pg_default; + +-- test alter database rename +ALTER DATABASE current_database RENAME TO newdb1; +ALTER DATABASE "current_database" RENAME TO mydb2; +\l+ + +ALTER DATABASE mydb2 rename to current_database; +ALTER DATABASE mydb2 rename to "current_database"; +\l+ + +-- test alter database set parameter +ALTER DATABASE current_database SET parallel_tuple_cost=0.3; +\c mydb1 +show parallel_tuple_cost; +ALTER DATABASE current_database RESET parallel_tuple_cost; +\c mydb1 +show parallel_tuple_cost; + +-- clean up +\c postgres + +DROP DATABASE "current_database"; +DROP DATABASE current_database; + +DROP ROLE dbuser1; +DROP ROLE dbuser2; +DROP ROLE dbuser3; +DROP DATABASE mydb1; +DROP DATABASE mydb2;
-- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers