diff --git a/lib/modules/Sql.pmod/pgsql.pike b/lib/modules/Sql.pmod/pgsql.pike index b424e505a8642eebaccc9052fd38683cf1d04a19..35b3334dd46e8b679730cc43ad262246fa2be46d 100644 --- a/lib/modules/Sql.pmod/pgsql.pike +++ b/lib/modules/Sql.pmod/pgsql.pike @@ -211,7 +211,9 @@ protected void create(void|string host, void|string database, //! @seealso //! @[big_query()] /*semi*/final string error(void|int clear) { - throwdelayederror(proxy); + mixed err = catch(throwdelayederror(proxy)); + if (!clear && err) + throw(err); return proxy.geterror(clear); } @@ -497,7 +499,6 @@ protected void destroy() { private void reset_dbsession() { proxy.statementsinflight->wait_till_drained(); - proxy.delayederror = 0; error(1); big_query("ROLLBACK"); big_query("RESET ALL"); @@ -1039,7 +1040,6 @@ private void startquery(int forcetext, .pgsql_util.sql_result portal, string q, /*semi*/final .pgsql_util.sql_result big_query(string q, void|mapping(string|int:mixed) bindings, void|int _alltyped) { - throwdelayederror(proxy); string preparedname = ""; mapping(string:mixed) options = proxy.options; .pgsql_util.conxion c = proxy.c; @@ -1124,6 +1124,15 @@ private void startquery(int forcetext, .pgsql_util.sql_result portal, string q, */ int transtype = .pgsql_util.transendprefix->match(q) ? TRANSEND : .pgsql_util.transbeginprefix->match(q) ? TRANSBEGIN : NOTRANS; + { + int inerror = proxy.backendstatus == 'E'; + if (inerror && transtype == TRANSEND) + proxy.sendsync(); + throwdelayederror(proxy); + if (inerror && transtype != TRANSEND) + ERROR("Current transaction is aborted, " + "commands ignored until end of transaction"); + } if (transtype != NOTRANS) tp = .pgsql_util.describenodata; // Description already known else if (!forcetext && forcecache == 1 diff --git a/lib/modules/Sql.pmod/pgsql_util.pmod b/lib/modules/Sql.pmod/pgsql_util.pmod index b359143151845d0e4edbdba484db704057302d7f..1066a80de185d6afbbd8e28cdf80aa030fba8854 100644 --- a/lib/modules/Sql.pmod/pgsql_util.pmod +++ b/lib/modules/Sql.pmod/pgsql_util.pmod @@ -209,8 +209,8 @@ final void throwdelayederror(sql_result|proxy parent) { if (!objectp(parent->pgsqlsess)) parent->untolderror = 0; else if (parent->pgsqlsess) - parent->pgsqlsess->untolderror = 0; - parent.delayederror = 0; + parent->pgsqlsess->untolderror = parent->pgsqlsess->delayederror = 0; + parent->delayederror = 0; if (stringp(err)) err = ({err, backtrace()[..<2]}); throw(err); @@ -1511,7 +1511,7 @@ class sql_result { replenishrows(); } - private void releaseconditions() { + private void releaseconditions(void|int aborted) { _unnamedportalkey = _unnamedstatementkey = 0; if (!datarowtypes) { if (_state != PURGED && !delayederror) @@ -1519,9 +1519,9 @@ class sql_result { datarowtypes = ({}); _ddescribe->broadcast(); } - if (delayederror && pgsqlsess && !pgsqlsess.delayederror) + if (aborted && delayederror && pgsqlsess && !pgsqlsess.delayederror) pgsqlsess.delayederror = delayederror; // Preserve error upstream - pgsqlsess = 0; + pgsqlsess = 0; // Sever connection to upstream } final void _releasesession(void|string statusccomplete) { @@ -1542,7 +1542,7 @@ class sql_result { _state = CLOSED; } datarows->write(1); // Signal EOF - releaseconditions(); + releaseconditions(statusccomplete == "ABORT"); } protected void destroy() { @@ -1758,6 +1758,7 @@ class proxy { private array(string) lastmessage = ({}); final int(0..1) clearmessage; final int(0..1) untolderror; + final mixed delayederror; private mapping(string:array(mixed)) notifylist = ([]); final mapping(string:string) runtimeparameter; final mapping(string:mapping(string:mixed)) prepareds = ([]); @@ -1769,7 +1770,6 @@ class proxy { private int warningscollected; final int(0..1) invalidatecache; private Thread.Queue qportals; - final mixed delayederror; final function (:void) readyforquery_cb; final string host;