~ubuntu-branches/debian/sid/postgresql-9.3/sid

« back to all changes in this revision

Viewing changes to src/bin/psql/common.c

  • Committer: Package Import Robot
  • Author(s): Martin Pitt
  • Date: 2013-05-08 05:39:52 UTC
  • Revision ID: package-import@ubuntu.com-20130508053952-1j7uilp7mjtrvq8q
Tags: upstream-9.3~beta1
ImportĀ upstreamĀ versionĀ 9.3~beta1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * psql - the PostgreSQL interactive terminal
 
3
 *
 
4
 * Copyright (c) 2000-2013, PostgreSQL Global Development Group
 
5
 *
 
6
 * src/bin/psql/common.c
 
7
 */
 
8
#include "postgres_fe.h"
 
9
#include "common.h"
 
10
 
 
11
#include <ctype.h>
 
12
#include <signal.h>
 
13
#ifndef WIN32
 
14
#include <unistd.h>                             /* for write() */
 
15
#else
 
16
#include <io.h>                                 /* for _write() */
 
17
#include <win32.h>
 
18
#endif
 
19
 
 
20
#include "portability/instr_time.h"
 
21
 
 
22
#include "settings.h"
 
23
#include "command.h"
 
24
#include "copy.h"
 
25
#include "mbprint.h"
 
26
 
 
27
 
 
28
 
 
29
static bool ExecQueryUsingCursor(const char *query, double *elapsed_msec);
 
30
static bool command_no_begin(const char *query);
 
31
static bool is_select_command(const char *query);
 
32
 
 
33
/*
 
34
 * setQFout
 
35
 * -- handler for -o command line option and \o command
 
36
 *
 
37
 * Tries to open file fname (or pipe if fname starts with '|')
 
38
 * and stores the file handle in pset)
 
39
 * Upon failure, sets stdout and returns false.
 
40
 */
 
41
bool
 
42
setQFout(const char *fname)
 
43
{
 
44
        bool            status = true;
 
45
 
 
46
        /* Close old file/pipe */
 
47
        if (pset.queryFout && pset.queryFout != stdout && pset.queryFout != stderr)
 
48
        {
 
49
                if (pset.queryFoutPipe)
 
50
                        pclose(pset.queryFout);
 
51
                else
 
52
                        fclose(pset.queryFout);
 
53
        }
 
54
 
 
55
        /* If no filename, set stdout */
 
56
        if (!fname || fname[0] == '\0')
 
57
        {
 
58
                pset.queryFout = stdout;
 
59
                pset.queryFoutPipe = false;
 
60
        }
 
61
        else if (*fname == '|')
 
62
        {
 
63
                pset.queryFout = popen(fname + 1, "w");
 
64
                pset.queryFoutPipe = true;
 
65
        }
 
66
        else
 
67
        {
 
68
                pset.queryFout = fopen(fname, "w");
 
69
                pset.queryFoutPipe = false;
 
70
        }
 
71
 
 
72
        if (!(pset.queryFout))
 
73
        {
 
74
                psql_error("%s: %s\n", fname, strerror(errno));
 
75
                pset.queryFout = stdout;
 
76
                pset.queryFoutPipe = false;
 
77
                status = false;
 
78
        }
 
79
 
 
80
        /* Direct signals */
 
81
#ifndef WIN32
 
82
        pqsignal(SIGPIPE, pset.queryFoutPipe ? SIG_IGN : SIG_DFL);
 
83
#endif
 
84
 
 
85
        return status;
 
86
}
 
87
 
 
88
 
 
89
 
 
90
/*
 
91
 * Error reporting for scripts. Errors should look like
 
92
 *       psql:filename:lineno: message
 
93
 *
 
94
 */
 
95
void
 
96
psql_error(const char *fmt,...)
 
97
{
 
98
        va_list         ap;
 
99
 
 
100
        fflush(stdout);
 
101
        if (pset.queryFout && pset.queryFout != stdout)
 
102
                fflush(pset.queryFout);
 
103
 
 
104
        if (pset.inputfile)
 
105
                fprintf(stderr, "%s:%s:" UINT64_FORMAT ": ", pset.progname, pset.inputfile, pset.lineno);
 
106
        va_start(ap, fmt);
 
107
        vfprintf(stderr, _(fmt), ap);
 
108
        va_end(ap);
 
109
}
 
110
 
 
111
 
 
112
 
 
113
/*
 
114
 * for backend Notice messages (INFO, WARNING, etc)
 
115
 */
 
116
void
 
117
NoticeProcessor(void *arg, const char *message)
 
118
{
 
119
        (void) arg;                                     /* not used */
 
120
        psql_error("%s", message);
 
121
}
 
122
 
 
123
 
 
124
 
 
125
/*
 
126
 * Code to support query cancellation
 
127
 *
 
128
 * Before we start a query, we enable the SIGINT signal catcher to send a
 
129
 * cancel request to the backend. Note that sending the cancel directly from
 
130
 * the signal handler is safe because PQcancel() is written to make it
 
131
 * so. We use write() to report to stderr because it's better to use simple
 
132
 * facilities in a signal handler.
 
133
 *
 
134
 * On win32, the signal canceling happens on a separate thread, because
 
135
 * that's how SetConsoleCtrlHandler works. The PQcancel function is safe
 
136
 * for this (unlike PQrequestCancel). However, a CRITICAL_SECTION is required
 
137
 * to protect the PGcancel structure against being changed while the signal
 
138
 * thread is using it.
 
139
 *
 
140
 * SIGINT is supposed to abort all long-running psql operations, not only
 
141
 * database queries.  In most places, this is accomplished by checking
 
142
 * cancel_pressed during long-running loops.  However, that won't work when
 
143
 * blocked on user input (in readline() or fgets()).  In those places, we
 
144
 * set sigint_interrupt_enabled TRUE while blocked, instructing the signal
 
145
 * catcher to longjmp through sigint_interrupt_jmp.  We assume readline and
 
146
 * fgets are coded to handle possible interruption.  (XXX currently this does
 
147
 * not work on win32, so control-C is less useful there)
 
148
 */
 
149
volatile bool sigint_interrupt_enabled = false;
 
150
 
 
151
sigjmp_buf      sigint_interrupt_jmp;
 
152
 
 
153
static PGcancel *volatile cancelConn = NULL;
 
154
 
 
155
#ifdef WIN32
 
156
static CRITICAL_SECTION cancelConnLock;
 
157
#endif
 
158
 
 
159
/* Used from signal handlers, no buffering */
 
160
#define write_stderr(str)       write(fileno(stderr), str, strlen(str))
 
161
 
 
162
 
 
163
#ifndef WIN32
 
164
 
 
165
static void
 
166
handle_sigint(SIGNAL_ARGS)
 
167
{
 
168
        int                     save_errno = errno;
 
169
        int                     rc;
 
170
        char            errbuf[256];
 
171
 
 
172
        /* if we are waiting for input, longjmp out of it */
 
173
        if (sigint_interrupt_enabled)
 
174
        {
 
175
                sigint_interrupt_enabled = false;
 
176
                siglongjmp(sigint_interrupt_jmp, 1);
 
177
        }
 
178
 
 
179
        /* else, set cancel flag to stop any long-running loops */
 
180
        cancel_pressed = true;
 
181
 
 
182
        /* and send QueryCancel if we are processing a database query */
 
183
        if (cancelConn != NULL)
 
184
        {
 
185
                if (PQcancel(cancelConn, errbuf, sizeof(errbuf)))
 
186
                {
 
187
                        rc = write_stderr("Cancel request sent\n");
 
188
                        (void) rc;                      /* ignore errors, nothing we can do here */
 
189
                }
 
190
                else
 
191
                {
 
192
                        rc = write_stderr("Could not send cancel request: ");
 
193
                        (void) rc;                      /* ignore errors, nothing we can do here */
 
194
                        rc = write_stderr(errbuf);
 
195
                        (void) rc;                      /* ignore errors, nothing we can do here */
 
196
                }
 
197
        }
 
198
 
 
199
        errno = save_errno;                     /* just in case the write changed it */
 
200
}
 
201
 
 
202
void
 
203
setup_cancel_handler(void)
 
204
{
 
205
        pqsignal(SIGINT, handle_sigint);
 
206
}
 
207
#else                                                   /* WIN32 */
 
208
 
 
209
static BOOL WINAPI
 
210
consoleHandler(DWORD dwCtrlType)
 
211
{
 
212
        char            errbuf[256];
 
213
 
 
214
        if (dwCtrlType == CTRL_C_EVENT ||
 
215
                dwCtrlType == CTRL_BREAK_EVENT)
 
216
        {
 
217
                /*
 
218
                 * Can't longjmp here, because we are in wrong thread :-(
 
219
                 */
 
220
 
 
221
                /* set cancel flag to stop any long-running loops */
 
222
                cancel_pressed = true;
 
223
 
 
224
                /* and send QueryCancel if we are processing a database query */
 
225
                EnterCriticalSection(&cancelConnLock);
 
226
                if (cancelConn != NULL)
 
227
                {
 
228
                        if (PQcancel(cancelConn, errbuf, sizeof(errbuf)))
 
229
                                write_stderr("Cancel request sent\n");
 
230
                        else
 
231
                        {
 
232
                                write_stderr("Could not send cancel request: ");
 
233
                                write_stderr(errbuf);
 
234
                        }
 
235
                }
 
236
                LeaveCriticalSection(&cancelConnLock);
 
237
 
 
238
                return TRUE;
 
239
        }
 
240
        else
 
241
                /* Return FALSE for any signals not being handled */
 
242
                return FALSE;
 
243
}
 
244
 
 
245
void
 
246
setup_cancel_handler(void)
 
247
{
 
248
        InitializeCriticalSection(&cancelConnLock);
 
249
 
 
250
        SetConsoleCtrlHandler(consoleHandler, TRUE);
 
251
}
 
252
#endif   /* WIN32 */
 
253
 
 
254
 
 
255
/* ConnectionUp
 
256
 *
 
257
 * Returns whether our backend connection is still there.
 
258
 */
 
259
static bool
 
260
ConnectionUp(void)
 
261
{
 
262
        return PQstatus(pset.db) != CONNECTION_BAD;
 
263
}
 
264
 
 
265
 
 
266
 
 
267
/* CheckConnection
 
268
 *
 
269
 * Verify that we still have a good connection to the backend, and if not,
 
270
 * see if it can be restored.
 
271
 *
 
272
 * Returns true if either the connection was still there, or it could be
 
273
 * restored successfully; false otherwise.      If, however, there was no
 
274
 * connection and the session is non-interactive, this will exit the program
 
275
 * with a code of EXIT_BADCONN.
 
276
 */
 
277
static bool
 
278
CheckConnection(void)
 
279
{
 
280
        bool            OK;
 
281
 
 
282
        OK = ConnectionUp();
 
283
        if (!OK)
 
284
        {
 
285
                if (!pset.cur_cmd_interactive)
 
286
                {
 
287
                        psql_error("connection to server was lost\n");
 
288
                        exit(EXIT_BADCONN);
 
289
                }
 
290
 
 
291
                psql_error("The connection to the server was lost. Attempting reset: ");
 
292
                PQreset(pset.db);
 
293
                OK = ConnectionUp();
 
294
                if (!OK)
 
295
                {
 
296
                        psql_error("Failed.\n");
 
297
                        PQfinish(pset.db);
 
298
                        pset.db = NULL;
 
299
                        ResetCancelConn();
 
300
                        UnsyncVariables();
 
301
                }
 
302
                else
 
303
                        psql_error("Succeeded.\n");
 
304
        }
 
305
 
 
306
        return OK;
 
307
}
 
308
 
 
309
 
 
310
 
 
311
/*
 
312
 * SetCancelConn
 
313
 *
 
314
 * Set cancelConn to point to the current database connection.
 
315
 */
 
316
void
 
317
SetCancelConn(void)
 
318
{
 
319
        PGcancel   *oldCancelConn;
 
320
 
 
321
#ifdef WIN32
 
322
        EnterCriticalSection(&cancelConnLock);
 
323
#endif
 
324
 
 
325
        /* Free the old one if we have one */
 
326
        oldCancelConn = cancelConn;
 
327
        /* be sure handle_sigint doesn't use pointer while freeing */
 
328
        cancelConn = NULL;
 
329
 
 
330
        if (oldCancelConn != NULL)
 
331
                PQfreeCancel(oldCancelConn);
 
332
 
 
333
        cancelConn = PQgetCancel(pset.db);
 
334
 
 
335
#ifdef WIN32
 
336
        LeaveCriticalSection(&cancelConnLock);
 
337
#endif
 
338
}
 
339
 
 
340
 
 
341
/*
 
342
 * ResetCancelConn
 
343
 *
 
344
 * Free the current cancel connection, if any, and set to NULL.
 
345
 */
 
346
void
 
347
ResetCancelConn(void)
 
348
{
 
349
        PGcancel   *oldCancelConn;
 
350
 
 
351
#ifdef WIN32
 
352
        EnterCriticalSection(&cancelConnLock);
 
353
#endif
 
354
 
 
355
        oldCancelConn = cancelConn;
 
356
        /* be sure handle_sigint doesn't use pointer while freeing */
 
357
        cancelConn = NULL;
 
358
 
 
359
        if (oldCancelConn != NULL)
 
360
                PQfreeCancel(oldCancelConn);
 
361
 
 
362
#ifdef WIN32
 
363
        LeaveCriticalSection(&cancelConnLock);
 
364
#endif
 
365
}
 
366
 
 
367
 
 
368
/*
 
369
 * AcceptResult
 
370
 *
 
371
 * Checks whether a result is valid, giving an error message if necessary;
 
372
 * and ensures that the connection to the backend is still up.
 
373
 *
 
374
 * Returns true for valid result, false for error state.
 
375
 */
 
376
static bool
 
377
AcceptResult(const PGresult *result)
 
378
{
 
379
        bool            OK;
 
380
 
 
381
        if (!result)
 
382
                OK = false;
 
383
        else
 
384
                switch (PQresultStatus(result))
 
385
                {
 
386
                        case PGRES_COMMAND_OK:
 
387
                        case PGRES_TUPLES_OK:
 
388
                        case PGRES_EMPTY_QUERY:
 
389
                        case PGRES_COPY_IN:
 
390
                        case PGRES_COPY_OUT:
 
391
                                /* Fine, do nothing */
 
392
                                OK = true;
 
393
                                break;
 
394
 
 
395
                        case PGRES_BAD_RESPONSE:
 
396
                        case PGRES_NONFATAL_ERROR:
 
397
                        case PGRES_FATAL_ERROR:
 
398
                                OK = false;
 
399
                                break;
 
400
 
 
401
                        default:
 
402
                                OK = false;
 
403
                                psql_error("unexpected PQresultStatus: %d\n",
 
404
                                                   PQresultStatus(result));
 
405
                                break;
 
406
                }
 
407
 
 
408
        if (!OK)
 
409
        {
 
410
                const char *error = PQerrorMessage(pset.db);
 
411
 
 
412
                if (strlen(error))
 
413
                        psql_error("%s", error);
 
414
 
 
415
                CheckConnection();
 
416
        }
 
417
 
 
418
        return OK;
 
419
}
 
420
 
 
421
 
 
422
 
 
423
/*
 
424
 * PSQLexec
 
425
 *
 
426
 * This is the way to send "backdoor" queries (those not directly entered
 
427
 * by the user). It is subject to -E but not -e.
 
428
 *
 
429
 * In autocommit-off mode, a new transaction block is started if start_xact
 
430
 * is true; nothing special is done when start_xact is false.  Typically,
 
431
 * start_xact = false is used for SELECTs and explicit BEGIN/COMMIT commands.
 
432
 *
 
433
 * Caller is responsible for handling the ensuing processing if a COPY
 
434
 * command is sent.
 
435
 *
 
436
 * Note: we don't bother to check PQclientEncoding; it is assumed that no
 
437
 * caller uses this path to issue "SET CLIENT_ENCODING".
 
438
 */
 
439
PGresult *
 
440
PSQLexec(const char *query, bool start_xact)
 
441
{
 
442
        PGresult   *res;
 
443
 
 
444
        if (!pset.db)
 
445
        {
 
446
                psql_error("You are currently not connected to a database.\n");
 
447
                return NULL;
 
448
        }
 
449
 
 
450
        if (pset.echo_hidden != PSQL_ECHO_HIDDEN_OFF)
 
451
        {
 
452
                printf(_("********* QUERY **********\n"
 
453
                                 "%s\n"
 
454
                                 "**************************\n\n"), query);
 
455
                fflush(stdout);
 
456
                if (pset.logfile)
 
457
                {
 
458
                        fprintf(pset.logfile,
 
459
                                        _("********* QUERY **********\n"
 
460
                                          "%s\n"
 
461
                                          "**************************\n\n"), query);
 
462
                        fflush(pset.logfile);
 
463
                }
 
464
 
 
465
                if (pset.echo_hidden == PSQL_ECHO_HIDDEN_NOEXEC)
 
466
                        return NULL;
 
467
        }
 
468
 
 
469
        SetCancelConn();
 
470
 
 
471
        if (start_xact &&
 
472
                !pset.autocommit &&
 
473
                PQtransactionStatus(pset.db) == PQTRANS_IDLE)
 
474
        {
 
475
                res = PQexec(pset.db, "BEGIN");
 
476
                if (PQresultStatus(res) != PGRES_COMMAND_OK)
 
477
                {
 
478
                        psql_error("%s", PQerrorMessage(pset.db));
 
479
                        PQclear(res);
 
480
                        ResetCancelConn();
 
481
                        return NULL;
 
482
                }
 
483
                PQclear(res);
 
484
        }
 
485
 
 
486
        res = PQexec(pset.db, query);
 
487
 
 
488
        ResetCancelConn();
 
489
 
 
490
        if (!AcceptResult(res))
 
491
        {
 
492
                PQclear(res);
 
493
                res = NULL;
 
494
        }
 
495
 
 
496
        return res;
 
497
}
 
498
 
 
499
 
 
500
 
 
501
/*
 
502
 * PrintNotifications: check for asynchronous notifications, and print them out
 
503
 */
 
504
static void
 
505
PrintNotifications(void)
 
506
{
 
507
        PGnotify   *notify;
 
508
 
 
509
        while ((notify = PQnotifies(pset.db)))
 
510
        {
 
511
                /* for backward compatibility, only show payload if nonempty */
 
512
                if (notify->extra[0])
 
513
                        fprintf(pset.queryFout, _("Asynchronous notification \"%s\" with payload \"%s\" received from server process with PID %d.\n"),
 
514
                                        notify->relname, notify->extra, notify->be_pid);
 
515
                else
 
516
                        fprintf(pset.queryFout, _("Asynchronous notification \"%s\" received from server process with PID %d.\n"),
 
517
                                        notify->relname, notify->be_pid);
 
518
                fflush(pset.queryFout);
 
519
                PQfreemem(notify);
 
520
        }
 
521
}
 
522
 
 
523
 
 
524
/*
 
525
 * PrintQueryTuples: assuming query result is OK, print its tuples
 
526
 *
 
527
 * Returns true if successful, false otherwise.
 
528
 */
 
529
static bool
 
530
PrintQueryTuples(const PGresult *results)
 
531
{
 
532
        printQueryOpt my_popt = pset.popt;
 
533
 
 
534
        /* write output to \g argument, if any */
 
535
        if (pset.gfname)
 
536
        {
 
537
                /* keep this code in sync with ExecQueryUsingCursor */
 
538
                FILE       *queryFout_copy = pset.queryFout;
 
539
                bool            queryFoutPipe_copy = pset.queryFoutPipe;
 
540
 
 
541
                pset.queryFout = stdout;        /* so it doesn't get closed */
 
542
 
 
543
                /* open file/pipe */
 
544
                if (!setQFout(pset.gfname))
 
545
                {
 
546
                        pset.queryFout = queryFout_copy;
 
547
                        pset.queryFoutPipe = queryFoutPipe_copy;
 
548
                        return false;
 
549
                }
 
550
 
 
551
                printQuery(results, &my_popt, pset.queryFout, pset.logfile);
 
552
 
 
553
                /* close file/pipe, restore old setting */
 
554
                setQFout(NULL);
 
555
 
 
556
                pset.queryFout = queryFout_copy;
 
557
                pset.queryFoutPipe = queryFoutPipe_copy;
 
558
        }
 
559
        else
 
560
                printQuery(results, &my_popt, pset.queryFout, pset.logfile);
 
561
 
 
562
        return true;
 
563
}
 
564
 
 
565
 
 
566
/*
 
567
 * StoreQueryTuple: assuming query result is OK, save data into variables
 
568
 *
 
569
 * Returns true if successful, false otherwise.
 
570
 */
 
571
static bool
 
572
StoreQueryTuple(const PGresult *result)
 
573
{
 
574
        bool            success = true;
 
575
 
 
576
        if (PQntuples(result) < 1)
 
577
        {
 
578
                psql_error("no rows returned for \\gset\n");
 
579
                success = false;
 
580
        }
 
581
        else if (PQntuples(result) > 1)
 
582
        {
 
583
                psql_error("more than one row returned for \\gset\n");
 
584
                success = false;
 
585
        }
 
586
        else
 
587
        {
 
588
                int                     i;
 
589
 
 
590
                for (i = 0; i < PQnfields(result); i++)
 
591
                {
 
592
                        char       *colname = PQfname(result, i);
 
593
                        char       *varname;
 
594
                        char       *value;
 
595
 
 
596
                        /* concate prefix and column name */
 
597
                        varname = pg_malloc(strlen(pset.gset_prefix) + strlen(colname) + 1);
 
598
                        strcpy(varname, pset.gset_prefix);
 
599
                        strcat(varname, colname);
 
600
 
 
601
                        if (!PQgetisnull(result, 0, i))
 
602
                                value = PQgetvalue(result, 0, i);
 
603
                        else
 
604
                        {
 
605
                                /* for NULL value, unset rather than set the variable */
 
606
                                value = NULL;
 
607
                        }
 
608
 
 
609
                        if (!SetVariable(pset.vars, varname, value))
 
610
                        {
 
611
                                psql_error("could not set variable \"%s\"\n", varname);
 
612
                                free(varname);
 
613
                                success = false;
 
614
                                break;
 
615
                        }
 
616
 
 
617
                        free(varname);
 
618
                }
 
619
        }
 
620
 
 
621
        return success;
 
622
}
 
623
 
 
624
 
 
625
/*
 
626
 * ProcessResult: utility function for use by SendQuery() only
 
627
 *
 
628
 * When our command string contained a COPY FROM STDIN or COPY TO STDOUT,
 
629
 * PQexec() has stopped at the PGresult associated with the first such
 
630
 * command.  In that event, we'll marshal data for the COPY and then cycle
 
631
 * through any subsequent PGresult objects.
 
632
 *
 
633
 * When the command string contained no affected COPY command, this function
 
634
 * degenerates to an AcceptResult() call.
 
635
 *
 
636
 * Changes its argument to point to the last PGresult of the command string,
 
637
 * or NULL if that result was for a COPY FROM STDIN or COPY TO STDOUT.
 
638
 *
 
639
 * Returns true on complete success, false otherwise.  Possible failure modes
 
640
 * include purely client-side problems; check the transaction status for the
 
641
 * server-side opinion.
 
642
 */
 
643
static bool
 
644
ProcessResult(PGresult **results)
 
645
{
 
646
        PGresult   *next_result;
 
647
        bool            success = true;
 
648
        bool            first_cycle = true;
 
649
 
 
650
        do
 
651
        {
 
652
                ExecStatusType result_status;
 
653
                bool            is_copy;
 
654
 
 
655
                if (!AcceptResult(*results))
 
656
                {
 
657
                        /*
 
658
                         * Failure at this point is always a server-side failure or a
 
659
                         * failure to submit the command string.  Either way, we're
 
660
                         * finished with this command string.
 
661
                         */
 
662
                        success = false;
 
663
                        break;
 
664
                }
 
665
 
 
666
                result_status = PQresultStatus(*results);
 
667
                switch (result_status)
 
668
                {
 
669
                        case PGRES_EMPTY_QUERY:
 
670
                        case PGRES_COMMAND_OK:
 
671
                        case PGRES_TUPLES_OK:
 
672
                                is_copy = false;
 
673
                                break;
 
674
 
 
675
                        case PGRES_COPY_OUT:
 
676
                        case PGRES_COPY_IN:
 
677
                                is_copy = true;
 
678
                                break;
 
679
 
 
680
                        default:
 
681
                                /* AcceptResult() should have caught anything else. */
 
682
                                is_copy = false;
 
683
                                psql_error("unexpected PQresultStatus: %d\n", result_status);
 
684
                                break;
 
685
                }
 
686
 
 
687
                if (is_copy)
 
688
                {
 
689
                        /*
 
690
                         * Marshal the COPY data.  Either subroutine will get the
 
691
                         * connection out of its COPY state, then call PQresultStatus()
 
692
                         * once and report any error.
 
693
                         */
 
694
                        SetCancelConn();
 
695
                        if (result_status == PGRES_COPY_OUT)
 
696
                                success = handleCopyOut(pset.db, pset.queryFout) && success;
 
697
                        else
 
698
                                success = handleCopyIn(pset.db, pset.cur_cmd_source,
 
699
                                                                           PQbinaryTuples(*results)) && success;
 
700
                        ResetCancelConn();
 
701
 
 
702
                        /*
 
703
                         * Call PQgetResult() once more.  In the typical case of a
 
704
                         * single-command string, it will return NULL.  Otherwise, we'll
 
705
                         * have other results to process that may include other COPYs.
 
706
                         */
 
707
                        PQclear(*results);
 
708
                        *results = next_result = PQgetResult(pset.db);
 
709
                }
 
710
                else if (first_cycle)
 
711
                        /* fast path: no COPY commands; PQexec visited all results */
 
712
                        break;
 
713
                else if ((next_result = PQgetResult(pset.db)))
 
714
                {
 
715
                        /* non-COPY command(s) after a COPY: keep the last one */
 
716
                        PQclear(*results);
 
717
                        *results = next_result;
 
718
                }
 
719
 
 
720
                first_cycle = false;
 
721
        } while (next_result);
 
722
 
 
723
        /* may need this to recover from conn loss during COPY */
 
724
        if (!first_cycle && !CheckConnection())
 
725
                return false;
 
726
 
 
727
        return success;
 
728
}
 
729
 
 
730
 
 
731
/*
 
732
 * PrintQueryStatus: report command status as required
 
733
 *
 
734
 * Note: Utility function for use by PrintQueryResults() only.
 
735
 */
 
736
static void
 
737
PrintQueryStatus(PGresult *results)
 
738
{
 
739
        char            buf[16];
 
740
 
 
741
        if (!pset.quiet)
 
742
        {
 
743
                if (pset.popt.topt.format == PRINT_HTML)
 
744
                {
 
745
                        fputs("<p>", pset.queryFout);
 
746
                        html_escaped_print(PQcmdStatus(results), pset.queryFout);
 
747
                        fputs("</p>\n", pset.queryFout);
 
748
                }
 
749
                else
 
750
                        fprintf(pset.queryFout, "%s\n", PQcmdStatus(results));
 
751
        }
 
752
 
 
753
        if (pset.logfile)
 
754
                fprintf(pset.logfile, "%s\n", PQcmdStatus(results));
 
755
 
 
756
        snprintf(buf, sizeof(buf), "%u", (unsigned int) PQoidValue(results));
 
757
        SetVariable(pset.vars, "LASTOID", buf);
 
758
}
 
759
 
 
760
 
 
761
/*
 
762
 * PrintQueryResults: print out (or store) query results as required
 
763
 *
 
764
 * Note: Utility function for use by SendQuery() only.
 
765
 *
 
766
 * Returns true if the query executed successfully, false otherwise.
 
767
 */
 
768
static bool
 
769
PrintQueryResults(PGresult *results)
 
770
{
 
771
        bool            success;
 
772
        const char *cmdstatus;
 
773
 
 
774
        if (!results)
 
775
                return false;
 
776
 
 
777
        switch (PQresultStatus(results))
 
778
        {
 
779
                case PGRES_TUPLES_OK:
 
780
                        /* store or print the data ... */
 
781
                        if (pset.gset_prefix)
 
782
                                success = StoreQueryTuple(results);
 
783
                        else
 
784
                                success = PrintQueryTuples(results);
 
785
                        /* if it's INSERT/UPDATE/DELETE RETURNING, also print status */
 
786
                        cmdstatus = PQcmdStatus(results);
 
787
                        if (strncmp(cmdstatus, "INSERT", 6) == 0 ||
 
788
                                strncmp(cmdstatus, "UPDATE", 6) == 0 ||
 
789
                                strncmp(cmdstatus, "DELETE", 6) == 0)
 
790
                                PrintQueryStatus(results);
 
791
                        break;
 
792
 
 
793
                case PGRES_COMMAND_OK:
 
794
                        PrintQueryStatus(results);
 
795
                        success = true;
 
796
                        break;
 
797
 
 
798
                case PGRES_EMPTY_QUERY:
 
799
                        success = true;
 
800
                        break;
 
801
 
 
802
                case PGRES_COPY_OUT:
 
803
                case PGRES_COPY_IN:
 
804
                        /* nothing to do here */
 
805
                        success = true;
 
806
                        break;
 
807
 
 
808
                case PGRES_BAD_RESPONSE:
 
809
                case PGRES_NONFATAL_ERROR:
 
810
                case PGRES_FATAL_ERROR:
 
811
                        success = false;
 
812
                        break;
 
813
 
 
814
                default:
 
815
                        success = false;
 
816
                        psql_error("unexpected PQresultStatus: %d\n",
 
817
                                           PQresultStatus(results));
 
818
                        break;
 
819
        }
 
820
 
 
821
        fflush(pset.queryFout);
 
822
 
 
823
        return success;
 
824
}
 
825
 
 
826
 
 
827
/*
 
828
 * SendQuery: send the query string to the backend
 
829
 * (and print out results)
 
830
 *
 
831
 * Note: This is the "front door" way to send a query. That is, use it to
 
832
 * send queries actually entered by the user. These queries will be subject to
 
833
 * single step mode.
 
834
 * To send "back door" queries (generated by slash commands, etc.) in a
 
835
 * controlled way, use PSQLexec().
 
836
 *
 
837
 * Returns true if the query executed successfully, false otherwise.
 
838
 */
 
839
bool
 
840
SendQuery(const char *query)
 
841
{
 
842
        PGresult   *results;
 
843
        PGTransactionStatusType transaction_status;
 
844
        double          elapsed_msec = 0;
 
845
        bool            OK = false;
 
846
        bool            on_error_rollback_savepoint = false;
 
847
        static bool on_error_rollback_warning = false;
 
848
 
 
849
        if (!pset.db)
 
850
        {
 
851
                psql_error("You are currently not connected to a database.\n");
 
852
                goto sendquery_cleanup;
 
853
        }
 
854
 
 
855
        if (pset.singlestep)
 
856
        {
 
857
                char            buf[3];
 
858
 
 
859
                printf(_("***(Single step mode: verify command)*******************************************\n"
 
860
                                 "%s\n"
 
861
                                 "***(press return to proceed or enter x and return to cancel)********************\n"),
 
862
                           query);
 
863
                fflush(stdout);
 
864
                if (fgets(buf, sizeof(buf), stdin) != NULL)
 
865
                        if (buf[0] == 'x')
 
866
                                goto sendquery_cleanup;
 
867
        }
 
868
        else if (pset.echo == PSQL_ECHO_QUERIES)
 
869
        {
 
870
                puts(query);
 
871
                fflush(stdout);
 
872
        }
 
873
 
 
874
        if (pset.logfile)
 
875
        {
 
876
                fprintf(pset.logfile,
 
877
                                _("********* QUERY **********\n"
 
878
                                  "%s\n"
 
879
                                  "**************************\n\n"), query);
 
880
                fflush(pset.logfile);
 
881
        }
 
882
 
 
883
        SetCancelConn();
 
884
 
 
885
        transaction_status = PQtransactionStatus(pset.db);
 
886
 
 
887
        if (transaction_status == PQTRANS_IDLE &&
 
888
                !pset.autocommit &&
 
889
                !command_no_begin(query))
 
890
        {
 
891
                results = PQexec(pset.db, "BEGIN");
 
892
                if (PQresultStatus(results) != PGRES_COMMAND_OK)
 
893
                {
 
894
                        psql_error("%s", PQerrorMessage(pset.db));
 
895
                        PQclear(results);
 
896
                        ResetCancelConn();
 
897
                        goto sendquery_cleanup;
 
898
                }
 
899
                PQclear(results);
 
900
                transaction_status = PQtransactionStatus(pset.db);
 
901
        }
 
902
 
 
903
        if (transaction_status == PQTRANS_INTRANS &&
 
904
                pset.on_error_rollback != PSQL_ERROR_ROLLBACK_OFF &&
 
905
                (pset.cur_cmd_interactive ||
 
906
                 pset.on_error_rollback == PSQL_ERROR_ROLLBACK_ON))
 
907
        {
 
908
                if (on_error_rollback_warning == false && pset.sversion < 80000)
 
909
                {
 
910
                        psql_error("The server (version %d.%d) does not support savepoints for ON_ERROR_ROLLBACK.\n",
 
911
                                           pset.sversion / 10000, (pset.sversion / 100) % 100);
 
912
                        on_error_rollback_warning = true;
 
913
                }
 
914
                else
 
915
                {
 
916
                        results = PQexec(pset.db, "SAVEPOINT pg_psql_temporary_savepoint");
 
917
                        if (PQresultStatus(results) != PGRES_COMMAND_OK)
 
918
                        {
 
919
                                psql_error("%s", PQerrorMessage(pset.db));
 
920
                                PQclear(results);
 
921
                                ResetCancelConn();
 
922
                                goto sendquery_cleanup;
 
923
                        }
 
924
                        PQclear(results);
 
925
                        on_error_rollback_savepoint = true;
 
926
                }
 
927
        }
 
928
 
 
929
        if (pset.fetch_count <= 0 || !is_select_command(query))
 
930
        {
 
931
                /* Default fetch-it-all-and-print mode */
 
932
                instr_time      before,
 
933
                                        after;
 
934
 
 
935
                if (pset.timing)
 
936
                        INSTR_TIME_SET_CURRENT(before);
 
937
 
 
938
                results = PQexec(pset.db, query);
 
939
 
 
940
                /* these operations are included in the timing result: */
 
941
                ResetCancelConn();
 
942
                OK = ProcessResult(&results);
 
943
 
 
944
                if (pset.timing)
 
945
                {
 
946
                        INSTR_TIME_SET_CURRENT(after);
 
947
                        INSTR_TIME_SUBTRACT(after, before);
 
948
                        elapsed_msec = INSTR_TIME_GET_MILLISEC(after);
 
949
                }
 
950
 
 
951
                /* but printing results isn't: */
 
952
                if (OK && results)
 
953
                        OK = PrintQueryResults(results);
 
954
        }
 
955
        else
 
956
        {
 
957
                /* Fetch-in-segments mode */
 
958
                OK = ExecQueryUsingCursor(query, &elapsed_msec);
 
959
                ResetCancelConn();
 
960
                results = NULL;                 /* PQclear(NULL) does nothing */
 
961
        }
 
962
 
 
963
        /* If we made a temporary savepoint, possibly release/rollback */
 
964
        if (on_error_rollback_savepoint)
 
965
        {
 
966
                const char *svptcmd = NULL;
 
967
 
 
968
                transaction_status = PQtransactionStatus(pset.db);
 
969
 
 
970
                switch (transaction_status)
 
971
                {
 
972
                        case PQTRANS_INERROR:
 
973
                                /* We always rollback on an error */
 
974
                                svptcmd = "ROLLBACK TO pg_psql_temporary_savepoint";
 
975
                                break;
 
976
 
 
977
                        case PQTRANS_IDLE:
 
978
                                /* If they are no longer in a transaction, then do nothing */
 
979
                                break;
 
980
 
 
981
                        case PQTRANS_INTRANS:
 
982
 
 
983
                                /*
 
984
                                 * Do nothing if they are messing with savepoints themselves:
 
985
                                 * If the user did RELEASE or ROLLBACK, our savepoint is gone.
 
986
                                 * If they issued a SAVEPOINT, releasing ours would remove
 
987
                                 * theirs.
 
988
                                 */
 
989
                                if (results &&
 
990
                                        (strcmp(PQcmdStatus(results), "SAVEPOINT") == 0 ||
 
991
                                         strcmp(PQcmdStatus(results), "RELEASE") == 0 ||
 
992
                                         strcmp(PQcmdStatus(results), "ROLLBACK") == 0))
 
993
                                        svptcmd = NULL;
 
994
                                else
 
995
                                        svptcmd = "RELEASE pg_psql_temporary_savepoint";
 
996
                                break;
 
997
 
 
998
                        case PQTRANS_ACTIVE:
 
999
                        case PQTRANS_UNKNOWN:
 
1000
                        default:
 
1001
                                OK = false;
 
1002
                                /* PQTRANS_UNKNOWN is expected given a broken connection. */
 
1003
                                if (transaction_status != PQTRANS_UNKNOWN || ConnectionUp())
 
1004
                                        psql_error("unexpected transaction status (%d)\n",
 
1005
                                                           transaction_status);
 
1006
                                break;
 
1007
                }
 
1008
 
 
1009
                if (svptcmd)
 
1010
                {
 
1011
                        PGresult   *svptres;
 
1012
 
 
1013
                        svptres = PQexec(pset.db, svptcmd);
 
1014
                        if (PQresultStatus(svptres) != PGRES_COMMAND_OK)
 
1015
                        {
 
1016
                                psql_error("%s", PQerrorMessage(pset.db));
 
1017
                                PQclear(svptres);
 
1018
                                OK = false;
 
1019
 
 
1020
                                PQclear(results);
 
1021
                                ResetCancelConn();
 
1022
                                goto sendquery_cleanup;
 
1023
                        }
 
1024
                        PQclear(svptres);
 
1025
                }
 
1026
        }
 
1027
 
 
1028
        PQclear(results);
 
1029
 
 
1030
        /* Possible microtiming output */
 
1031
        if (pset.timing)
 
1032
                printf(_("Time: %.3f ms\n"), elapsed_msec);
 
1033
 
 
1034
        /* check for events that may occur during query execution */
 
1035
 
 
1036
        if (pset.encoding != PQclientEncoding(pset.db) &&
 
1037
                PQclientEncoding(pset.db) >= 0)
 
1038
        {
 
1039
                /* track effects of SET CLIENT_ENCODING */
 
1040
                pset.encoding = PQclientEncoding(pset.db);
 
1041
                pset.popt.topt.encoding = pset.encoding;
 
1042
                SetVariable(pset.vars, "ENCODING",
 
1043
                                        pg_encoding_to_char(pset.encoding));
 
1044
        }
 
1045
 
 
1046
        PrintNotifications();
 
1047
 
 
1048
        /* perform cleanup that should occur after any attempted query */
 
1049
 
 
1050
sendquery_cleanup:
 
1051
 
 
1052
        /* reset \g's output-to-filename trigger */
 
1053
        if (pset.gfname)
 
1054
        {
 
1055
                free(pset.gfname);
 
1056
                pset.gfname = NULL;
 
1057
        }
 
1058
 
 
1059
        /* reset \gset trigger */
 
1060
        if (pset.gset_prefix)
 
1061
        {
 
1062
                free(pset.gset_prefix);
 
1063
                pset.gset_prefix = NULL;
 
1064
        }
 
1065
 
 
1066
        return OK;
 
1067
}
 
1068
 
 
1069
 
 
1070
/*
 
1071
 * ExecQueryUsingCursor: run a SELECT-like query using a cursor
 
1072
 *
 
1073
 * This feature allows result sets larger than RAM to be dealt with.
 
1074
 *
 
1075
 * Returns true if the query executed successfully, false otherwise.
 
1076
 *
 
1077
 * If pset.timing is on, total query time (exclusive of result-printing) is
 
1078
 * stored into *elapsed_msec.
 
1079
 */
 
1080
static bool
 
1081
ExecQueryUsingCursor(const char *query, double *elapsed_msec)
 
1082
{
 
1083
        bool            OK = true;
 
1084
        PGresult   *results;
 
1085
        PQExpBufferData buf;
 
1086
        printQueryOpt my_popt = pset.popt;
 
1087
        FILE       *queryFout_copy = pset.queryFout;
 
1088
        bool            queryFoutPipe_copy = pset.queryFoutPipe;
 
1089
        bool            started_txn = false;
 
1090
        bool            did_pager = false;
 
1091
        int                     ntuples;
 
1092
        int                     fetch_count;
 
1093
        char            fetch_cmd[64];
 
1094
        instr_time      before,
 
1095
                                after;
 
1096
        int                     flush_error;
 
1097
 
 
1098
        *elapsed_msec = 0;
 
1099
 
 
1100
        /* initialize print options for partial table output */
 
1101
        my_popt.topt.start_table = true;
 
1102
        my_popt.topt.stop_table = false;
 
1103
        my_popt.topt.prior_records = 0;
 
1104
 
 
1105
        if (pset.timing)
 
1106
                INSTR_TIME_SET_CURRENT(before);
 
1107
 
 
1108
        /* if we're not in a transaction, start one */
 
1109
        if (PQtransactionStatus(pset.db) == PQTRANS_IDLE)
 
1110
        {
 
1111
                results = PQexec(pset.db, "BEGIN");
 
1112
                OK = AcceptResult(results) &&
 
1113
                        (PQresultStatus(results) == PGRES_COMMAND_OK);
 
1114
                PQclear(results);
 
1115
                if (!OK)
 
1116
                        return false;
 
1117
                started_txn = true;
 
1118
        }
 
1119
 
 
1120
        /* Send DECLARE CURSOR */
 
1121
        initPQExpBuffer(&buf);
 
1122
        appendPQExpBuffer(&buf, "DECLARE _psql_cursor NO SCROLL CURSOR FOR\n%s",
 
1123
                                          query);
 
1124
 
 
1125
        results = PQexec(pset.db, buf.data);
 
1126
        OK = AcceptResult(results) &&
 
1127
                (PQresultStatus(results) == PGRES_COMMAND_OK);
 
1128
        PQclear(results);
 
1129
        termPQExpBuffer(&buf);
 
1130
        if (!OK)
 
1131
                goto cleanup;
 
1132
 
 
1133
        if (pset.timing)
 
1134
        {
 
1135
                INSTR_TIME_SET_CURRENT(after);
 
1136
                INSTR_TIME_SUBTRACT(after, before);
 
1137
                *elapsed_msec += INSTR_TIME_GET_MILLISEC(after);
 
1138
        }
 
1139
 
 
1140
        /*
 
1141
         * In \gset mode, we force the fetch count to be 2, so that we will throw
 
1142
         * the appropriate error if the query returns more than one row.
 
1143
         */
 
1144
        if (pset.gset_prefix)
 
1145
                fetch_count = 2;
 
1146
        else
 
1147
                fetch_count = pset.fetch_count;
 
1148
 
 
1149
        snprintf(fetch_cmd, sizeof(fetch_cmd),
 
1150
                         "FETCH FORWARD %d FROM _psql_cursor",
 
1151
                         fetch_count);
 
1152
 
 
1153
        /* prepare to write output to \g argument, if any */
 
1154
        if (pset.gfname)
 
1155
        {
 
1156
                /* keep this code in sync with PrintQueryTuples */
 
1157
                pset.queryFout = stdout;        /* so it doesn't get closed */
 
1158
 
 
1159
                /* open file/pipe */
 
1160
                if (!setQFout(pset.gfname))
 
1161
                {
 
1162
                        pset.queryFout = queryFout_copy;
 
1163
                        pset.queryFoutPipe = queryFoutPipe_copy;
 
1164
                        OK = false;
 
1165
                        goto cleanup;
 
1166
                }
 
1167
        }
 
1168
 
 
1169
        /* clear any pre-existing error indication on the output stream */
 
1170
        clearerr(pset.queryFout);
 
1171
 
 
1172
        for (;;)
 
1173
        {
 
1174
                if (pset.timing)
 
1175
                        INSTR_TIME_SET_CURRENT(before);
 
1176
 
 
1177
                /* get fetch_count tuples at a time */
 
1178
                results = PQexec(pset.db, fetch_cmd);
 
1179
 
 
1180
                if (pset.timing)
 
1181
                {
 
1182
                        INSTR_TIME_SET_CURRENT(after);
 
1183
                        INSTR_TIME_SUBTRACT(after, before);
 
1184
                        *elapsed_msec += INSTR_TIME_GET_MILLISEC(after);
 
1185
                }
 
1186
 
 
1187
                if (PQresultStatus(results) != PGRES_TUPLES_OK)
 
1188
                {
 
1189
                        /* shut down pager before printing error message */
 
1190
                        if (did_pager)
 
1191
                        {
 
1192
                                ClosePager(pset.queryFout);
 
1193
                                pset.queryFout = queryFout_copy;
 
1194
                                pset.queryFoutPipe = queryFoutPipe_copy;
 
1195
                                did_pager = false;
 
1196
                        }
 
1197
 
 
1198
                        OK = AcceptResult(results);
 
1199
                        Assert(!OK);
 
1200
                        PQclear(results);
 
1201
                        break;
 
1202
                }
 
1203
 
 
1204
                if (pset.gset_prefix)
 
1205
                {
 
1206
                        /* StoreQueryTuple will complain if not exactly one row */
 
1207
                        OK = StoreQueryTuple(results);
 
1208
                        PQclear(results);
 
1209
                        break;
 
1210
                }
 
1211
 
 
1212
                ntuples = PQntuples(results);
 
1213
 
 
1214
                if (ntuples < fetch_count)
 
1215
                {
 
1216
                        /* this is the last result set, so allow footer decoration */
 
1217
                        my_popt.topt.stop_table = true;
 
1218
                }
 
1219
                else if (pset.queryFout == stdout && !did_pager)
 
1220
                {
 
1221
                        /*
 
1222
                         * If query requires multiple result sets, hack to ensure that
 
1223
                         * only one pager instance is used for the whole mess
 
1224
                         */
 
1225
                        pset.queryFout = PageOutput(100000, my_popt.topt.pager);
 
1226
                        did_pager = true;
 
1227
                }
 
1228
 
 
1229
                printQuery(results, &my_popt, pset.queryFout, pset.logfile);
 
1230
 
 
1231
                PQclear(results);
 
1232
 
 
1233
                /* after the first result set, disallow header decoration */
 
1234
                my_popt.topt.start_table = false;
 
1235
                my_popt.topt.prior_records += ntuples;
 
1236
 
 
1237
                /*
 
1238
                 * Make sure to flush the output stream, so intermediate results are
 
1239
                 * visible to the client immediately.  We check the results because if
 
1240
                 * the pager dies/exits/etc, there's no sense throwing more data at
 
1241
                 * it.
 
1242
                 */
 
1243
                flush_error = fflush(pset.queryFout);
 
1244
 
 
1245
                /*
 
1246
                 * Check if we are at the end, if a cancel was pressed, or if there
 
1247
                 * were any errors either trying to flush out the results, or more
 
1248
                 * generally on the output stream at all.  If we hit any errors
 
1249
                 * writing things to the stream, we presume $PAGER has disappeared and
 
1250
                 * stop bothering to pull down more data.
 
1251
                 */
 
1252
                if (ntuples < fetch_count || cancel_pressed || flush_error ||
 
1253
                        ferror(pset.queryFout))
 
1254
                        break;
 
1255
        }
 
1256
 
 
1257
        /* close \g argument file/pipe, restore old setting */
 
1258
        if (pset.gfname)
 
1259
        {
 
1260
                /* keep this code in sync with PrintQueryTuples */
 
1261
                setQFout(NULL);
 
1262
 
 
1263
                pset.queryFout = queryFout_copy;
 
1264
                pset.queryFoutPipe = queryFoutPipe_copy;
 
1265
        }
 
1266
        else if (did_pager)
 
1267
        {
 
1268
                ClosePager(pset.queryFout);
 
1269
                pset.queryFout = queryFout_copy;
 
1270
                pset.queryFoutPipe = queryFoutPipe_copy;
 
1271
        }
 
1272
 
 
1273
cleanup:
 
1274
        if (pset.timing)
 
1275
                INSTR_TIME_SET_CURRENT(before);
 
1276
 
 
1277
        /*
 
1278
         * We try to close the cursor on either success or failure, but on failure
 
1279
         * ignore the result (it's probably just a bleat about being in an aborted
 
1280
         * transaction)
 
1281
         */
 
1282
        results = PQexec(pset.db, "CLOSE _psql_cursor");
 
1283
        if (OK)
 
1284
        {
 
1285
                OK = AcceptResult(results) &&
 
1286
                        (PQresultStatus(results) == PGRES_COMMAND_OK);
 
1287
        }
 
1288
        PQclear(results);
 
1289
 
 
1290
        if (started_txn)
 
1291
        {
 
1292
                results = PQexec(pset.db, OK ? "COMMIT" : "ROLLBACK");
 
1293
                OK &= AcceptResult(results) &&
 
1294
                        (PQresultStatus(results) == PGRES_COMMAND_OK);
 
1295
                PQclear(results);
 
1296
        }
 
1297
 
 
1298
        if (pset.timing)
 
1299
        {
 
1300
                INSTR_TIME_SET_CURRENT(after);
 
1301
                INSTR_TIME_SUBTRACT(after, before);
 
1302
                *elapsed_msec += INSTR_TIME_GET_MILLISEC(after);
 
1303
        }
 
1304
 
 
1305
        return OK;
 
1306
}
 
1307
 
 
1308
 
 
1309
/*
 
1310
 * Advance the given char pointer over white space and SQL comments.
 
1311
 */
 
1312
static const char *
 
1313
skip_white_space(const char *query)
 
1314
{
 
1315
        int                     cnestlevel = 0; /* slash-star comment nest level */
 
1316
 
 
1317
        while (*query)
 
1318
        {
 
1319
                int                     mblen = PQmblen(query, pset.encoding);
 
1320
 
 
1321
                /*
 
1322
                 * Note: we assume the encoding is a superset of ASCII, so that for
 
1323
                 * example "query[0] == '/'" is meaningful.  However, we do NOT assume
 
1324
                 * that the second and subsequent bytes of a multibyte character
 
1325
                 * couldn't look like ASCII characters; so it is critical to advance
 
1326
                 * by mblen, not 1, whenever we haven't exactly identified the
 
1327
                 * character we are skipping over.
 
1328
                 */
 
1329
                if (isspace((unsigned char) *query))
 
1330
                        query += mblen;
 
1331
                else if (query[0] == '/' && query[1] == '*')
 
1332
                {
 
1333
                        cnestlevel++;
 
1334
                        query += 2;
 
1335
                }
 
1336
                else if (cnestlevel > 0 && query[0] == '*' && query[1] == '/')
 
1337
                {
 
1338
                        cnestlevel--;
 
1339
                        query += 2;
 
1340
                }
 
1341
                else if (cnestlevel == 0 && query[0] == '-' && query[1] == '-')
 
1342
                {
 
1343
                        query += 2;
 
1344
 
 
1345
                        /*
 
1346
                         * We have to skip to end of line since any slash-star inside the
 
1347
                         * -- comment does NOT start a slash-star comment.
 
1348
                         */
 
1349
                        while (*query)
 
1350
                        {
 
1351
                                if (*query == '\n')
 
1352
                                {
 
1353
                                        query++;
 
1354
                                        break;
 
1355
                                }
 
1356
                                query += PQmblen(query, pset.encoding);
 
1357
                        }
 
1358
                }
 
1359
                else if (cnestlevel > 0)
 
1360
                        query += mblen;
 
1361
                else
 
1362
                        break;                          /* found first token */
 
1363
        }
 
1364
 
 
1365
        return query;
 
1366
}
 
1367
 
 
1368
 
 
1369
/*
 
1370
 * Check whether a command is one of those for which we should NOT start
 
1371
 * a new transaction block (ie, send a preceding BEGIN).
 
1372
 *
 
1373
 * These include the transaction control statements themselves, plus
 
1374
 * certain statements that the backend disallows inside transaction blocks.
 
1375
 */
 
1376
static bool
 
1377
command_no_begin(const char *query)
 
1378
{
 
1379
        int                     wordlen;
 
1380
 
 
1381
        /*
 
1382
         * First we must advance over any whitespace and comments.
 
1383
         */
 
1384
        query = skip_white_space(query);
 
1385
 
 
1386
        /*
 
1387
         * Check word length (since "beginx" is not "begin").
 
1388
         */
 
1389
        wordlen = 0;
 
1390
        while (isalpha((unsigned char) query[wordlen]))
 
1391
                wordlen += PQmblen(&query[wordlen], pset.encoding);
 
1392
 
 
1393
        /*
 
1394
         * Transaction control commands.  These should include every keyword that
 
1395
         * gives rise to a TransactionStmt in the backend grammar, except for the
 
1396
         * savepoint-related commands.
 
1397
         *
 
1398
         * (We assume that START must be START TRANSACTION, since there is
 
1399
         * presently no other "START foo" command.)
 
1400
         */
 
1401
        if (wordlen == 5 && pg_strncasecmp(query, "abort", 5) == 0)
 
1402
                return true;
 
1403
        if (wordlen == 5 && pg_strncasecmp(query, "begin", 5) == 0)
 
1404
                return true;
 
1405
        if (wordlen == 5 && pg_strncasecmp(query, "start", 5) == 0)
 
1406
                return true;
 
1407
        if (wordlen == 6 && pg_strncasecmp(query, "commit", 6) == 0)
 
1408
                return true;
 
1409
        if (wordlen == 3 && pg_strncasecmp(query, "end", 3) == 0)
 
1410
                return true;
 
1411
        if (wordlen == 8 && pg_strncasecmp(query, "rollback", 8) == 0)
 
1412
                return true;
 
1413
        if (wordlen == 7 && pg_strncasecmp(query, "prepare", 7) == 0)
 
1414
        {
 
1415
                /* PREPARE TRANSACTION is a TC command, PREPARE foo is not */
 
1416
                query += wordlen;
 
1417
 
 
1418
                query = skip_white_space(query);
 
1419
 
 
1420
                wordlen = 0;
 
1421
                while (isalpha((unsigned char) query[wordlen]))
 
1422
                        wordlen += PQmblen(&query[wordlen], pset.encoding);
 
1423
 
 
1424
                if (wordlen == 11 && pg_strncasecmp(query, "transaction", 11) == 0)
 
1425
                        return true;
 
1426
                return false;
 
1427
        }
 
1428
 
 
1429
        /*
 
1430
         * Commands not allowed within transactions.  The statements checked for
 
1431
         * here should be exactly those that call PreventTransactionChain() in the
 
1432
         * backend.
 
1433
         */
 
1434
        if (wordlen == 6 && pg_strncasecmp(query, "vacuum", 6) == 0)
 
1435
                return true;
 
1436
        if (wordlen == 7 && pg_strncasecmp(query, "cluster", 7) == 0)
 
1437
        {
 
1438
                /* CLUSTER with any arguments is allowed in transactions */
 
1439
                query += wordlen;
 
1440
 
 
1441
                query = skip_white_space(query);
 
1442
 
 
1443
                if (isalpha((unsigned char) query[0]))
 
1444
                        return false;           /* has additional words */
 
1445
                return true;                    /* it's CLUSTER without arguments */
 
1446
        }
 
1447
 
 
1448
        if (wordlen == 6 && pg_strncasecmp(query, "create", 6) == 0)
 
1449
        {
 
1450
                query += wordlen;
 
1451
 
 
1452
                query = skip_white_space(query);
 
1453
 
 
1454
                wordlen = 0;
 
1455
                while (isalpha((unsigned char) query[wordlen]))
 
1456
                        wordlen += PQmblen(&query[wordlen], pset.encoding);
 
1457
 
 
1458
                if (wordlen == 8 && pg_strncasecmp(query, "database", 8) == 0)
 
1459
                        return true;
 
1460
                if (wordlen == 10 && pg_strncasecmp(query, "tablespace", 10) == 0)
 
1461
                        return true;
 
1462
 
 
1463
                /* CREATE [UNIQUE] INDEX CONCURRENTLY isn't allowed in xacts */
 
1464
                if (wordlen == 6 && pg_strncasecmp(query, "unique", 6) == 0)
 
1465
                {
 
1466
                        query += wordlen;
 
1467
 
 
1468
                        query = skip_white_space(query);
 
1469
 
 
1470
                        wordlen = 0;
 
1471
                        while (isalpha((unsigned char) query[wordlen]))
 
1472
                                wordlen += PQmblen(&query[wordlen], pset.encoding);
 
1473
                }
 
1474
 
 
1475
                if (wordlen == 5 && pg_strncasecmp(query, "index", 5) == 0)
 
1476
                {
 
1477
                        query += wordlen;
 
1478
 
 
1479
                        query = skip_white_space(query);
 
1480
 
 
1481
                        wordlen = 0;
 
1482
                        while (isalpha((unsigned char) query[wordlen]))
 
1483
                                wordlen += PQmblen(&query[wordlen], pset.encoding);
 
1484
 
 
1485
                        if (wordlen == 12 && pg_strncasecmp(query, "concurrently", 12) == 0)
 
1486
                                return true;
 
1487
                }
 
1488
 
 
1489
                return false;
 
1490
        }
 
1491
 
 
1492
        /*
 
1493
         * Note: these tests will match DROP SYSTEM and REINDEX TABLESPACE, which
 
1494
         * aren't really valid commands so we don't care much. The other four
 
1495
         * possible matches are correct.
 
1496
         */
 
1497
        if ((wordlen == 4 && pg_strncasecmp(query, "drop", 4) == 0) ||
 
1498
                (wordlen == 7 && pg_strncasecmp(query, "reindex", 7) == 0))
 
1499
        {
 
1500
                query += wordlen;
 
1501
 
 
1502
                query = skip_white_space(query);
 
1503
 
 
1504
                wordlen = 0;
 
1505
                while (isalpha((unsigned char) query[wordlen]))
 
1506
                        wordlen += PQmblen(&query[wordlen], pset.encoding);
 
1507
 
 
1508
                if (wordlen == 8 && pg_strncasecmp(query, "database", 8) == 0)
 
1509
                        return true;
 
1510
                if (wordlen == 6 && pg_strncasecmp(query, "system", 6) == 0)
 
1511
                        return true;
 
1512
                if (wordlen == 10 && pg_strncasecmp(query, "tablespace", 10) == 0)
 
1513
                        return true;
 
1514
                return false;
 
1515
        }
 
1516
 
 
1517
        /* DISCARD ALL isn't allowed in xacts, but other variants are allowed. */
 
1518
        if (wordlen == 7 && pg_strncasecmp(query, "discard", 7) == 0)
 
1519
        {
 
1520
                query += wordlen;
 
1521
 
 
1522
                query = skip_white_space(query);
 
1523
 
 
1524
                wordlen = 0;
 
1525
                while (isalpha((unsigned char) query[wordlen]))
 
1526
                        wordlen += PQmblen(&query[wordlen], pset.encoding);
 
1527
 
 
1528
                if (wordlen == 3 && pg_strncasecmp(query, "all", 3) == 0)
 
1529
                        return true;
 
1530
                return false;
 
1531
        }
 
1532
 
 
1533
        return false;
 
1534
}
 
1535
 
 
1536
 
 
1537
/*
 
1538
 * Check whether the specified command is a SELECT (or VALUES).
 
1539
 */
 
1540
static bool
 
1541
is_select_command(const char *query)
 
1542
{
 
1543
        int                     wordlen;
 
1544
 
 
1545
        /*
 
1546
         * First advance over any whitespace, comments and left parentheses.
 
1547
         */
 
1548
        for (;;)
 
1549
        {
 
1550
                query = skip_white_space(query);
 
1551
                if (query[0] == '(')
 
1552
                        query++;
 
1553
                else
 
1554
                        break;
 
1555
        }
 
1556
 
 
1557
        /*
 
1558
         * Check word length (since "selectx" is not "select").
 
1559
         */
 
1560
        wordlen = 0;
 
1561
        while (isalpha((unsigned char) query[wordlen]))
 
1562
                wordlen += PQmblen(&query[wordlen], pset.encoding);
 
1563
 
 
1564
        if (wordlen == 6 && pg_strncasecmp(query, "select", 6) == 0)
 
1565
                return true;
 
1566
 
 
1567
        if (wordlen == 6 && pg_strncasecmp(query, "values", 6) == 0)
 
1568
                return true;
 
1569
 
 
1570
        return false;
 
1571
}
 
1572
 
 
1573
 
 
1574
/*
 
1575
 * Test if the current user is a database superuser.
 
1576
 *
 
1577
 * Note: this will correctly detect superuserness only with a protocol-3.0
 
1578
 * or newer backend; otherwise it will always say "false".
 
1579
 */
 
1580
bool
 
1581
is_superuser(void)
 
1582
{
 
1583
        const char *val;
 
1584
 
 
1585
        if (!pset.db)
 
1586
                return false;
 
1587
 
 
1588
        val = PQparameterStatus(pset.db, "is_superuser");
 
1589
 
 
1590
        if (val && strcmp(val, "on") == 0)
 
1591
                return true;
 
1592
 
 
1593
        return false;
 
1594
}
 
1595
 
 
1596
 
 
1597
/*
 
1598
 * Test if the current session uses standard string literals.
 
1599
 *
 
1600
 * Note: With a pre-protocol-3.0 connection this will always say "false",
 
1601
 * which should be the right answer.
 
1602
 */
 
1603
bool
 
1604
standard_strings(void)
 
1605
{
 
1606
        const char *val;
 
1607
 
 
1608
        if (!pset.db)
 
1609
                return false;
 
1610
 
 
1611
        val = PQparameterStatus(pset.db, "standard_conforming_strings");
 
1612
 
 
1613
        if (val && strcmp(val, "on") == 0)
 
1614
                return true;
 
1615
 
 
1616
        return false;
 
1617
}
 
1618
 
 
1619
 
 
1620
/*
 
1621
 * Return the session user of the current connection.
 
1622
 *
 
1623
 * Note: this will correctly detect the session user only with a
 
1624
 * protocol-3.0 or newer backend; otherwise it will return the
 
1625
 * connection user.
 
1626
 */
 
1627
const char *
 
1628
session_username(void)
 
1629
{
 
1630
        const char *val;
 
1631
 
 
1632
        if (!pset.db)
 
1633
                return NULL;
 
1634
 
 
1635
        val = PQparameterStatus(pset.db, "session_authorization");
 
1636
        if (val)
 
1637
                return val;
 
1638
        else
 
1639
                return PQuser(pset.db);
 
1640
}
 
1641
 
 
1642
 
 
1643
/* expand_tilde
 
1644
 *
 
1645
 * substitute '~' with HOME or '~username' with username's home dir
 
1646
 *
 
1647
 */
 
1648
void
 
1649
expand_tilde(char **filename)
 
1650
{
 
1651
        if (!filename || !(*filename))
 
1652
                return;
 
1653
 
 
1654
        /*
 
1655
         * WIN32 doesn't use tilde expansion for file names. Also, it uses tilde
 
1656
         * for short versions of long file names, though the tilde is usually
 
1657
         * toward the end, not at the beginning.
 
1658
         */
 
1659
#ifndef WIN32
 
1660
 
 
1661
        /* try tilde expansion */
 
1662
        if (**filename == '~')
 
1663
        {
 
1664
                char       *fn;
 
1665
                char            oldp,
 
1666
                                   *p;
 
1667
                struct passwd *pw;
 
1668
                char            home[MAXPGPATH];
 
1669
 
 
1670
                fn = *filename;
 
1671
                *home = '\0';
 
1672
 
 
1673
                p = fn + 1;
 
1674
                while (*p != '/' && *p != '\0')
 
1675
                        p++;
 
1676
 
 
1677
                oldp = *p;
 
1678
                *p = '\0';
 
1679
 
 
1680
                if (*(fn + 1) == '\0')
 
1681
                        get_home_path(home);    /* ~ or ~/ only */
 
1682
                else if ((pw = getpwnam(fn + 1)) != NULL)
 
1683
                        strlcpy(home, pw->pw_dir, sizeof(home));        /* ~user */
 
1684
 
 
1685
                *p = oldp;
 
1686
                if (strlen(home) != 0)
 
1687
                {
 
1688
                        char       *newfn;
 
1689
 
 
1690
                        newfn = pg_malloc(strlen(home) + strlen(p) + 1);
 
1691
                        strcpy(newfn, home);
 
1692
                        strcat(newfn, p);
 
1693
 
 
1694
                        free(fn);
 
1695
                        *filename = newfn;
 
1696
                }
 
1697
        }
 
1698
#endif
 
1699
 
 
1700
        return;
 
1701
}