8
8
*
9
9
*
10
10
* IDENTIFICATION
11
- * $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.470 2005/11/22 18: 17:21 momjian Exp $
11
+ * $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.471 2005/12/14 17:06:27 tgl Exp $
12
12
*
13
13
* NOTES
14
14
* this is the "main" module of the postgres backend and
@@ -1849,6 +1849,15 @@ exec_describe_statement_message(const char *stmt_name)
1849
1849
ListCell * l ;
1850
1850
StringInfoData buf ;
1851
1851
1852
+ /*
1853
+ * Start up a transaction command. (Note that this will normally change
1854
+ * current memory context.) Nothing happens if we are already in one.
1855
+ */
1856
+ start_xact_command ();
1857
+
1858
+ /* Switch back to message context */
1859
+ MemoryContextSwitchTo (MessageContext );
1860
+
1852
1861
/* Find prepared statement */
1853
1862
if (stmt_name [0 ] != '\0' )
1854
1863
pstmt = FetchPreparedStatement (stmt_name , true);
@@ -1862,6 +1871,22 @@ exec_describe_statement_message(const char *stmt_name)
1862
1871
errmsg ("unnamed prepared statement does not exist" )));
1863
1872
}
1864
1873
1874
+ /*
1875
+ * If we are in aborted transaction state, we can't safely create a result
1876
+ * tupledesc, because that needs catalog accesses. Hence, refuse to
1877
+ * Describe statements that return data. (We shouldn't just refuse all
1878
+ * Describes, since that might break the ability of some clients to issue
1879
+ * COMMIT or ROLLBACK commands, if they use code that blindly Describes
1880
+ * whatever it does.) We can Describe parameters without doing anything
1881
+ * dangerous, so we don't restrict that.
1882
+ */
1883
+ if (IsAbortedTransactionBlockState () &&
1884
+ PreparedStatementReturnsTuples (pstmt ))
1885
+ ereport (ERROR ,
1886
+ (errcode (ERRCODE_IN_FAILED_SQL_TRANSACTION ),
1887
+ errmsg ("current transaction is aborted, "
1888
+ "commands ignored until end of transaction block" )));
1889
+
1865
1890
if (whereToSendOutput != DestRemote )
1866
1891
return ; /* can't actually do anything... */
1867
1892
@@ -1902,12 +1927,36 @@ exec_describe_portal_message(const char *portal_name)
1902
1927
{
1903
1928
Portal portal ;
1904
1929
1930
+ /*
1931
+ * Start up a transaction command. (Note that this will normally change
1932
+ * current memory context.) Nothing happens if we are already in one.
1933
+ */
1934
+ start_xact_command ();
1935
+
1936
+ /* Switch back to message context */
1937
+ MemoryContextSwitchTo (MessageContext );
1938
+
1905
1939
portal = GetPortalByName (portal_name );
1906
1940
if (!PortalIsValid (portal ))
1907
1941
ereport (ERROR ,
1908
1942
(errcode (ERRCODE_UNDEFINED_CURSOR ),
1909
1943
errmsg ("portal \"%s\" does not exist" , portal_name )));
1910
1944
1945
+ /*
1946
+ * If we are in aborted transaction state, we can't run
1947
+ * SendRowDescriptionMessage(), because that needs catalog accesses.
1948
+ * Hence, refuse to Describe portals that return data. (We shouldn't just
1949
+ * refuse all Describes, since that might break the ability of some
1950
+ * clients to issue COMMIT or ROLLBACK commands, if they use code that
1951
+ * blindly Describes whatever it does.)
1952
+ */
1953
+ if (IsAbortedTransactionBlockState () &&
1954
+ portal -> tupDesc )
1955
+ ereport (ERROR ,
1956
+ (errcode (ERRCODE_IN_FAILED_SQL_TRANSACTION ),
1957
+ errmsg ("current transaction is aborted, "
1958
+ "commands ignored until end of transaction block" )));
1959
+
1911
1960
if (whereToSendOutput != DestRemote )
1912
1961
return ; /* can't actually do anything... */
1913
1962
0 commit comments