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 <str>		opt_existing_window_name
 %type <boolean> opt_if_not_exists
+%type <node>	db_spec_name
 %type <ival>	generated_when override_kind
 %type <partspec>	PartitionSpec OptPartitionSpec
 %type <str>			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/expected/dbname.out b/src/test/regress/expected/dbname.out
new file mode 100644
index 0000000..0e7a1e9
--- /dev/null
+++ b/src/test/regress/expected/dbname.out
@@ -0,0 +1,119 @@
+CREATE ROLE dbuser1 with LOGIN;
+CREATE ROLE dbuser2 with SUPERUSER LOGIN;
+CREATE ROLE dbuser3 with SUPERUSER LOGIN;
+CREATE DATABASE mydb1 with owner=dbuser1;
+CREATE DATABASE "current_database" with owner=dbuser1;
+CREATE DATABASE current_database with owner=dbuser1;
+ERROR:  CURRENT_DATABASE cannot be used as a database name here
+LINE 1: CREATE DATABASE current_database with owner=dbuser1;
+                        ^
+SELECT d.datname as "Name",
+       pg_catalog.shobj_description(d.oid, 'pg_database') as "Description"
+FROM pg_catalog.pg_database d
+  	JOIN pg_catalog.pg_tablespace t on d.dattablespace = t.oid
+ORDER BY 1;
+       Name       |                Description                 
+------------------+--------------------------------------------
+ current_database | 
+ mydb1            | 
+ postgres         | default administrative connection database
+ regression       | 
+ template0        | unmodifiable empty database
+ template1        | default template for new databases
+(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';
+SELECT d.datname as "Name",
+       pg_catalog.shobj_description(d.oid, 'pg_database') as "Description"
+FROM pg_catalog.pg_database d
+  	JOIN pg_catalog.pg_tablespace t on d.dattablespace = t.oid
+ORDER BY 1;
+       Name       |                Description                 
+------------------+--------------------------------------------
+ current_database | db2
+ mydb1            | db1
+ postgres         | default administrative connection database
+ regression       | 
+ template0        | unmodifiable empty database
+ template1        | default template for new databases
+(6 rows)
+
+-- test alter owner
+ALTER DATABASE current_database OWNER to dbuser2; 
+ALTER DATABASE "current_database" OWNER to dbuser2;
+SELECT d.datname as "Name",
+       pg_catalog.pg_get_userbyid(d.datdba) as "Owner",
+       pg_catalog.shobj_description(d.oid, 'pg_database') as "Description"
+FROM pg_catalog.pg_database d
+  	JOIN pg_catalog.pg_tablespace t on d.dattablespace = t.oid
+WHERE d.datname='current_database' or d.datname='mydb1'
+ORDER BY 1;
+       Name       |  Owner  | Description 
+------------------+---------+-------------
+ current_database | dbuser2 | db2
+ mydb1            | dbuser2 | db1
+(2 rows)
+
+-- 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 mydb2;
+ERROR:  CURRENT_DATABASE cannot be used as a database name here
+LINE 1: ALTER DATABASE current_database rename to mydb2;
+                       ^
+ALTER DATABASE "current_database" rename to mydb2;
+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;
+                                       ^
+SELECT d.datname as "Name",
+       pg_catalog.shobj_description(d.oid, 'pg_database') as "Description"
+FROM pg_catalog.pg_database d
+  	JOIN pg_catalog.pg_tablespace t on d.dattablespace = t.oid
+ORDER BY 1;
+    Name    |                Description                 
+------------+--------------------------------------------
+ mydb1      | db1
+ mydb2      | db2
+ postgres   | default administrative connection database
+ regression | 
+ template0  | unmodifiable empty database
+ template1  | default template for new databases
+(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 IF EXISTS "current_database";
+NOTICE:  database "current_database" does not exist, skipping
+DROP DATABASE IF EXISTS mydb1;
+DROP DATABASE IF EXISTS mydb2;
+DROP ROLE dbuser1;
+DROP ROLE dbuser2;
+DROP ROLE dbuser3;
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
diff --git a/src/test/regress/sql/dbname.sql b/src/test/regress/sql/dbname.sql
new file mode 100644
index 0000000..2ce50e6
--- /dev/null
+++ b/src/test/regress/sql/dbname.sql
@@ -0,0 +1,72 @@
+CREATE ROLE dbuser1 with LOGIN;
+CREATE ROLE dbuser2 with SUPERUSER LOGIN;
+CREATE ROLE dbuser3 with SUPERUSER LOGIN;
+
+CREATE DATABASE mydb1 with owner=dbuser1;
+CREATE DATABASE "current_database" with owner=dbuser1;
+CREATE DATABASE current_database with owner=dbuser1;
+
+SELECT d.datname as "Name",
+       pg_catalog.shobj_description(d.oid, 'pg_database') as "Description"
+FROM pg_catalog.pg_database d
+  	JOIN pg_catalog.pg_tablespace t on d.dattablespace = t.oid
+ORDER BY 1;
+
+
+\c mydb1;
+SELECT CURRENT_DATABASE;
+
+
+COMMENT ON DATABASE current_database IS 'db1';
+COMMENT ON DATABASE "current_database" IS 'db2';
+
+SELECT d.datname as "Name",
+       pg_catalog.shobj_description(d.oid, 'pg_database') as "Description"
+FROM pg_catalog.pg_database d
+  	JOIN pg_catalog.pg_tablespace t on d.dattablespace = t.oid
+ORDER BY 1;
+
+-- test alter owner
+ALTER DATABASE current_database OWNER to dbuser2; 
+ALTER DATABASE "current_database" OWNER to dbuser2;
+
+SELECT d.datname as "Name",
+       pg_catalog.pg_get_userbyid(d.datdba) as "Owner",
+       pg_catalog.shobj_description(d.oid, 'pg_database') as "Description"
+FROM pg_catalog.pg_database d
+  	JOIN pg_catalog.pg_tablespace t on d.dattablespace = t.oid
+WHERE d.datname='current_database' or d.datname='mydb1'
+ORDER BY 1;
+
+-- 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 mydb2;
+ALTER DATABASE "current_database" rename to mydb2;
+ALTER DATABASE mydb2 rename to current_database;
+
+SELECT d.datname as "Name",
+       pg_catalog.shobj_description(d.oid, 'pg_database') as "Description"
+FROM pg_catalog.pg_database d
+  	JOIN pg_catalog.pg_tablespace t on d.dattablespace = t.oid
+ORDER BY 1;
+
+-- 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 IF EXISTS "current_database";
+DROP DATABASE IF EXISTS mydb1;
+DROP DATABASE IF EXISTS mydb2;
+DROP ROLE dbuser1;
+DROP ROLE dbuser2;
+DROP ROLE dbuser3;
