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/[email protected]
[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 ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers