32
32
33
33
static bool DescribeQuery (const char * query , double * elapsed_msec );
34
34
static bool ExecQueryUsingCursor (const char * query , double * elapsed_msec );
35
+ static bool ExecQueryAndProcessResult (const char * query , double * elapsed_msec , bool * svpt_gone_p );
35
36
static bool command_no_begin (const char * query );
36
37
static bool is_select_command (const char * query );
37
38
@@ -1195,12 +1196,12 @@ bool
1195
1196
SendQuery (const char * query )
1196
1197
{
1197
1198
bool timing = pset .timing ;
1198
- PGresult * result ;
1199
1199
PGTransactionStatusType transaction_status ;
1200
1200
double elapsed_msec = 0 ;
1201
1201
bool OK = false;
1202
1202
int i ;
1203
1203
bool on_error_rollback_savepoint = false;
1204
+ bool svpt_gone = false;
1204
1205
1205
1206
if (!pset .db )
1206
1207
{
@@ -1247,6 +1248,8 @@ SendQuery(const char *query)
1247
1248
!pset .autocommit &&
1248
1249
!command_no_begin (query ))
1249
1250
{
1251
+ PGresult * result ;
1252
+
1250
1253
result = PQexec (pset .db , "BEGIN" );
1251
1254
if (PQresultStatus (result ) != PGRES_COMMAND_OK )
1252
1255
{
@@ -1264,6 +1267,8 @@ SendQuery(const char *query)
1264
1267
(pset .cur_cmd_interactive ||
1265
1268
pset .on_error_rollback == PSQL_ERROR_ROLLBACK_ON ))
1266
1269
{
1270
+ PGresult * result ;
1271
+
1267
1272
result = PQexec (pset .db , "SAVEPOINT pg_psql_temporary_savepoint" );
1268
1273
if (PQresultStatus (result ) != PGRES_COMMAND_OK )
1269
1274
{
@@ -1281,41 +1286,18 @@ SendQuery(const char *query)
1281
1286
/* Describe query's result columns, without executing it */
1282
1287
OK = DescribeQuery (query , & elapsed_msec );
1283
1288
ResetCancelConn ();
1284
- result = NULL ; /* PQclear(NULL) does nothing */
1285
1289
}
1286
1290
else if (pset .fetch_count <= 0 || pset .gexec_flag ||
1287
1291
pset .crosstab_flag || !is_select_command (query ))
1288
1292
{
1289
1293
/* Default fetch-it-all-and-print mode */
1290
- instr_time before ,
1291
- after ;
1292
-
1293
- if (timing )
1294
- INSTR_TIME_SET_CURRENT (before );
1295
-
1296
- result = PQexec (pset .db , query );
1297
-
1298
- /* these operations are included in the timing result: */
1299
- ResetCancelConn ();
1300
- OK = ProcessResult (& result );
1301
-
1302
- if (timing )
1303
- {
1304
- INSTR_TIME_SET_CURRENT (after );
1305
- INSTR_TIME_SUBTRACT (after , before );
1306
- elapsed_msec = INSTR_TIME_GET_MILLISEC (after );
1307
- }
1308
-
1309
- /* but printing result isn't: */
1310
- if (OK && result )
1311
- OK = PrintQueryResult (result );
1294
+ OK = ExecQueryAndProcessResult (query , & elapsed_msec , & svpt_gone );
1312
1295
}
1313
1296
else
1314
1297
{
1315
1298
/* Fetch-in-segments mode */
1316
1299
OK = ExecQueryUsingCursor (query , & elapsed_msec );
1317
1300
ResetCancelConn ();
1318
- result = NULL ; /* PQclear(NULL) does nothing */
1319
1301
}
1320
1302
1321
1303
if (!OK && pset .echo == PSQL_ECHO_ERRORS )
@@ -1340,20 +1322,11 @@ SendQuery(const char *query)
1340
1322
break ;
1341
1323
1342
1324
case PQTRANS_INTRANS :
1343
-
1344
1325
/*
1345
- * Do nothing if they are messing with savepoints themselves:
1346
- * If the user did COMMIT AND CHAIN, RELEASE or ROLLBACK, our
1347
- * savepoint is gone. If they issued a SAVEPOINT, releasing
1348
- * ours would remove theirs.
1326
+ * Release our savepoint, but do nothing if they are messing
1327
+ * with savepoints themselves
1349
1328
*/
1350
- if (result &&
1351
- (strcmp (PQcmdStatus (result ), "COMMIT" ) == 0 ||
1352
- strcmp (PQcmdStatus (result ), "SAVEPOINT" ) == 0 ||
1353
- strcmp (PQcmdStatus (result ), "RELEASE" ) == 0 ||
1354
- strcmp (PQcmdStatus (result ), "ROLLBACK" ) == 0 ))
1355
- svptcmd = NULL ;
1356
- else
1329
+ if (!svpt_gone )
1357
1330
svptcmd = "RELEASE pg_psql_temporary_savepoint" ;
1358
1331
break ;
1359
1332
@@ -1379,16 +1352,13 @@ SendQuery(const char *query)
1379
1352
ClearOrSaveResult (svptres );
1380
1353
OK = false;
1381
1354
1382
- PQclear (result );
1383
1355
ResetCancelConn ();
1384
1356
goto sendquery_cleanup ;
1385
1357
}
1386
1358
PQclear (svptres );
1387
1359
}
1388
1360
}
1389
1361
1390
- ClearOrSaveResult (result );
1391
-
1392
1362
/* Possible microtiming output */
1393
1363
if (timing )
1394
1364
PrintTiming (elapsed_msec );
@@ -1565,6 +1535,60 @@ DescribeQuery(const char *query, double *elapsed_msec)
1565
1535
}
1566
1536
1567
1537
1538
+ /*
1539
+ * ExecQueryAndProcessResults: SendQuery() subroutine for the normal way to
1540
+ * send a query
1541
+ */
1542
+ static bool
1543
+ ExecQueryAndProcessResult (const char * query , double * elapsed_msec , bool * svpt_gone_p )
1544
+ {
1545
+ bool timing = pset .timing ;
1546
+ bool OK ;
1547
+ instr_time before ,
1548
+ after ;
1549
+ PGresult * result ;
1550
+
1551
+ if (timing )
1552
+ INSTR_TIME_SET_CURRENT (before );
1553
+
1554
+ result = PQexec (pset .db , query );
1555
+
1556
+ /* these operations are included in the timing result: */
1557
+ ResetCancelConn ();
1558
+ OK = ProcessResult (& result );
1559
+
1560
+ if (timing )
1561
+ {
1562
+ INSTR_TIME_SET_CURRENT (after );
1563
+ INSTR_TIME_SUBTRACT (after , before );
1564
+ * elapsed_msec = INSTR_TIME_GET_MILLISEC (after );
1565
+ }
1566
+
1567
+ /* but printing result isn't: */
1568
+ if (OK && result )
1569
+ OK = PrintQueryResult (result );
1570
+
1571
+ /*
1572
+ * Check if the user ran any command that would destroy our internal
1573
+ * savepoint: If the user did COMMIT AND CHAIN, RELEASE or ROLLBACK, our
1574
+ * savepoint is gone. If they issued a SAVEPOINT, releasing ours would
1575
+ * remove theirs.
1576
+ */
1577
+ if (result && svpt_gone_p )
1578
+ {
1579
+ const char * cmd = PQcmdStatus (result );
1580
+ * svpt_gone_p = (strcmp (cmd , "COMMIT" ) == 0 ||
1581
+ strcmp (cmd , "SAVEPOINT" ) == 0 ||
1582
+ strcmp (cmd , "RELEASE" ) == 0 ||
1583
+ strcmp (cmd , "ROLLBACK" ) == 0 );
1584
+ }
1585
+
1586
+ ClearOrSaveResult (result );
1587
+
1588
+ return OK ;
1589
+ }
1590
+
1591
+
1568
1592
/*
1569
1593
* ExecQueryUsingCursor: run a SELECT-like query using a cursor
1570
1594
*
0 commit comments