LCOV - differential code coverage report
Current view: top level - src/bin/pg_dump - pg_backup_db.c (source / functions) Coverage Total Hit UNC LBC UIC UBC GBC GIC GNC CBC EUB ECB DUB
Current: Differential Code Coverage HEAD vs 15 Lines: 79.4 % 209 166 1 1 19 22 9 69 1 87 10 78 2
Current Date: 2023-04-08 17:13:01 Functions: 94.1 % 17 16 1 12 2 2 1 13
Baseline: 15 Line coverage date bins:
Baseline Date: 2023-04-08 15:09:40 (120,180] days: 100.0 % 1 1 1
Legend: Lines: hit not hit (240..) days: 79.3 % 208 165 1 1 19 22 9 69 87 10 78
Function coverage date bins:
(120,180] days: 100.0 % 1 1 1
(240..) days: 50.0 % 30 15 1 12 1 2 1 13

 Age         Owner                  TLA  Line data    Source code
                                  1                 : /*-------------------------------------------------------------------------
                                  2                 :  *
                                  3                 :  * pg_backup_db.c
                                  4                 :  *
                                  5                 :  *  Implements the basic DB functions used by the archiver.
                                  6                 :  *
                                  7                 :  * IDENTIFICATION
                                  8                 :  *    src/bin/pg_dump/pg_backup_db.c
                                  9                 :  *
                                 10                 :  *-------------------------------------------------------------------------
                                 11                 :  */
                                 12                 : #include "postgres_fe.h"
                                 13                 : 
                                 14                 : #include <unistd.h>
                                 15                 : #include <ctype.h>
                                 16                 : #ifdef HAVE_TERMIOS_H
                                 17                 : #include <termios.h>
                                 18                 : #endif
                                 19                 : 
                                 20                 : #include "common/connect.h"
                                 21                 : #include "common/string.h"
                                 22                 : #include "dumputils.h"
                                 23                 : #include "fe_utils/string_utils.h"
                                 24                 : #include "parallel.h"
                                 25                 : #include "pg_backup_archiver.h"
                                 26                 : #include "pg_backup_db.h"
                                 27                 : #include "pg_backup_utils.h"
                                 28                 : 
                                 29                 : static void _check_database_version(ArchiveHandle *AH);
                                 30                 : static void notice_processor(void *arg, const char *message);
                                 31                 : 
                                 32                 : static void
 5474 tgl                        33 CBC         186 : _check_database_version(ArchiveHandle *AH)
                                 34                 : {
                                 35                 :     const char *remoteversion_str;
                                 36                 :     int         remoteversion;
                                 37                 :     PGresult   *res;
                                 38                 : 
 7231                            39             186 :     remoteversion_str = PQparameterStatus(AH->connection, "server_version");
 3666 heikki.linnakangas         40             186 :     remoteversion = PQserverVersion(AH->connection);
                                 41             186 :     if (remoteversion == 0 || !remoteversion_str)
  366 tgl                        42 UBC           0 :         pg_fatal("could not get server_version from libpq");
                                 43                 : 
 4153 bruce                      44 CBC         186 :     AH->public.remoteVersionStr = pg_strdup(remoteversion_str);
 8019 pjw                        45             186 :     AH->public.remoteVersion = remoteversion;
 4792 tgl                        46             186 :     if (!AH->archiveRemoteVersion)
                                 47             131 :         AH->archiveRemoteVersion = AH->public.remoteVersionStr;
                                 48                 : 
 3666 heikki.linnakangas         49             186 :     if (remoteversion != PG_VERSION_NUM
 7231 tgl                        50 UBC           0 :         && (remoteversion < AH->public.minRemoteVersion ||
                                 51               0 :             remoteversion > AH->public.maxRemoteVersion))
                                 52                 :     {
  366                            53               0 :         pg_log_error("aborting because of server version mismatch");
                                 54               0 :         pg_log_error_detail("server version: %s; %s version: %s",
                                 55                 :                             remoteversion_str, progname, PG_VERSION);
                                 56               0 :         exit(1);
                                 57                 :     }
                                 58                 : 
                                 59                 :     /*
                                 60                 :      * Check if server is in recovery mode, which means we are on a hot
                                 61                 :      * standby.
                                 62                 :      */
  479 tgl                        63 CBC         186 :     res = ExecuteSqlQueryForSingleRow((Archive *) AH,
                                 64                 :                                       "SELECT pg_catalog.pg_is_in_recovery()");
                                 65             186 :     AH->public.isStandby = (strcmp(PQgetvalue(res, 0, 0), "t") == 0);
                                 66             186 :     PQclear(res);
 8297 pjw                        67             186 : }
                                 68                 : 
                                 69                 : /*
                                 70                 :  * Reconnect to the server.  If dbname is not NULL, use that database,
                                 71                 :  * else the one associated with the archive handle.
                                 72                 :  */
                                 73                 : void
  927 tgl                        74              13 : ReconnectToServer(ArchiveHandle *AH, const char *dbname)
                                 75                 : {
                                 76              13 :     PGconn     *oldConn = AH->connection;
                                 77              13 :     RestoreOptions *ropt = AH->public.ropt;
                                 78                 : 
                                 79                 :     /*
                                 80                 :      * Save the dbname, if given, in override_dbname so that it will also
                                 81                 :      * affect any later reconnection attempt.
                                 82                 :      */
                                 83              13 :     if (dbname)
                                 84              13 :         ropt->cparams.override_dbname = pg_strdup(dbname);
                                 85                 : 
                                 86                 :     /*
                                 87                 :      * Note: we want to establish the new connection, and in particular update
                                 88                 :      * ArchiveHandle's connCancel, before closing old connection.  Otherwise
                                 89                 :      * an ill-timed SIGINT could try to access a dead connection.
                                 90                 :      */
                                 91              13 :     AH->connection = NULL;       /* dodge error check in ConnectDatabase */
                                 92                 : 
                                 93              13 :     ConnectDatabase((Archive *) AH, &ropt->cparams, true);
                                 94                 : 
                                 95              13 :     PQfinish(oldConn);
 8294 pjw                        96              13 : }
                                 97                 : 
                                 98                 : /*
                                 99                 :  * Make, or remake, a database connection with the given parameters.
                                100                 :  *
                                101                 :  * The resulting connection handle is stored in AHX->connection.
                                102                 :  *
                                103                 :  * An interactive password prompt is automatically issued if required.
                                104                 :  * We store the results of that in AHX->savedPassword.
                                105                 :  * Note: it's not really all that sensible to use a single-entry password
                                106                 :  * cache if the username keeps changing.  In current usage, however, the
                                107                 :  * username never does change, so one savedPassword is sufficient.
                                108                 :  */
                                109                 : void
 8053 bruce                     110             187 : ConnectDatabase(Archive *AHX,
                                111                 :                 const ConnParams *cparams,
                                112                 :                 bool isReconnect)
                                113                 : {
                                114             187 :     ArchiveHandle *AH = (ArchiveHandle *) AHX;
                                115                 :     trivalue    prompt_password;
                                116                 :     char       *password;
                                117                 :     bool        new_pass;
                                118                 : 
 8297 pjw                       119             187 :     if (AH->connection)
  366 tgl                       120 UBC           0 :         pg_fatal("already connected to a database");
                                121                 : 
                                122                 :     /* Never prompt for a password during a reconnection */
  927 tgl                       123 CBC         187 :     prompt_password = isReconnect ? TRI_NO : cparams->promptPassword;
                                124                 : 
 2413                           125             187 :     password = AH->savedPassword;
                                126                 : 
 5155 peter_e                   127             187 :     if (prompt_password == TRI_YES && password == NULL)
  948 tgl                       128 UBC           0 :         password = simple_prompt("Password: ", false);
                                129                 : 
                                130                 :     /*
                                131                 :      * Start the connection.  Loop until we have a password if requested by
                                132                 :      * backend.
                                133                 :      */
                                134                 :     do
                                135                 :     {
                                136                 :         const char *keywords[8];
                                137                 :         const char *values[8];
  927 tgl                       138 CBC         187 :         int         i = 0;
                                139                 : 
                                140                 :         /*
                                141                 :          * If dbname is a connstring, its entries can override the other
                                142                 :          * values obtained from cparams; but in turn, override_dbname can
                                143                 :          * override the dbname component of it.
                                144                 :          */
                                145             187 :         keywords[i] = "host";
                                146             187 :         values[i++] = cparams->pghost;
                                147             187 :         keywords[i] = "port";
                                148             187 :         values[i++] = cparams->pgport;
                                149             187 :         keywords[i] = "user";
                                150             187 :         values[i++] = cparams->username;
                                151             187 :         keywords[i] = "password";
                                152             187 :         values[i++] = password;
                                153             187 :         keywords[i] = "dbname";
                                154             187 :         values[i++] = cparams->dbname;
                                155             187 :         if (cparams->override_dbname)
                                156                 :         {
                                157              16 :             keywords[i] = "dbname";
                                158              16 :             values[i++] = cparams->override_dbname;
                                159                 :         }
                                160             187 :         keywords[i] = "fallback_application_name";
                                161             187 :         values[i++] = progname;
                                162             187 :         keywords[i] = NULL;
                                163             187 :         values[i++] = NULL;
                                164             187 :         Assert(i <= lengthof(keywords));
                                165                 : 
 5754                           166             187 :         new_pass = false;
 4811 mail                      167             187 :         AH->connection = PQconnectdbParams(keywords, values, true);
                                168                 : 
 7997 peter_e                   169             187 :         if (!AH->connection)
  366 tgl                       170 UBC           0 :             pg_fatal("could not connect to database");
                                171                 : 
 7997 peter_e                   172 CBC         188 :         if (PQstatus(AH->connection) == CONNECTION_BAD &&
 5600 tgl                       173               1 :             PQconnectionNeedsPassword(AH->connection) &&
 5155 peter_e                   174 UBC           0 :             password == NULL &&
                                175                 :             prompt_password != TRI_NO)
                                176                 :         {
 7997                           177               0 :             PQfinish(AH->connection);
  948 tgl                       178               0 :             password = simple_prompt("Password: ", false);
 5754                           179               0 :             new_pass = true;
                                180                 :         }
 5754 tgl                       181 CBC         187 :     } while (new_pass);
                                182                 : 
                                183                 :     /* check to see that the backend connection was successfully made */
 8297 pjw                       184             187 :     if (PQstatus(AH->connection) == CONNECTION_BAD)
                                185                 :     {
  927 tgl                       186               1 :         if (isReconnect)
  366 tgl                       187 UBC           0 :             pg_fatal("reconnection failed: %s",
                                188                 :                      PQerrorMessage(AH->connection));
                                189                 :         else
  366 tgl                       190 CBC           1 :             pg_fatal("%s",
                                191                 :                      PQerrorMessage(AH->connection));
                                192                 :     }
                                193                 : 
                                194                 :     /* Start strict; later phases may override this. */
 1868 noah                      195             186 :     PQclear(ExecuteSqlQueryForSingleRow((Archive *) AH,
                                196                 :                                         ALWAYS_SECURE_SEARCH_PATH_SQL));
                                197                 : 
  948 tgl                       198             186 :     if (password && password != AH->savedPassword)
  948 tgl                       199 UBC           0 :         free(password);
                                200                 : 
                                201                 :     /*
                                202                 :      * We want to remember connection's actual password, whether or not we got
                                203                 :      * it by prompting.  So we don't just store the password variable.
                                204                 :      */
 2664 tgl                       205 CBC         186 :     if (PQconnectionUsedPassword(AH->connection))
                                206                 :     {
  297 peter                     207 UNC           0 :         free(AH->savedPassword);
 2664 tgl                       208 UIC           0 :         AH->savedPassword = pg_strdup(PQpass(AH->connection));
                                209                 :     }
                                210                 : 
 8297 pjw                       211 ECB             :     /* check for version mismatch */
 5474 tgl                       212 GIC         186 :     _check_database_version(AH);
 8297 pjw                       213 ECB             : 
 7910 peter_e                   214 GIC         186 :     PQsetNoticeProcessor(AH->connection, notice_processor, NULL);
                                215                 : 
 2502 tgl                       216 ECB             :     /* arrange for SIGINT to issue a query cancel on this connection */
 2502 tgl                       217 CBC         186 :     set_archive_cancel_info(AH, AH->connection);
 8297 pjw                       218 GIC         186 : }
                                219                 : 
                                220                 : /*
                                221                 :  * Close the connection to the database and also cancel off the query if we
                                222                 :  * have one running.
                                223                 :  */
 4070 rhaas                     224 ECB             : void
 4070 rhaas                     225 GIC         172 : DisconnectDatabase(Archive *AHX)
 4070 rhaas                     226 ECB             : {
 4070 rhaas                     227 GIC         172 :     ArchiveHandle *AH = (ArchiveHandle *) AHX;
                                228                 :     char        errbuf[1];
 3668 andrew                    229 ECB             : 
 3668 andrew                    230 GBC         172 :     if (!AH->connection)
 3668 andrew                    231 UIC           0 :         return;
 4070 rhaas                     232 ECB             : 
 2502 tgl                       233 GIC         172 :     if (AH->connCancel)
                                234                 :     {
                                235                 :         /*
                                236                 :          * If we have an active query, send a cancel before closing, ignoring
                                237                 :          * any errors.  This is of no use for a normal exit, but might be
                                238                 :          * helpful during pg_fatal().
 2502 tgl                       239 ECB             :          */
 2502 tgl                       240 GBC         171 :         if (PQtransactionStatus(AH->connection) == PQTRANS_ACTIVE)
 2161 alvherre                  241 UIC           0 :             (void) PQcancel(AH->connCancel, errbuf, sizeof(errbuf));
                                242                 : 
                                243                 :         /*
                                244                 :          * Prevent signal handler from sending a cancel after this.
 2502 tgl                       245 ECB             :          */
 2502 tgl                       246 GIC         171 :         set_archive_cancel_info(AH, NULL);
                                247                 :     }
 3668 andrew                    248 ECB             : 
 3668 andrew                    249 CBC         172 :     PQfinish(AH->connection);
 4070 rhaas                     250 GIC         172 :     AH->connection = NULL;
                                251                 : }
                                252                 : 
 4070 rhaas                     253 ECB             : PGconn *
 4070 rhaas                     254 GIC        3311 : GetConnection(Archive *AHX)
 4070 rhaas                     255 ECB             : {
 4070 rhaas                     256 GIC        3311 :     ArchiveHandle *AH = (ArchiveHandle *) AHX;
 4070 rhaas                     257 ECB             : 
 4070 rhaas                     258 GIC        3311 :     return AH->connection;
                                259                 : }
                                260                 : 
 7836 bruce                     261 EUB             : static void
 7836 bruce                     262 UIC           0 : notice_processor(void *arg, const char *message)
 7910 peter_e                   263 EUB             : {
  366 tgl                       264 UBC           0 :     pg_log_info("%s", message);
 7910 peter_e                   265 UIC           0 : }
                                266                 : 
                                267                 : /* Like pg_fatal(), but with a complaint about a particular query. */
 4037 alvherre                  268 ECB             : static void
 1469 peter                     269 GIC           2 : die_on_query_failure(ArchiveHandle *AH, const char *query)
 4037 alvherre                  270 ECB             : {
 1469 peter                     271 GIC           2 :     pg_log_error("query failed: %s",
 1418 tgl                       272 ECB             :                  PQerrorMessage(AH->connection));
  366 tgl                       273 CBC           2 :     pg_log_error_detail("Query was: %s", query);
  366 tgl                       274 GIC           2 :     exit(1);
                                275                 : }
                                276                 : 
 4079 rhaas                     277 ECB             : void
 4079 rhaas                     278 GIC        2338 : ExecuteSqlStatement(Archive *AHX, const char *query)
 4079 rhaas                     279 ECB             : {
 3955 bruce                     280 GIC        2338 :     ArchiveHandle *AH = (ArchiveHandle *) AHX;
                                281                 :     PGresult   *res;
 4079 rhaas                     282 ECB             : 
 4079 rhaas                     283 CBC        2338 :     res = PQexec(AH->connection, query);
                                284            2338 :     if (PQresultStatus(res) != PGRES_COMMAND_OK)
 1469 peter                     285               1 :         die_on_query_failure(AH, query);
 4079 rhaas                     286            2337 :     PQclear(res);
 4079 rhaas                     287 GIC        2337 : }
                                288                 : 
 4079 rhaas                     289 ECB             : PGresult *
 4079 rhaas                     290 GIC       19417 : ExecuteSqlQuery(Archive *AHX, const char *query, ExecStatusType status)
 4079 rhaas                     291 ECB             : {
 3955 bruce                     292 GIC       19417 :     ArchiveHandle *AH = (ArchiveHandle *) AHX;
                                293                 :     PGresult   *res;
 4079 rhaas                     294 ECB             : 
 4079 rhaas                     295 CBC       19417 :     res = PQexec(AH->connection, query);
                                296           19417 :     if (PQresultStatus(res) != status)
 1469 peter                     297               1 :         die_on_query_failure(AH, query);
 4079 rhaas                     298 GIC       19416 :     return res;
                                299                 : }
                                300                 : 
                                301                 : /*
                                302                 :  * Execute an SQL query and verify that we got exactly one row back.
                                303                 :  */
 2509 magnus                    304 ECB             : PGresult *
 1986 peter_e                   305 GIC        7913 : ExecuteSqlQueryForSingleRow(Archive *fout, const char *query)
                                306                 : {
                                307                 :     PGresult   *res;
                                308                 :     int         ntups;
 2509 magnus                    309 ECB             : 
 2509 magnus                    310 GIC        7913 :     res = ExecuteSqlQuery(fout, query, PGRES_TUPLES_OK);
                                311                 : 
 2509 magnus                    312 ECB             :     /* Expecting a single result only */
 2509 magnus                    313 CBC        7913 :     ntups = PQntuples(res);
 2509 magnus                    314 GBC        7913 :     if (ntups != 1)
  366 tgl                       315 UIC           0 :         pg_fatal(ngettext("query returned %d row instead of one: %s",
                                316                 :                           "query returned %d rows instead of one: %s",
                                317                 :                           ntups),
                                318                 :                  ntups, query);
 2509 magnus                    319 ECB             : 
 2509 magnus                    320 GIC        7913 :     return res;
                                321                 : }
                                322                 : 
                                323                 : /*
                                324                 :  * Convenience function to send a query.
                                325                 :  * Monitors result to detect COPY statements
                                326                 :  */
 5349 tgl                       327 ECB             : static void
 5349 tgl                       328 GIC        6576 : ExecuteSqlCommand(ArchiveHandle *AH, const char *qry, const char *desc)
 8297 pjw                       329 ECB             : {
 6501 tgl                       330 GIC        6576 :     PGconn     *conn = AH->connection;
                                331                 :     PGresult   *res;
                                332                 : 
                                333                 : #ifdef NOT_USED
                                334                 :     fprintf(stderr, "Executing: '%s'\n\n", qry);
 5349 tgl                       335 ECB             : #endif
 5349 tgl                       336 GIC        6576 :     res = PQexec(conn, qry);
 8297 pjw                       337 ECB             : 
 5349 tgl                       338 GIC        6576 :     switch (PQresultStatus(res))
 8297 pjw                       339 ECB             :     {
 5349 tgl                       340 GIC        6567 :         case PGRES_COMMAND_OK:
                                341                 :         case PGRES_TUPLES_OK:
                                342                 :         case PGRES_EMPTY_QUERY:
 5349 tgl                       343 ECB             :             /* A-OK */
 5349 tgl                       344 CBC        6567 :             break;
 5349 tgl                       345 GIC           9 :         case PGRES_COPY_IN:
 5349 tgl                       346 ECB             :             /* Assume this is an expected result */
 6272 tgl                       347 CBC           9 :             AH->pgCopyIn = true;
 5349 tgl                       348 GBC           9 :             break;
 5349 tgl                       349 UIC           0 :         default:
 5349 tgl                       350 EUB             :             /* trouble */
 1469 peter                     351 UIC           0 :             warn_or_exit_horribly(AH, "%s: %sCommand was: %s",
 2202 peter_e                   352 EUB             :                                   desc, PQerrorMessage(conn), qry);
 5349 tgl                       353 UIC           0 :             break;
                                354                 :     }
 8297 pjw                       355 ECB             : 
 8297 pjw                       356 CBC        6576 :     PQclear(res);
 8297 pjw                       357 GIC        6576 : }
                                358                 : 
                                359                 : 
                                360                 : /*
                                361                 :  * Process non-COPY table data (that is, INSERT commands).
                                362                 :  *
                                363                 :  * The commands have been run together as one long string for compressibility,
                                364                 :  * and we are receiving them in bufferloads with arbitrary boundaries, so we
                                365                 :  * have to locate command boundaries and save partial commands across calls.
                                366                 :  * All state must be kept in AH->sqlparse, not in local variables of this
                                367                 :  * routine.  We assume that AH->sqlparse was filled with zeroes when created.
                                368                 :  *
                                369                 :  * We have to lex the data to the extent of identifying literals and quoted
                                370                 :  * identifiers, so that we can recognize statement-terminating semicolons.
                                371                 :  * We assume that INSERT data will not contain SQL comments, E'' literals,
                                372                 :  * or dollar-quoted strings, so this is much simpler than a full SQL lexer.
                                373                 :  *
                                374                 :  * Note: when restoring from a pre-9.0 dump file, this code is also used to
                                375                 :  * process BLOB COMMENTS data, which has the same problem of containing
                                376                 :  * multiple SQL commands that might be split across bufferloads.  Fortunately,
                                377                 :  * that data won't contain anything complicated to lex either.
                                378                 :  */
 4111 tgl                       379 ECB             : static void
 3223 tgl                       380 GIC          37 : ExecuteSimpleCommands(ArchiveHandle *AH, const char *buf, size_t bufLen)
 4111 tgl                       381 ECB             : {
 4111 tgl                       382 CBC          37 :     const char *qry = buf;
 4111 tgl                       383 GIC          37 :     const char *eos = buf + bufLen;
                                384                 : 
 4111 tgl                       385 ECB             :     /* initialize command buffer if first time through */
 4111 tgl                       386 CBC          37 :     if (AH->sqlparse.curCmd == NULL)
 4111 tgl                       387 GIC           3 :         AH->sqlparse.curCmd = createPQExpBuffer();
 4111 tgl                       388 ECB             : 
 4111 tgl                       389 GIC      129730 :     for (; qry < eos; qry++)
 4111 tgl                       390 ECB             :     {
 3955 bruce                     391 GIC      129693 :         char        ch = *qry;
                                392                 : 
 4111 tgl                       393 ECB             :         /* For neatness, we skip any newlines between commands */
 4111 tgl                       394 CBC      129693 :         if (!(ch == '\n' && AH->sqlparse.curCmd->len == 0))
 4111 tgl                       395 GIC      126679 :             appendPQExpBufferChar(AH->sqlparse.curCmd, ch);
 4111 tgl                       396 ECB             : 
 4111 tgl                       397 GIC      129693 :         switch (AH->sqlparse.state)
 4111 tgl                       398 ECB             :         {
 4111 tgl                       399 CBC      125693 :             case SQL_SCAN:      /* Default state == 0, set in _allocAH */
 4111 tgl                       400 GIC      125693 :                 if (ch == ';')
                                401                 :                 {
                                402                 :                     /*
                                403                 :                      * We've found the end of a statement. Send it and reset
                                404                 :                      * the buffer.
 4111 tgl                       405 ECB             :                      */
 4111 tgl                       406 GIC        3000 :                     ExecuteSqlCommand(AH, AH->sqlparse.curCmd->data,
 4111 tgl                       407 ECB             :                                       "could not execute query");
 4111 tgl                       408 GIC        3000 :                     resetPQExpBuffer(AH->sqlparse.curCmd);
 4111 tgl                       409 ECB             :                 }
 4111 tgl                       410 GIC      122693 :                 else if (ch == '\'')
 4111 tgl                       411 ECB             :                 {
 4111 tgl                       412 CBC        2000 :                     AH->sqlparse.state = SQL_IN_SINGLE_QUOTE;
 4111 tgl                       413 GIC        2000 :                     AH->sqlparse.backSlash = false;
 4111 tgl                       414 ECB             :                 }
 4111 tgl                       415 GIC      120693 :                 else if (ch == '"')
 4111 tgl                       416 EUB             :                 {
 4111 tgl                       417 UIC           0 :                     AH->sqlparse.state = SQL_IN_DOUBLE_QUOTE;
 4111 tgl                       418 ECB             :                 }
 4111 tgl                       419 GIC      125693 :                 break;
 4111 tgl                       420 ECB             : 
 4111 tgl                       421 GIC        4000 :             case SQL_IN_SINGLE_QUOTE:
 4111 tgl                       422 ECB             :                 /* We needn't handle '' specially */
 4111 tgl                       423 CBC        4000 :                 if (ch == '\'' && !AH->sqlparse.backSlash)
                                424            2000 :                     AH->sqlparse.state = SQL_SCAN;
 4111 tgl                       425 GBC        2000 :                 else if (ch == '\\' && !AH->public.std_strings)
 4111 tgl                       426 UIC           0 :                     AH->sqlparse.backSlash = !AH->sqlparse.backSlash;
 4111 tgl                       427 ECB             :                 else
 4111 tgl                       428 CBC        2000 :                     AH->sqlparse.backSlash = false;
 4111 tgl                       429 GIC        4000 :                 break;
 4111 tgl                       430 EUB             : 
 4111 tgl                       431 UIC           0 :             case SQL_IN_DOUBLE_QUOTE:
 4111 tgl                       432 EUB             :                 /* We needn't handle "" specially */
 4111 tgl                       433 UBC           0 :                 if (ch == '"')
                                434               0 :                     AH->sqlparse.state = SQL_SCAN;
 4111 tgl                       435 UIC           0 :                 break;
                                436                 :         }
 4111 tgl                       437 ECB             :     }
 4111 tgl                       438 GIC          37 : }
                                439                 : 
                                440                 : 
                                441                 : /*
                                442                 :  * Implement ahwrite() for direct-to-DB restore
                                443                 :  */
 4273 tgl                       444 ECB             : int
 3099 alvherre                  445 GIC        3603 : ExecuteSqlCommandBuf(Archive *AHX, const char *buf, size_t bufLen)
 8297 pjw                       446 ECB             : {
 3099 alvherre                  447 GIC        3603 :     ArchiveHandle *AH = (ArchiveHandle *) AHX;
 3099 alvherre                  448 ECB             : 
 4111 tgl                       449 GIC        3603 :     if (AH->outputKind == OUTPUT_COPYDATA)
                                450                 :     {
                                451                 :         /*
                                452                 :          * COPY data.
                                453                 :          *
                                454                 :          * We drop the data on the floor if libpq has failed to enter COPY
                                455                 :          * mode; this allows us to behave reasonably when trying to continue
                                456                 :          * after an error in a COPY command.
 7751 tgl                       457 ECB             :          */
 4273 tgl                       458 CBC          20 :         if (AH->pgCopyIn &&
 4273 tgl                       459 GBC          10 :             PQputCopyData(AH->connection, buf, bufLen) <= 0)
  366 tgl                       460 UIC           0 :             pg_fatal("error returned by PQputCopyData: %s",
                                461                 :                      PQerrorMessage(AH->connection));
 4273 tgl                       462 ECB             :     }
 4111 tgl                       463 GIC        3593 :     else if (AH->outputKind == OUTPUT_OTHERDATA)
                                464                 :     {
                                465                 :         /*
                                466                 :          * Table data expressed as INSERT commands; or, in old dump files,
                                467                 :          * BLOB COMMENTS data (which is expressed as COMMENT ON commands).
 4111 tgl                       468 ECB             :          */
 3223 tgl                       469 GIC          37 :         ExecuteSimpleCommands(AH, buf, bufLen);
                                470                 :     }
                                471                 :     else
                                472                 :     {
                                473                 :         /*
                                474                 :          * General SQL commands; we assume that commands will not be split
                                475                 :          * across calls.
                                476                 :          *
                                477                 :          * In most cases the data passed to us will be a null-terminated
                                478                 :          * string, but if it's not, we have to add a trailing null.
 7751 tgl                       479 ECB             :          */
 4273 tgl                       480 CBC        3556 :         if (buf[bufLen] == '\0')
 4273 tgl                       481 GIC        3556 :             ExecuteSqlCommand(AH, buf, "could not execute query");
                                482                 :         else
 7751 tgl                       483 EUB             :         {
 3955 bruce                     484 UIC           0 :             char       *str = (char *) pg_malloc(bufLen + 1);
 4273 tgl                       485 EUB             : 
 4273 tgl                       486 UBC           0 :             memcpy(str, buf, bufLen);
                                487               0 :             str[bufLen] = '\0';
                                488               0 :             ExecuteSqlCommand(AH, str, "could not execute query");
 4273 tgl                       489 UIC           0 :             free(str);
                                490                 :         }
                                491                 :     }
 8297 pjw                       492 ECB             : 
 3261 bruce                     493 GIC        3603 :     return bufLen;
                                494                 : }
                                495                 : 
                                496                 : /*
                                497                 :  * Terminate a COPY operation during direct-to-DB restore
                                498                 :  */
 4273 tgl                       499 ECB             : void
 3099 alvherre                  500 GIC           9 : EndDBCopyMode(Archive *AHX, const char *tocEntryTag)
 4273 tgl                       501 ECB             : {
 3099 alvherre                  502 GIC           9 :     ArchiveHandle *AH = (ArchiveHandle *) AHX;
 3099 alvherre                  503 ECB             : 
 4273 tgl                       504 GIC           9 :     if (AH->pgCopyIn)
                                505                 :     {
                                506                 :         PGresult   *res;
 6246 tgl                       507 ECB             : 
 6246 tgl                       508 GBC           9 :         if (PQputCopyEnd(AH->connection, NULL) <= 0)
  366 tgl                       509 UIC           0 :             pg_fatal("error returned by PQputCopyEnd: %s",
                                510                 :                      PQerrorMessage(AH->connection));
                                511                 : 
 6246 tgl                       512 ECB             :         /* Check command status and return to normal libpq state */
 6246 tgl                       513 CBC           9 :         res = PQgetResult(AH->connection);
 6246 tgl                       514 GBC           9 :         if (PQresultStatus(res) != PGRES_COMMAND_OK)
 1469 peter                     515 UBC           0 :             warn_or_exit_horribly(AH, "COPY failed for table \"%s\": %s",
 2118 tgl                       516 LBC           0 :                                   tocEntryTag, PQerrorMessage(AH->connection));
 6246 tgl                       517 GIC           9 :         PQclear(res);
                                518                 : 
 2502 tgl                       519 ECB             :         /* Do this to ensure we've pumped libpq back to idle state */
 2502 tgl                       520 GBC           9 :         if (PQgetResult(AH->connection) != NULL)
 1469 peter                     521 UIC           0 :             pg_log_warning("unexpected extra results during COPY of table \"%s\"",
                                522                 :                            tocEntryTag);
 2502 tgl                       523 ECB             : 
 6272 tgl                       524 GIC           9 :         AH->pgCopyIn = false;
 7751 tgl                       525 ECB             :     }
 8297 pjw                       526 GIC           9 : }
                                527                 : 
 8053 bruce                     528 ECB             : void
 3099 alvherre                  529 GIC          10 : StartTransaction(Archive *AHX)
 8297 pjw                       530 ECB             : {
 3099 alvherre                  531 GIC          10 :     ArchiveHandle *AH = (ArchiveHandle *) AHX;
 3099 alvherre                  532 ECB             : 
 5349 tgl                       533 CBC          10 :     ExecuteSqlCommand(AH, "BEGIN", "could not start database transaction");
 8297 pjw                       534 GIC          10 : }
                                535                 : 
 8053 bruce                     536 ECB             : void
 3099 alvherre                  537 GIC          10 : CommitTransaction(Archive *AHX)
 8297 pjw                       538 ECB             : {
 3099 alvherre                  539 GIC          10 :     ArchiveHandle *AH = (ArchiveHandle *) AHX;
 3099 alvherre                  540 ECB             : 
 5349 tgl                       541 CBC          10 :     ExecuteSqlCommand(AH, "COMMIT", "could not commit database transaction");
 8195 pjw                       542 GIC          10 : }
                                543                 : 
 4864 itagaki.takahiro          544 ECB             : void
  125 peter                     545 GNC           2 : DropLOIfExists(ArchiveHandle *AH, Oid oid)
                                546                 : {
                                547                 :     /*
                                548                 :      * If we are not restoring to a direct database connection, we have to
                                549                 :      * guess about how to detect whether the LO exists.  Assume new-style.
 4798 tgl                       550 ECB             :      */
 4798 tgl                       551 CBC           4 :     if (AH->connection == NULL ||
 4798 tgl                       552 GIC           2 :         PQserverVersion(AH->connection) >= 90000)
 4864 itagaki.takahiro          553 ECB             :     {
 4798 tgl                       554 GIC           2 :         ahprintf(AH,
                                555                 :                  "SELECT pg_catalog.lo_unlink(oid) "
                                556                 :                  "FROM pg_catalog.pg_largeobject_metadata "
                                557                 :                  "WHERE oid = '%u';\n",
                                558                 :                  oid);
                                559                 :     }
                                560                 :     else
                                561                 :     {
 4798 tgl                       562 EUB             :         /* Restoring to pre-9.0 server, so do it the old way */
 4798 tgl                       563 UIC           0 :         ahprintf(AH,
                                564                 :                  "SELECT CASE WHEN EXISTS("
                                565                 :                  "SELECT 1 FROM pg_catalog.pg_largeobject WHERE loid = '%u'"
                                566                 :                  ") THEN pg_catalog.lo_unlink('%u') END;\n",
                                567                 :                  oid, oid);
 4864 itagaki.takahiro          568 ECB             :     }
 4864 itagaki.takahiro          569 GIC           2 : }
        

Generated by: LCOV version v1.16-55-g56c0a2a