Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit5b564e5

Browse files
committed
Fix some shortcomings in psql's autocommit-off mode concerning detection
of commands for which a transaction block should not be forced. RecognizeVACUUM and other PreventTransactionChain commands; handle nested /* .. */comments correctly; handle multibyte encodings correctly.Michael Paesold with some kibitzing from Tom Lane.
1 parent9332d0b commit5b564e5

File tree

2 files changed

+110
-27
lines changed

2 files changed

+110
-27
lines changed

‎doc/src/sgml/ref/psql-ref.sgml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<!--
2-
$PostgreSQL: pgsql/doc/src/sgml/ref/psql-ref.sgml,v 1.121 2004/08/24 00:06:51 neilc Exp $
2+
$PostgreSQL: pgsql/doc/src/sgml/ref/psql-ref.sgml,v 1.122 2004/09/20 18:51:17 tgl Exp $
33
PostgreSQL documentation
44
-->
55

@@ -1875,7 +1875,8 @@ bar
18751875
mode works by issuing an implicit <command>BEGIN</> for you, just
18761876
before any command that is not already in a transaction block and
18771877
is not itself a <command>BEGIN</> or other transaction-control
1878-
command.
1878+
command, nor a command that cannot be executed inside a transaction
1879+
block (such as <command>VACUUM</>).
18791880
</para>
18801881

18811882
<note>

‎src/bin/psql/common.c

Lines changed: 107 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
*
44
* Copyright (c) 2000-2004, PostgreSQL Global Development Group
55
*
6-
* $PostgreSQL: pgsql/src/bin/psql/common.c,v 1.90 2004/08/29 05:06:54 momjian Exp $
6+
* $PostgreSQL: pgsql/src/bin/psql/common.c,v 1.91 2004/09/20 18:51:19 tgl Exp $
77
*/
88
#include"postgres_fe.h"
99
#include"common.h"
@@ -62,7 +62,7 @@ typedef struct _timeb TimevalStruct;
6262
externboolprompt_state;
6363

6464

65-
staticboolis_transact_command(constchar*query);
65+
staticboolcommand_no_begin(constchar*query);
6666

6767

6868
/*
@@ -895,7 +895,7 @@ SendQuery(const char *query)
895895

896896
if (PQtransactionStatus(pset.db)==PQTRANS_IDLE&&
897897
!GetVariableBool(pset.vars,"AUTOCOMMIT")&&
898-
!is_transact_command(query))
898+
!command_no_begin(query))
899899
{
900900
results=PQexec(pset.db,"BEGIN");
901901
if (PQresultStatus(results)!=PGRES_COMMAND_OK)
@@ -946,65 +946,147 @@ SendQuery(const char *query)
946946
returnOK;
947947
}
948948

949+
949950
/*
950-
*check whether a query string begins with BEGIN/COMMIT/ROLLBACK/START XACT
951+
*Advance the given char pointer over white space and SQL comments.
951952
*/
952-
staticbool
953-
is_transact_command(constchar*query)
953+
staticconstchar*
954+
skip_white_space(constchar*query)
954955
{
955-
intwordlen;
956+
intcnestlevel=0;/* slash-star comment nest level */
956957

957-
/*
958-
* First we must advance over any whitespace and comments.
959-
*/
960958
while (*query)
961959
{
960+
intmblen=PQmblen(query,pset.encoding);
961+
962+
/*
963+
* Note: we assume the encoding is a superset of ASCII, so that
964+
* for example "query[0] == '/'" is meaningful. However, we do NOT
965+
* assume that the second and subsequent bytes of a multibyte
966+
* character couldn't look like ASCII characters; so it is critical
967+
* to advance by mblen, not 1, whenever we haven't exactly identified
968+
* the character we are skipping over.
969+
*/
962970
if (isspace((unsignedchar)*query))
963-
query++;
964-
elseif (query[0]=='-'&&query[1]=='-')
971+
query+=mblen;
972+
elseif (query[0]=='/'&&query[1]=='*')
965973
{
974+
cnestlevel++;
966975
query+=2;
967-
while (*query&&*query!='\n')
968-
query++;
969976
}
970-
elseif (query[0]=='/'&&query[1]=='*')
977+
elseif (cnestlevel>0&&query[0]=='*'&&query[1]=='/')
978+
{
979+
cnestlevel--;
980+
query+=2;
981+
}
982+
elseif (cnestlevel==0&&query[0]=='-'&&query[1]=='-')
971983
{
972984
query+=2;
985+
/*
986+
* We have to skip to end of line since any slash-star inside
987+
* the -- comment does NOT start a slash-star comment.
988+
*/
973989
while (*query)
974990
{
975-
if (query[0]=='*'&&query[1]=='/')
991+
if (*query=='\n')
976992
{
977-
query+=2;
993+
query++;
978994
break;
979995
}
980-
else
981-
query++;
996+
query+=PQmblen(query,pset.encoding);
982997
}
983998
}
999+
elseif (cnestlevel>0)
1000+
query+=mblen;
9841001
else
9851002
break;/* found first token */
9861003
}
9871004

1005+
returnquery;
1006+
}
1007+
1008+
1009+
/*
1010+
* Check whether a command is one of those for which we should NOT start
1011+
* a new transaction block (ie, send a preceding BEGIN).
1012+
*
1013+
* These include the transaction control statements themselves, plus
1014+
* certain statements that the backend disallows inside transaction blocks.
1015+
*/
1016+
staticbool
1017+
command_no_begin(constchar*query)
1018+
{
1019+
intwordlen;
1020+
9881021
/*
989-
* Check word length ("beginx" is not "begin").
1022+
* First we must advance over any whitespace and comments.
1023+
*/
1024+
query=skip_white_space(query);
1025+
1026+
/*
1027+
* Check word length (since "beginx" is not "begin").
9901028
*/
9911029
wordlen=0;
9921030
while (isalpha((unsignedchar)query[wordlen]))
993-
wordlen++;
1031+
wordlen+=PQmblen(&query[wordlen],pset.encoding);
9941032

1033+
/*
1034+
* Transaction control commands. These should include every keyword
1035+
* that gives rise to a TransactionStmt in the backend grammar, except
1036+
* for the savepoint-related commands.
1037+
*
1038+
* (We assume that START must be START TRANSACTION, since there is
1039+
* presently no other "START foo" command.)
1040+
*/
1041+
if (wordlen==5&&pg_strncasecmp(query,"abort",5)==0)
1042+
return true;
9951043
if (wordlen==5&&pg_strncasecmp(query,"begin",5)==0)
9961044
return true;
1045+
if (wordlen==5&&pg_strncasecmp(query,"start",5)==0)
1046+
return true;
9971047
if (wordlen==6&&pg_strncasecmp(query,"commit",6)==0)
9981048
return true;
999-
if (wordlen==8&&pg_strncasecmp(query,"rollback",8)==0)
1049+
if (wordlen==3&&pg_strncasecmp(query,"end",3)==0)
10001050
return true;
1001-
if (wordlen==5&&pg_strncasecmp(query,"abort",5)==0)
1051+
if (wordlen==8&&pg_strncasecmp(query,"rollback",8)==0)
10021052
return true;
1003-
if (wordlen==3&&pg_strncasecmp(query,"end",3)==0)
1053+
1054+
/*
1055+
* Commands not allowed within transactions. The statements checked
1056+
* for here should be exactly those that call PreventTransactionChain()
1057+
* in the backend.
1058+
*
1059+
* Note: we are a bit sloppy about CLUSTER, which is transactional in
1060+
* some variants but not others.
1061+
*/
1062+
if (wordlen==6&&pg_strncasecmp(query,"vacuum",6)==0)
10041063
return true;
1005-
if (wordlen==5&&pg_strncasecmp(query,"start",5)==0)
1064+
if (wordlen==7&&pg_strncasecmp(query,"cluster",7)==0)
10061065
return true;
10071066

1067+
/*
1068+
* Note: these tests will match REINDEX TABLESPACE, which isn't really
1069+
* a valid command so we don't care much. The other five possible
1070+
* matches are correct.
1071+
*/
1072+
if ((wordlen==6&&pg_strncasecmp(query,"create",6)==0)||
1073+
(wordlen==4&&pg_strncasecmp(query,"drop",4)==0)||
1074+
(wordlen==7&&pg_strncasecmp(query,"reindex",7)==0))
1075+
{
1076+
query+=wordlen;
1077+
1078+
query=skip_white_space(query);
1079+
1080+
wordlen=0;
1081+
while (isalpha((unsignedchar)query[wordlen]))
1082+
wordlen+=PQmblen(&query[wordlen],pset.encoding);
1083+
1084+
if (wordlen==8&&pg_strncasecmp(query,"database",8)==0)
1085+
return true;
1086+
if (wordlen==10&&pg_strncasecmp(query,"tablespace",10)==0)
1087+
return true;
1088+
}
1089+
10081090
return false;
10091091
}
10101092

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp