Index: common.c
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/bin/psql/common.c,v
retrieving revision 1.90
diff -u -r1.90 common.c
--- common.c	29 Aug 2004 05:06:54 -0000	1.90
+++ common.c	20 Sep 2004 07:52:39 -0000
@@ -946,45 +946,61 @@
 	return OK;
 }
 
+
 /*
- * check whether a query string begins with BEGIN/COMMIT/ROLLBACK/START XACT
+ * Advance the given char* over white space and comments.
+ * This is used for is_transact_command. 
  */
-static bool
-is_transact_command(const char *query)
+static char *
+command_remove_noise(const char *query)
 {
-	int			wordlen;
+	unsigned int	cnestlevel = 0;		/* comment nest level */
 
-	/*
-	 * First we must advance over any whitespace and comments.
-	 */
 	while (*query)
 	{
 		if (isspace((unsigned char) *query))
 			query++;
-		else if (query[0] == '-' && query[1] == '-')
+		else if (query[0] == '/' && query[1] == '*')
 		{
 			query += 2;
-			while (*query && *query != '\n')
-				query++;
+			cnestlevel++;
 		}
-		else if (query[0] == '/' && query[1] == '*')
+		else if (cnestlevel > 0 && query[0] == '*' && query[1] == '/')
 		{
 			query += 2;
-			while (*query)
-			{
-				if (query[0] == '*' && query[1] == '/')
-				{
-					query += 2;
-					break;
-				}
-				else
-					query++;
-			}
+			cnestlevel--;
 		}
+		else if (cnestlevel == 0 && query[0] == '-' && query[1] == '-')
+		{
+			query += 2;
+			while (*query && *query != '\n')
+				query++;
+		}
+		else if (cnestlevel > 0)
+			query++;
 		else
 			break;				/* found first token */
 	}
 
+	return (char *) query;
+}
+
+
+/*
+ * check whether a command is either a transaction modifying statement
+ * (BEGIN,COMMIT,ROLLBACK,ABORT,END,START) or a statement that must
+ * not be executed within a transaction
+ */
+static bool
+is_transact_command(const char *query)
+{
+	int			wordlen;
+
+	/*
+	 * First we must advance over any whitespace and comments.
+	 */
+	query = command_remove_noise(query);
+
 	/*
 	 * Check word length ("beginx" is not "begin").
 	 */
@@ -992,6 +1008,9 @@
 	while (isalpha((unsigned char) query[wordlen]))
 		wordlen++;
 
+	/*
+	 * Trx modifying commands.
+	 */
 	if (wordlen == 5 && pg_strncasecmp(query, "begin", 5) == 0)
 		return true;
 	if (wordlen == 6 && pg_strncasecmp(query, "commit", 6) == 0)
@@ -1005,6 +1024,35 @@
 	if (wordlen == 5 && pg_strncasecmp(query, "start", 5) == 0)
 		return true;
 
+	/*
+	 * Commands not allowed within transactions.
+	 */
+	if (wordlen == 6 && pg_strncasecmp(query, "vacuum", 6) == 0)
+		return true;
+	if (wordlen == 7 && pg_strncasecmp(query, "cluster", 7) == 0)
+		return true;
+
+	/*
+	 * Commands that are only disallowed in some variations.
+	 */
+	if ((wordlen == 6 && pg_strncasecmp(query, "create", 6) == 0) ||
+		(wordlen == 4 && pg_strncasecmp(query, "drop", 4) == 0) ||
+		(wordlen == 7 && pg_strncasecmp(query, "reindex", 7) == 0))
+	{
+		query += wordlen;
+
+		query = command_remove_noise(query);
+
+		wordlen = 0;
+		while (isalpha((unsigned char) query[wordlen]))
+			wordlen++;
+
+		if (wordlen == 8 && pg_strncasecmp(query, "database", 8) == 0)
+			return true;
+		if (wordlen == 10 && pg_strncasecmp(query, "tablespace", 10) == 0)
+			return true;
+	}
+
 	return false;
 }
 
