From 71fd49e28dd218531164d5cd9fd080323c3f1bad Mon Sep 17 00:00:00 2001
From: Bruce Momjian <bruce@momjian.us>
Date: Tue, 18 Jun 2002 17:27:58 +0000
Subject: [PATCH] Change CREATE DATABASE to use DefElem instead of constructing
 structure members in gram.y.  This is the prefered method for WITH and
 arbitrary param/value pairs.

---
 src/backend/commands/dbcommands.c | 59 ++++++++++++++++++++++++--
 src/backend/nodes/copyfuncs.c     | 10 +----
 src/backend/nodes/equalfuncs.c    | 10 +----
 src/backend/parser/gram.y         | 70 ++++++++++++++-----------------
 src/backend/tcop/utility.c        |  7 +---
 src/include/commands/dbcommands.h |  6 +--
 src/include/nodes/parsenodes.h    |  7 +---
 7 files changed, 96 insertions(+), 73 deletions(-)

diff --git a/src/backend/commands/dbcommands.c b/src/backend/commands/dbcommands.c
index 7add59e2c39..ae4e52f42a4 100644
--- a/src/backend/commands/dbcommands.c
+++ b/src/backend/commands/dbcommands.c
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/commands/dbcommands.c,v 1.92 2002/05/25 16:30:59 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/dbcommands.c,v 1.93 2002/06/18 17:27:57 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -58,9 +58,7 @@ static bool remove_dbdirs(const char *real_loc, const char *altloc);
  */
 
 void
-createdb(const char *dbname, const char *dbowner,
-		 const char *dbpath, const char *dbtemplate,
-		 int encoding)
+createdb(CreatedbStmt *stmt)
 {
 	char	   *nominal_loc;
 	char	   *alt_loc;
@@ -82,6 +80,59 @@ createdb(const char *dbname, const char *dbowner,
 	char		new_record_nulls[Natts_pg_database];
 	Oid			dboid;
 	int32		datdba;
+	List	   *option;
+	DefElem    *downer = NULL;
+	DefElem	   *dpath = NULL;
+	DefElem	   *dtemplate = NULL;
+	DefElem	   *dencoding = NULL;
+	char	   *dbname = stmt->dbname;
+	char	   *dbowner = NULL;
+	char	   *dbpath = NULL;
+	char	   *dbtemplate = NULL;
+	int		    encoding = -1;
+
+	/* Extract options from the statement node tree */
+	foreach(option, stmt->options)
+	{
+		DefElem    *defel = (DefElem *) lfirst(option);
+
+		if (strcmp(defel->defname, "owner") == 0)
+		{
+			if (downer)
+				elog(ERROR, "CREATE DATABASE: conflicting options");
+			downer = defel;
+		}
+		else if (strcmp(defel->defname, "location") == 0)
+		{
+			if (dpath)
+				elog(ERROR, "CREATE DATABASE: conflicting options");
+			dpath = defel;
+		}
+		else if (strcmp(defel->defname, "template") == 0)
+		{
+			if (dtemplate)
+				elog(ERROR, "CREATE DATABASE: conflicting options");
+			dtemplate = defel;
+		}
+		else if (strcmp(defel->defname, "encoding") == 0)
+		{
+			if (dencoding)
+				elog(ERROR, "CREATE DATABASE: conflicting options");
+			dencoding = defel;
+		}
+		else
+			elog(ERROR, "CREATE DATABASE: option \"%s\" not recognized",
+				 defel->defname);
+	}
+
+	if (downer)
+		dbowner = strVal(downer->arg);
+	if (dpath)
+		dbpath = strVal(dpath->arg);
+	if (dtemplate)
+		dbtemplate = strVal(dtemplate->arg);
+	if (dencoding)
+		encoding = intVal(dencoding->arg);
 
 	/* obtain sysid of proposed owner */
 	if (dbowner)
diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c
index 5bc16dc9b82..d2a3f40a348 100644
--- a/src/backend/nodes/copyfuncs.c
+++ b/src/backend/nodes/copyfuncs.c
@@ -15,7 +15,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.188 2002/05/22 17:20:58 petere Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.189 2002/06/18 17:27:57 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -2258,13 +2258,7 @@ _copyCreatedbStmt(CreatedbStmt *from)
 
 	if (from->dbname)
 		newnode->dbname = pstrdup(from->dbname);
-	if (from->dbowner)
-		newnode->dbowner = pstrdup(from->dbowner);
-	if (from->dbpath)
-		newnode->dbpath = pstrdup(from->dbpath);
-	if (from->dbtemplate)
-		newnode->dbtemplate = pstrdup(from->dbtemplate);
-	newnode->encoding = from->encoding;
+	Node_Copy(from, newnode, options);
 
 	return newnode;
 }
diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c
index b4f576fc881..85ff384479d 100644
--- a/src/backend/nodes/equalfuncs.c
+++ b/src/backend/nodes/equalfuncs.c
@@ -20,7 +20,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.135 2002/05/22 17:20:59 petere Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.136 2002/06/18 17:27:57 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1085,13 +1085,7 @@ _equalCreatedbStmt(CreatedbStmt *a, CreatedbStmt *b)
 {
 	if (!equalstr(a->dbname, b->dbname))
 		return false;
-	if (!equalstr(a->dbowner, b->dbowner))
-		return false;
-	if (!equalstr(a->dbpath, b->dbpath))
-		return false;
-	if (!equalstr(a->dbtemplate, b->dbtemplate))
-		return false;
-	if (a->encoding != b->encoding)
+	if (!equal(a->options, b->options))
 		return false;
 
 	return true;
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index 7106cfc1c28..8affd233ed9 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -11,7 +11,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.328 2002/06/18 00:28:11 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.329 2002/06/18 17:27:57 momjian Exp $
  *
  * HISTORY
  *	  AUTHOR			DATE			MAJOR EVENT
@@ -154,7 +154,8 @@ static void doNegateFloat(Value *v);
 %type <node>	alter_column_default
 %type <ival>	add_drop, drop_behavior, opt_drop_behavior
 
-%type <list>	createdb_opt_list, createdb_opt_item
+%type <list>	createdb_opt_list
+%type <defelt>	createdb_opt_item
 %type <boolean> opt_equal
 
 %type <ival>	opt_lock, lock_type
@@ -3351,35 +3352,8 @@ CreatedbStmt:
 			CREATE DATABASE database_name opt_with createdb_opt_list
 				{
 					CreatedbStmt *n = makeNode(CreatedbStmt);
-					List   *l;
-
 					n->dbname = $3;
-					/* set default options */
-					n->dbowner = NULL;
-					n->dbpath = NULL;
-					n->dbtemplate = NULL;
-					n->encoding = -1;
-					/* process additional options */
-					foreach(l, $5)
-					{
-						List   *optitem = (List *) lfirst(l);
-
-						switch (lfirsti(optitem))
-						{
-							case 1:
-								n->dbpath = (char *) lsecond(optitem);
-								break;
-							case 2:
-								n->dbtemplate = (char *) lsecond(optitem);
-								break;
-							case 3:
-								n->encoding = lfirsti(lnext(optitem));
-								break;
-							case 4:
-								n->dbowner = (char *) lsecond(optitem);
-								break;
-						}
-					}
+					n->options = $5;
 					$$ = (Node *)n;
 				}
 		;
@@ -3396,19 +3370,27 @@ createdb_opt_list:
 createdb_opt_item:
 			LOCATION opt_equal Sconst
 				{
-					$$ = lconsi(1, makeList1($3));
+					$$ = makeNode(DefElem);
+					$$->defname = "location";
+					$$->arg = (Node *)makeString($3);
 				}
 			| LOCATION opt_equal DEFAULT
 				{
-					$$ = lconsi(1, makeList1(NULL));
+					$$ = makeNode(DefElem);
+					$$->defname = "location";
+					$$->arg = NULL;
 				}
 			| TEMPLATE opt_equal name
 				{
-					$$ = lconsi(2, makeList1($3));
+					$$ = makeNode(DefElem);
+					$$->defname = "template";
+					$$->arg = (Node *)makeString($3);
 				}
 			| TEMPLATE opt_equal DEFAULT
 				{
-					$$ = lconsi(2, makeList1(NULL));
+					$$ = makeNode(DefElem);
+					$$->defname = "template";
+					$$->arg = NULL;
 				}
 			| ENCODING opt_equal Sconst
 				{
@@ -3422,7 +3404,9 @@ createdb_opt_item:
 						elog(ERROR, "Multi-byte support is not enabled");
 					encoding = GetStandardEncoding();
 #endif
-					$$ = lconsi(3, makeListi1(encoding));
+					$$ = makeNode(DefElem);
+					$$->defname = "encoding";
+					$$->arg = (Node *)makeInteger(encoding);
 				}
 			| ENCODING opt_equal Iconst
 				{
@@ -3433,19 +3417,27 @@ createdb_opt_item:
 					if ($3 != GetStandardEncoding())
 						elog(ERROR, "Multi-byte support is not enabled");
 #endif
-					$$ = lconsi(3, makeListi1($3));
+					$$ = makeNode(DefElem);
+					$$->defname = "encoding";
+					$$->arg = (Node *)makeInteger($3);
 				}
 			| ENCODING opt_equal DEFAULT
 				{
-					$$ = lconsi(3, makeListi1(-1));
+					$$ = makeNode(DefElem);
+					$$->defname = "encoding";
+					$$->arg = (Node *)makeInteger(-1);
 				}
 			| OWNER opt_equal name
 				{
-					$$ = lconsi(4, makeList1($3));
+					$$ = makeNode(DefElem);
+					$$->defname = "owner";
+					$$->arg = (Node *)makeString($3);
 				}
 			| OWNER opt_equal DEFAULT
 				{
-					$$ = lconsi(4, makeList1(NULL));
+					$$ = makeNode(DefElem);
+					$$->defname = "owner";
+					$$->arg = NULL;
 				}
 		;
 
diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c
index 36a3cb06dd4..4e23a6d9190 100644
--- a/src/backend/tcop/utility.c
+++ b/src/backend/tcop/utility.c
@@ -10,7 +10,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.156 2002/05/21 22:18:08 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.157 2002/06/18 17:27:58 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -630,10 +630,7 @@ ProcessUtility(Node *parsetree,
 		case T_CreatedbStmt:
 			{
 				CreatedbStmt *stmt = (CreatedbStmt *) parsetree;
-
-				createdb(stmt->dbname, stmt->dbowner,
-						 stmt->dbpath, stmt->dbtemplate,
-						 stmt->encoding);
+				createdb(stmt);
 			}
 			break;
 
diff --git a/src/include/commands/dbcommands.h b/src/include/commands/dbcommands.h
index 32c823e152c..1a99da6d4da 100644
--- a/src/include/commands/dbcommands.h
+++ b/src/include/commands/dbcommands.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: dbcommands.h,v 1.21 2002/03/01 22:45:17 petere Exp $
+ * $Id: dbcommands.h,v 1.22 2002/06/18 17:27:58 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -16,9 +16,7 @@
 
 #include <nodes/parsenodes.h>
 
-extern void createdb(const char *dbname, const char *dbowner,
-					 const char *dbpath, const char *dbtemplate,
-					 int encoding);
+extern void createdb(CreatedbStmt *stmt);
 extern void dropdb(const char *dbname);
 extern void AlterDatabaseSet(AlterDatabaseSetStmt *stmt);
 
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index f7ea60ac802..01b90ce0285 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: parsenodes.h,v 1.179 2002/05/22 17:21:01 petere Exp $
+ * $Id: parsenodes.h,v 1.180 2002/06/18 17:27:58 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1350,10 +1350,7 @@ typedef struct CreatedbStmt
 {
 	NodeTag		type;
 	char	   *dbname;			/* name of database to create */
-	char	   *dbowner;		/* name of owner (NULL = default) */
-	char	   *dbpath;			/* location of database (NULL = default) */
-	char	   *dbtemplate;		/* template to use (NULL = default) */
-	int			encoding;		/* MULTIBYTE encoding (-1 = use default) */
+	List	   *options;		/* List of DefElem nodes */
 } CreatedbStmt;
 
 /* ----------------------
-- 
GitLab