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; }