LCOV - differential code coverage report
Current view: top level - src/bin/psql - large_obj.c (source / functions) Coverage Total Hit UBC CBC
Current: Differential Code Coverage HEAD vs 15 Lines: 53.3 % 107 57 50 57
Current Date: 2023-04-08 17:13:01 Functions: 85.7 % 7 6 1 6
Baseline: 15 Line coverage date bins:
Baseline Date: 2023-04-08 15:09:40 (240..) days: 53.3 % 107 57 50 57
Legend: Lines: hit not hit Function coverage date bins:
(240..) days: 85.7 % 7 6 1 6

 Age         Owner                  TLA  Line data    Source code
                                  1                 : /*
                                  2                 :  * psql - the PostgreSQL interactive terminal
                                  3                 :  *
                                  4                 :  * Copyright (c) 2000-2023, PostgreSQL Global Development Group
                                  5                 :  *
                                  6                 :  * src/bin/psql/large_obj.c
                                  7                 :  */
                                  8                 : #include "postgres_fe.h"
                                  9                 : 
                                 10                 : #include "common.h"
                                 11                 : #include "common/logging.h"
                                 12                 : #include "fe_utils/cancel.h"
                                 13                 : #include "large_obj.h"
                                 14                 : #include "settings.h"
                                 15                 : 
                                 16                 : static void print_lo_result(const char *fmt,...) pg_attribute_printf(1, 2);
                                 17                 : 
                                 18                 : static void
 5923 neilc                      19 CBC          22 : print_lo_result(const char *fmt,...)
                                 20                 : {
                                 21                 :     va_list     ap;
                                 22                 : 
                                 23              22 :     if (!pset.quiet)
                                 24                 :     {
                                 25               1 :         if (pset.popt.topt.format == PRINT_HTML)
 5923 neilc                      26 UBC           0 :             fputs("<p>", pset.queryFout);
                                 27                 : 
 5923 neilc                      28 CBC           1 :         va_start(ap, fmt);
                                 29               1 :         vfprintf(pset.queryFout, fmt, ap);
                                 30               1 :         va_end(ap);
                                 31                 : 
                                 32               1 :         if (pset.popt.topt.format == PRINT_HTML)
 5923 neilc                      33 UBC           0 :             fputs("</p>\n", pset.queryFout);
                                 34                 :         else
 5923 neilc                      35 CBC           1 :             fputs("\n", pset.queryFout);
                                 36                 :     }
                                 37                 : 
                                 38              22 :     if (pset.logfile)
                                 39                 :     {
 5923 neilc                      40 UBC           0 :         va_start(ap, fmt);
                                 41               0 :         vfprintf(pset.logfile, fmt, ap);
                                 42               0 :         va_end(ap);
                                 43               0 :         fputs("\n", pset.logfile);
                                 44                 :     }
 5923 neilc                      45 CBC          22 : }
                                 46                 : 
                                 47                 : 
                                 48                 : /*
                                 49                 :  * Prepare to do a large-object operation.  We *must* be inside a transaction
                                 50                 :  * block for all these operations, so start one if needed.
                                 51                 :  *
                                 52                 :  * Returns true if okay, false if failed.  *own_transaction is set to indicate
                                 53                 :  * if we started our own transaction or not.
                                 54                 :  */
                                 55                 : static bool
 7225 tgl                        56              22 : start_lo_xact(const char *operation, bool *own_transaction)
                                 57                 : {
                                 58                 :     PGTransactionStatusType tstatus;
                                 59                 :     PGresult   *res;
                                 60                 : 
                                 61              22 :     *own_transaction = false;
                                 62                 : 
                                 63              22 :     if (!pset.db)
                                 64                 :     {
 1469 peter                      65 UBC           0 :         pg_log_error("%s: not connected to a database", operation);
 7225 tgl                        66               0 :         return false;
                                 67                 :     }
                                 68                 : 
 7225 tgl                        69 CBC          22 :     tstatus = PQtransactionStatus(pset.db);
                                 70                 : 
                                 71              22 :     switch (tstatus)
                                 72                 :     {
                                 73              22 :         case PQTRANS_IDLE:
                                 74                 :             /* need to start our own xact */
 3090 fujii                      75              22 :             if (!(res = PSQLexec("BEGIN")))
 7225 tgl                        76 UBC           0 :                 return false;
 7225 tgl                        77 CBC          22 :             PQclear(res);
                                 78              22 :             *own_transaction = true;
                                 79              22 :             break;
 7225 tgl                        80 UBC           0 :         case PQTRANS_INTRANS:
                                 81                 :             /* use the existing xact */
                                 82               0 :             break;
                                 83               0 :         case PQTRANS_INERROR:
 1469 peter                      84               0 :             pg_log_error("%s: current transaction is aborted", operation);
 7225 tgl                        85               0 :             return false;
                                 86               0 :         default:
 1469 peter                      87               0 :             pg_log_error("%s: unknown transaction status", operation);
 7225 tgl                        88               0 :             return false;
                                 89                 :     }
                                 90                 : 
 7225 tgl                        91 CBC          22 :     return true;
                                 92                 : }
                                 93                 : 
                                 94                 : /*
                                 95                 :  * Clean up after a successful LO operation
                                 96                 :  */
                                 97                 : static bool
                                 98              22 : finish_lo_xact(const char *operation, bool own_transaction)
                                 99                 : {
                                100                 :     PGresult   *res;
                                101                 : 
 6067                           102              22 :     if (own_transaction && pset.autocommit)
                                103                 :     {
                                104                 :         /* close out our own xact */
 3090 fujii                     105              22 :         if (!(res = PSQLexec("COMMIT")))
                                106                 :         {
 3090 fujii                     107 UBC           0 :             res = PSQLexec("ROLLBACK");
 7225 tgl                       108               0 :             PQclear(res);
                                109               0 :             return false;
                                110                 :         }
 7225 tgl                       111 CBC          22 :         PQclear(res);
                                112                 :     }
                                113                 : 
                                114              22 :     return true;
                                115                 : }
                                116                 : 
                                117                 : /*
                                118                 :  * Clean up after a failed LO operation
                                119                 :  */
                                120                 : static bool
 7225 tgl                       121 UBC           0 : fail_lo_xact(const char *operation, bool own_transaction)
                                122                 : {
                                123                 :     PGresult   *res;
                                124                 : 
 6067                           125               0 :     if (own_transaction && pset.autocommit)
                                126                 :     {
                                127                 :         /* close out our own xact */
 3090 fujii                     128               0 :         res = PSQLexec("ROLLBACK");
 7225 tgl                       129               0 :         PQclear(res);
                                130                 :     }
                                131                 : 
                                132               0 :     return false;               /* always */
                                133                 : }
                                134                 : 
                                135                 : 
                                136                 : /*
                                137                 :  * do_lo_export()
                                138                 :  *
                                139                 :  * Write a large object to a file
                                140                 :  */
                                141                 : bool
 8486 peter_e                   142 CBC           3 : do_lo_export(const char *loid_arg, const char *filename_arg)
                                143                 : {
                                144                 :     int         status;
                                145                 :     bool        own_transaction;
                                146                 : 
 7225 tgl                       147               3 :     if (!start_lo_xact("\\lo_export", &own_transaction))
 8557 bruce                     148 UBC           0 :         return false;
                                149                 : 
 1224 michael                   150 CBC           3 :     SetCancelConn(NULL);
 7857 tgl                       151               3 :     status = lo_export(pset.db, atooid(loid_arg), filename_arg);
 6143                           152               3 :     ResetCancelConn();
                                153                 : 
                                154                 :     /* of course this status is documented nowhere :( */
 8557 bruce                     155               3 :     if (status != 1)
                                156                 :     {
 1469 peter                     157 UBC           0 :         pg_log_info("%s", PQerrorMessage(pset.db));
 7225 tgl                       158               0 :         return fail_lo_xact("\\lo_export", own_transaction);
                                159                 :     }
                                160                 : 
 7225 tgl                       161 CBC           3 :     if (!finish_lo_xact("\\lo_export", own_transaction))
 7225 tgl                       162 UBC           0 :         return false;
                                163                 : 
 5923 neilc                     164 CBC           3 :     print_lo_result("lo_export");
                                165                 : 
 8557 bruce                     166               3 :     return true;
                                167                 : }
                                168                 : 
                                169                 : 
                                170                 : /*
                                171                 :  * do_lo_import()
                                172                 :  *
                                173                 :  * Copy large object from file to database
                                174                 :  */
                                175                 : bool
 8486 peter_e                   176               7 : do_lo_import(const char *filename_arg, const char *comment_arg)
                                177                 : {
                                178                 :     PGresult   *res;
                                179                 :     Oid         loid;
                                180                 :     char        oidbuf[32];
                                181                 :     bool        own_transaction;
                                182                 : 
 7225 tgl                       183               7 :     if (!start_lo_xact("\\lo_import", &own_transaction))
 8557 bruce                     184 UBC           0 :         return false;
                                185                 : 
 1224 michael                   186 CBC           7 :     SetCancelConn(NULL);
 8462 peter_e                   187               7 :     loid = lo_import(pset.db, filename_arg);
 6143 tgl                       188               7 :     ResetCancelConn();
                                189                 : 
 8557 bruce                     190               7 :     if (loid == InvalidOid)
                                191                 :     {
 1469 peter                     192 UBC           0 :         pg_log_info("%s", PQerrorMessage(pset.db));
 7225 tgl                       193               0 :         return fail_lo_xact("\\lo_import", own_transaction);
                                194                 :     }
                                195                 : 
                                196                 :     /* insert description if given */
 7079 tgl                       197 CBC           7 :     if (comment_arg)
                                198                 :     {
                                199                 :         char       *cmdbuf;
                                200                 :         char       *bufptr;
 7493 bruce                     201 UBC           0 :         size_t      slen = strlen(comment_arg);
                                202                 : 
 1436 michael                   203               0 :         cmdbuf = pg_malloc_extended(slen * 2 + 256, MCXT_ALLOC_NO_OOM);
 3456 tgl                       204               0 :         if (!cmdbuf)
 7225                           205               0 :             return fail_lo_xact("\\lo_import", own_transaction);
 3456                           206               0 :         sprintf(cmdbuf, "COMMENT ON LARGE OBJECT %u IS '", loid);
                                207               0 :         bufptr = cmdbuf + strlen(cmdbuf);
 6160                           208               0 :         bufptr += PQescapeStringConn(pset.db, bufptr, comment_arg, slen, NULL);
 7079                           209               0 :         strcpy(bufptr, "'");
                                210                 : 
 3090 fujii                     211               0 :         if (!(res = PSQLexec(cmdbuf)))
                                212                 :         {
 7912 tgl                       213               0 :             free(cmdbuf);
 7225                           214               0 :             return fail_lo_xact("\\lo_import", own_transaction);
                                215                 :         }
                                216                 : 
 7912                           217               0 :         PQclear(res);
                                218               0 :         free(cmdbuf);
                                219                 :     }
                                220                 : 
 7225 tgl                       221 CBC           7 :     if (!finish_lo_xact("\\lo_import", own_transaction))
 7225 tgl                       222 UBC           0 :         return false;
                                223                 : 
 5923 neilc                     224 CBC           7 :     print_lo_result("lo_import %u", loid);
                                225                 : 
 7912 tgl                       226               7 :     sprintf(oidbuf, "%u", loid);
                                227               7 :     SetVariable(pset.vars, "LASTOID", oidbuf);
                                228                 : 
 8557 bruce                     229               7 :     return true;
                                230                 : }
                                231                 : 
                                232                 : 
                                233                 : /*
                                234                 :  * do_lo_unlink()
                                235                 :  *
                                236                 :  * removes a large object out of the database
                                237                 :  */
                                238                 : bool
 8486 peter_e                   239              12 : do_lo_unlink(const char *loid_arg)
                                240                 : {
                                241                 :     int         status;
 7857 tgl                       242              12 :     Oid         loid = atooid(loid_arg);
                                243                 :     bool        own_transaction;
                                244                 : 
 7225                           245              12 :     if (!start_lo_xact("\\lo_unlink", &own_transaction))
 8557 bruce                     246 UBC           0 :         return false;
                                247                 : 
 1224 michael                   248 CBC          12 :     SetCancelConn(NULL);
 8486 peter_e                   249              12 :     status = lo_unlink(pset.db, loid);
 6143 tgl                       250              12 :     ResetCancelConn();
                                251                 : 
 8557 bruce                     252              12 :     if (status == -1)
                                253                 :     {
 1469 peter                     254 UBC           0 :         pg_log_info("%s", PQerrorMessage(pset.db));
 7225 tgl                       255               0 :         return fail_lo_xact("\\lo_unlink", own_transaction);
                                256                 :     }
                                257                 : 
 7225 tgl                       258 CBC          12 :     if (!finish_lo_xact("\\lo_unlink", own_transaction))
 7225 tgl                       259 UBC           0 :         return false;
                                260                 : 
 5923 neilc                     261 CBC          12 :     print_lo_result("lo_unlink %u", loid);
                                262                 : 
 8557 bruce                     263              12 :     return true;
                                264                 : }
        

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