LCOV - differential code coverage report
Current view: top level - src/backend/commands - copy.c (source / functions) Coverage Total Hit UNC UBC GBC GIC GNC CBC DUB DCB
Current: bed3ffbf9d952be6c7d739d068cdce44c046dfb7 vs 574581b50ac9c63dd9e4abebb731a3b67e5b50f6 Lines: 95.4 % 414 395 1 18 2 68 325 7 33
Current Date: 2026-05-05 10:23:31 +0900 Functions: 100.0 % 7 7 5 2 1
Baseline: lcov-20260505-025707-baseline Branches: 80.0 % 536 429 9 98 2 8 119 300 6 81
Baseline Date: 2026-05-05 10:27:06 +0900 Line coverage date bins:
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
(7,30] days: 100.0 % 5 5 5
(30,360] days: 98.6 % 74 73 1 63 10
(360..) days: 94.6 % 335 317 18 2 315
Function coverage date bins:
(30,360] days: 100.0 % 1 1 1
(360..) days: 100.0 % 6 6 4 2
Branch coverage date bins:
(7,30] days: 70.0 % 10 7 3 7
(30,360] days: 94.4 % 124 117 6 1 112 5
(360..) days: 75.9 % 402 305 97 2 8 295

 Age         Owner                    Branch data    TLA  Line data    Source code
                                  1                 :                : /*-------------------------------------------------------------------------
                                  2                 :                :  *
                                  3                 :                :  * copy.c
                                  4                 :                :  *      Implements the COPY utility command
                                  5                 :                :  *
                                  6                 :                :  * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
                                  7                 :                :  * Portions Copyright (c) 1994, Regents of the University of California
                                  8                 :                :  *
                                  9                 :                :  *
                                 10                 :                :  * IDENTIFICATION
                                 11                 :                :  *    src/backend/commands/copy.c
                                 12                 :                :  *
                                 13                 :                :  *-------------------------------------------------------------------------
                                 14                 :                :  */
                                 15                 :                : #include "postgres.h"
                                 16                 :                : 
                                 17                 :                : #include <ctype.h>
                                 18                 :                : #include <unistd.h>
                                 19                 :                : #include <sys/stat.h>
                                 20                 :                : 
                                 21                 :                : #include "access/sysattr.h"
                                 22                 :                : #include "access/table.h"
                                 23                 :                : #include "access/xact.h"
                                 24                 :                : #include "catalog/pg_authid.h"
                                 25                 :                : #include "commands/copy.h"
                                 26                 :                : #include "commands/defrem.h"
                                 27                 :                : #include "executor/executor.h"
                                 28                 :                : #include "mb/pg_wchar.h"
                                 29                 :                : #include "miscadmin.h"
                                 30                 :                : #include "nodes/makefuncs.h"
                                 31                 :                : #include "nodes/miscnodes.h"
                                 32                 :                : #include "optimizer/optimizer.h"
                                 33                 :                : #include "parser/parse_coerce.h"
                                 34                 :                : #include "parser/parse_collate.h"
                                 35                 :                : #include "parser/parse_expr.h"
                                 36                 :                : #include "parser/parse_relation.h"
                                 37                 :                : #include "utils/acl.h"
                                 38                 :                : #include "utils/builtins.h"
                                 39                 :                : #include "utils/lsyscache.h"
                                 40                 :                : #include "utils/rel.h"
                                 41                 :                : #include "utils/rls.h"
                                 42                 :                : 
                                 43                 :                : /*
                                 44                 :                :  *   DoCopy executes the SQL COPY statement
                                 45                 :                :  *
                                 46                 :                :  * Either unload or reload contents of table <relation>, depending on <from>.
                                 47                 :                :  * (<from> = true means we are inserting into the table.)  In the "TO" case
                                 48                 :                :  * we also support copying the output of an arbitrary SELECT, INSERT, UPDATE
                                 49                 :                :  * or DELETE query.
                                 50                 :                :  *
                                 51                 :                :  * If <pipe> is false, transfer is between the table and the file named
                                 52                 :                :  * <filename>.  Otherwise, transfer is between the table and our regular
                                 53                 :                :  * input/output stream. The latter could be either stdin/stdout or a
                                 54                 :                :  * socket, depending on whether we're running under Postmaster control.
                                 55                 :                :  *
                                 56                 :                :  * Do not allow a Postgres user without the 'pg_read_server_files' or
                                 57                 :                :  * 'pg_write_server_files' role to read from or write to a file.
                                 58                 :                :  *
                                 59                 :                :  * Do not allow the copy if user doesn't have proper permission to access
                                 60                 :                :  * the table or the specifically requested columns.
                                 61                 :                :  */
                                 62                 :                : void
 3398 tgl@sss.pgh.pa.us          63                 :CBC        6718 : DoCopy(ParseState *pstate, const CopyStmt *stmt,
                                 64                 :                :        int stmt_location, int stmt_len,
                                 65                 :                :        uint64 *processed)
                                 66                 :                : {
 5557 itagaki.takahiro@gma       67                 :           6718 :     bool        is_from = stmt->is_from;
                                 68                 :           6718 :     bool        pipe = (stmt->filename == NULL);
                                 69                 :                :     Relation    rel;
                                 70                 :                :     Oid         relid;
 3398 tgl@sss.pgh.pa.us          71                 :           6718 :     RawStmt    *query = NULL;
 2588 andres@anarazel.de         72                 :           6718 :     Node       *whereClause = NULL;
                                 73                 :                : 
                                 74                 :                :     /*
                                 75                 :                :      * Disallow COPY to/from file or program except to users with the
                                 76                 :                :      * appropriate role.
                                 77                 :                :      */
 2951 sfrost@snowman.net         78         [ +  + ]:           6718 :     if (!pipe)
                                 79                 :                :     {
 4815 heikki.linnakangas@i       80         [ -  + ]:            302 :         if (stmt->is_program)
                                 81                 :                :         {
 1499 mail@joeconway.com         82         [ #  # ]:UBC           0 :             if (!has_privs_of_role(GetUserId(), ROLE_PG_EXECUTE_SERVER_PROGRAM))
 2951 sfrost@snowman.net         83         [ #  # ]:              0 :                 ereport(ERROR,
                                 84                 :                :                         (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
                                 85                 :                :                          errmsg("permission denied to COPY to or from an external program"),
                                 86                 :                :                          errdetail("Only roles with privileges of the \"%s\" role may COPY to or from an external program.",
                                 87                 :                :                                    "pg_execute_server_program"),
                                 88                 :                :                          errhint("Anyone can COPY to stdout or from stdin. "
                                 89                 :                :                                  "psql's \\copy command also works for anyone.")));
                                 90                 :                :         }
                                 91                 :                :         else
                                 92                 :                :         {
 1499 mail@joeconway.com         93   [ +  +  -  + ]:CBC         302 :             if (is_from && !has_privs_of_role(GetUserId(), ROLE_PG_READ_SERVER_FILES))
 2951 sfrost@snowman.net         94         [ #  # ]:UBC           0 :                 ereport(ERROR,
                                 95                 :                :                         (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
                                 96                 :                :                          errmsg("permission denied to COPY from a file"),
                                 97                 :                :                          errdetail("Only roles with privileges of the \"%s\" role may COPY from a file.",
                                 98                 :                :                                    "pg_read_server_files"),
                                 99                 :                :                          errhint("Anyone can COPY to stdout or from stdin. "
                                100                 :                :                                  "psql's \\copy command also works for anyone.")));
                                101                 :                : 
 1499 mail@joeconway.com        102   [ +  +  -  + ]:CBC         302 :             if (!is_from && !has_privs_of_role(GetUserId(), ROLE_PG_WRITE_SERVER_FILES))
 2951 sfrost@snowman.net        103         [ #  # ]:UBC           0 :                 ereport(ERROR,
                                104                 :                :                         (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
                                105                 :                :                          errmsg("permission denied to COPY to a file"),
                                106                 :                :                          errdetail("Only roles with privileges of the \"%s\" role may COPY to a file.",
                                107                 :                :                                    "pg_write_server_files"),
                                108                 :                :                          errhint("Anyone can COPY to stdout or from stdin. "
                                109                 :                :                                  "psql's \\copy command also works for anyone.")));
                                110                 :                :         }
                                111                 :                :     }
                                112                 :                : 
 5557 itagaki.takahiro@gma      113         [ +  + ]:CBC        6718 :     if (stmt->relation)
                                114                 :                :     {
 2774 tgl@sss.pgh.pa.us         115         [ +  + ]:           6367 :         LOCKMODE    lockmode = is_from ? RowExclusiveLock : AccessShareLock;
                                116                 :                :         ParseNamespaceItem *nsitem;
                                117                 :                :         RTEPermissionInfo *perminfo;
                                118                 :                :         TupleDesc   tupDesc;
                                119                 :                :         List       *attnums;
                                120                 :                :         ListCell   *cur;
                                121                 :                : 
 5557 itagaki.takahiro@gma      122         [ -  + ]:           6367 :         Assert(!stmt->query);
                                123                 :                : 
                                124                 :                :         /* Open and lock the relation, using the appropriate lock type. */
 2661 andres@anarazel.de        125                 :           6367 :         rel = table_openrv(stmt->relation, lockmode);
                                126                 :                : 
 4875 rhaas@postgresql.org      127                 :           6362 :         relid = RelationGetRelid(rel);
                                128                 :                : 
 2315 tgl@sss.pgh.pa.us         129                 :           6362 :         nsitem = addRangeTableEntryForRelation(pstate, rel, lockmode,
                                130                 :                :                                                NULL, false, false);
                                131                 :                : 
 1246 alvherre@alvh.no-ip.      132                 :           6362 :         perminfo = nsitem->p_perminfo;
                                133         [ +  + ]:           6362 :         perminfo->requiredPerms = (is_from ? ACL_INSERT : ACL_SELECT);
                                134                 :                : 
 2663 tomas.vondra@postgre      135         [ +  + ]:           6362 :         if (stmt->whereClause)
                                136                 :                :         {
  180 peter@eisentraut.org      137                 :             52 :             Bitmapset  *expr_attrs = NULL;
                                138                 :                :             int         i;
                                139                 :                : 
                                140                 :                :             /* Add nsitem to query namespace */
 2315 tgl@sss.pgh.pa.us         141                 :             52 :             addNSItemToQuery(pstate, nsitem, false, true, true);
                                142                 :                : 
                                143                 :                :             /* Transform the raw expression tree */
 2663 tomas.vondra@postgre      144                 :             52 :             whereClause = transformExpr(pstate, stmt->whereClause, EXPR_KIND_COPY_WHERE);
                                145                 :                : 
                                146                 :                :             /* Make sure it yields a boolean result */
                                147                 :             32 :             whereClause = coerce_to_boolean(pstate, whereClause, "WHERE");
                                148                 :                : 
                                149                 :                :             /* We have to fix its collations too */
                                150                 :             32 :             assign_expr_collations(pstate, whereClause);
                                151                 :                : 
                                152                 :                :             /*
                                153                 :                :              * Identify all columns used in the WHERE clause's expression.  If
                                154                 :                :              * there's a whole-row reference, replace it with a range of all
                                155                 :                :              * the user columns (caution: that'll include dropped columns).
                                156                 :                :              */
  180 peter@eisentraut.org      157                 :             32 :             pull_varattnos(whereClause, 1, &expr_attrs);
                                158         [ +  + ]:             32 :             if (bms_is_member(0 - FirstLowInvalidHeapAttributeNumber, expr_attrs))
                                159                 :                :             {
                                160                 :             16 :                 expr_attrs = bms_add_range(expr_attrs,
                                161                 :                :                                            1 - FirstLowInvalidHeapAttributeNumber,
                                162                 :              8 :                                            RelationGetNumberOfAttributes(rel) - FirstLowInvalidHeapAttributeNumber);
                                163                 :              8 :                 expr_attrs = bms_del_member(expr_attrs, 0 - FirstLowInvalidHeapAttributeNumber);
                                164                 :                :             }
                                165                 :                : 
                                166                 :                :             /* Now we can scan each column needed in the WHERE clause */
                                167                 :             32 :             i = -1;
                                168         [ +  + ]:             52 :             while ((i = bms_next_member(expr_attrs, i)) >= 0)
                                169                 :                :             {
                                170                 :             40 :                 AttrNumber  attno = i + FirstLowInvalidHeapAttributeNumber;
                                171                 :                :                 Form_pg_attribute att;
                                172                 :                : 
   29 tgl@sss.pgh.pa.us         173         [ -  + ]:GNC          40 :                 Assert(attno != 0); /* removed above */
                                174                 :                : 
                                175                 :                :                 /*
                                176                 :                :                  * Prohibit system columns in the WHERE clause.  They won't
                                177                 :                :                  * have been filled yet when the filtering happens.  (We could
                                178                 :                :                  * allow tableoid, but right now it isn't really useful: it
                                179                 :                :                  * will read as the target table's OID.  Any conceivable use
                                180                 :                :                  * for such a WHERE clause would probably wish it to read as
                                181                 :                :                  * the target partition's OID, which is not known yet.
                                182                 :                :                  * Disallow it to keep flexibility to change that sometime.)
                                183                 :                :                  */
                                184         [ +  + ]:             40 :                 if (attno < 0)
                                185         [ +  - ]:              4 :                     ereport(ERROR,
                                186                 :                :                             errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
                                187                 :                :                             errmsg("system columns are not supported in COPY FROM WHERE conditions"),
                                188                 :                :                             errdetail("Column \"%s\" is a system column.",
                                189                 :                :                                       get_attname(RelationGetRelid(rel), attno, false)));
                                190                 :                : 
                                191                 :                :                 /*
                                192                 :                :                  * Prohibit generated columns in the WHERE clause.  Stored
                                193                 :                :                  * generated columns are not yet computed when the filtering
                                194                 :                :                  * happens.  Virtual generated columns could probably work (we
                                195                 :                :                  * would need to expand them somewhere around here), but for
                                196                 :                :                  * now we keep them consistent with the stored variant.
                                197                 :                :                  */
                                198                 :             36 :                 att = TupleDescAttr(RelationGetDescr(rel), attno - 1);
                                199   [ +  +  +  - ]:             36 :                 if (att->attgenerated && !att->attisdropped)
  180 peter@eisentraut.org      200         [ +  - ]:CBC          16 :                     ereport(ERROR,
                                201                 :                :                             errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
                                202                 :                :                             errmsg("generated columns are not supported in COPY FROM WHERE conditions"),
                                203                 :                :                             errdetail("Column \"%s\" is a generated column.",
                                204                 :                :                                       get_attname(RelationGetRelid(rel), attno, false)));
                                205                 :                :             }
                                206                 :                : 
                                207                 :                :             /* Reduce WHERE clause to standard list-of-AND-terms form */
 2663 tomas.vondra@postgre      208                 :             12 :             whereClause = eval_const_expressions(NULL, whereClause);
                                209                 :                : 
                                210                 :             12 :             whereClause = (Node *) canonicalize_qual((Expr *) whereClause, false);
                                211                 :             12 :             whereClause = (Node *) make_ands_implicit((Expr *) whereClause);
                                212                 :                :         }
                                213                 :                : 
 5557 itagaki.takahiro@gma      214                 :           6322 :         tupDesc = RelationGetDescr(rel);
                                215                 :           6322 :         attnums = CopyGetAttnums(tupDesc, rel, stmt->attlist);
 5553 tgl@sss.pgh.pa.us         216   [ +  +  +  +  :          27224 :         foreach(cur, attnums)
                                              +  + ]
                                217                 :                :         {
                                218                 :                :             int         attno;
                                219                 :                :             Bitmapset **bms;
                                220                 :                : 
 1246 alvherre@alvh.no-ip.      221                 :          20958 :             attno = lfirst_int(cur) - FirstLowInvalidHeapAttributeNumber;
                                222         [ +  + ]:          20958 :             bms = is_from ? &perminfo->insertedCols : &perminfo->selectedCols;
                                223                 :                : 
                                224                 :          20958 :             *bms = bms_add_member(*bms, attno);
                                225                 :                :         }
                                226                 :           6266 :         ExecCheckPermissions(pstate->p_rtable, list_make1(perminfo), true);
                                227                 :                : 
                                228                 :                :         /*
                                229                 :                :          * Permission check for row security policies.
                                230                 :                :          *
                                231                 :                :          * check_enable_rls will ereport(ERROR) if the user has requested
                                232                 :                :          * something invalid and will otherwise indicate if we should enable
                                233                 :                :          * RLS (returns RLS_ENABLED) or not for this COPY statement.
                                234                 :                :          *
                                235                 :                :          * If the relation has a row security policy and we are to apply it
                                236                 :                :          * then perform a "query" copy and allow the normal query processing
                                237                 :                :          * to handle the policies.
                                238                 :                :          *
                                239                 :                :          * If RLS is not enabled for this, then just fall through to the
                                240                 :                :          * normal non-filtering relation handling.
                                241                 :                :          */
                                242         [ +  + ]:           6210 :         if (check_enable_rls(relid, InvalidOid, false) == RLS_ENABLED)
                                243                 :                :         {
                                244                 :                :             SelectStmt *select;
                                245                 :                :             ColumnRef  *cr;
                                246                 :                :             ResTarget  *target;
                                247                 :                :             RangeVar   *from;
 3501 sfrost@snowman.net        248                 :             56 :             List       *targetList = NIL;
                                249                 :                : 
 4246                           250         [ +  + ]:             56 :             if (is_from)
                                251         [ +  - ]:              4 :                 ereport(ERROR,
                                252                 :                :                         (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                                253                 :                :                          errmsg("COPY FROM not supported with row-level security"),
                                254                 :                :                          errhint("Use INSERT statements instead.")));
                                255                 :                : 
                                256                 :                :             /*
                                257                 :                :              * Build target list
                                258                 :                :              *
                                259                 :                :              * If no columns are specified in the attribute list of the COPY
                                260                 :                :              * command, then the target list is 'all' columns. Therefore, '*'
                                261                 :                :              * should be used as the target list for the resulting SELECT
                                262                 :                :              * statement.
                                263                 :                :              *
                                264                 :                :              * In the case that columns are specified in the attribute list,
                                265                 :                :              * create a ColumnRef and ResTarget for each column and add them
                                266                 :                :              * to the target list for the resulting SELECT statement.
                                267                 :                :              */
                                268         [ +  + ]:             52 :             if (!stmt->attlist)
                                269                 :                :             {
 3501                           270                 :             28 :                 cr = makeNode(ColumnRef);
 4246                           271                 :             28 :                 cr->fields = list_make1(makeNode(A_Star));
 3501                           272                 :             28 :                 cr->location = -1;
                                273                 :                : 
                                274                 :             28 :                 target = makeNode(ResTarget);
                                275                 :             28 :                 target->name = NULL;
                                276                 :             28 :                 target->indirection = NIL;
                                277                 :             28 :                 target->val = (Node *) cr;
                                278                 :             28 :                 target->location = -1;
                                279                 :                : 
                                280                 :             28 :                 targetList = list_make1(target);
                                281                 :                :             }
                                282                 :                :             else
                                283                 :                :             {
                                284                 :                :                 ListCell   *lc;
                                285                 :                : 
                                286   [ +  -  +  +  :             68 :                 foreach(lc, stmt->attlist)
                                              +  + ]
                                287                 :                :                 {
                                288                 :                :                     /*
                                289                 :                :                      * Build the ColumnRef for each column.  The ColumnRef
                                290                 :                :                      * 'fields' property is a String node that corresponds to
                                291                 :                :                      * the column name respectively.
                                292                 :                :                      */
                                293                 :             44 :                     cr = makeNode(ColumnRef);
                                294                 :             44 :                     cr->fields = list_make1(lfirst(lc));
                                295                 :             44 :                     cr->location = -1;
                                296                 :                : 
                                297                 :                :                     /* Build the ResTarget and add the ColumnRef to it. */
                                298                 :             44 :                     target = makeNode(ResTarget);
                                299                 :             44 :                     target->name = NULL;
                                300                 :             44 :                     target->indirection = NIL;
                                301                 :             44 :                     target->val = (Node *) cr;
                                302                 :             44 :                     target->location = -1;
                                303                 :                : 
                                304                 :                :                     /* Add each column to the SELECT statement's target list */
                                305                 :             44 :                     targetList = lappend(targetList, target);
                                306                 :                :                 }
                                307                 :                :             }
                                308                 :                : 
                                309                 :                :             /*
                                310                 :                :              * Build RangeVar for from clause, fully qualified based on the
                                311                 :                :              * relation which we have opened and locked.  Use "ONLY" so that
                                312                 :                :              * COPY retrieves rows from only the target table not any
                                313                 :                :              * inheritance children, the same as when RLS doesn't apply.
                                314                 :                :              *
                                315                 :                :              * However, when copying data from a partitioned table, we don't
                                316                 :                :              * use "ONLY", since we need to retrieve rows from its descendant
                                317                 :                :              * tables too.
                                318                 :                :              */
 3935                           319                 :             52 :             from = makeRangeVar(get_namespace_name(RelationGetNamespace(rel)),
 3347 tgl@sss.pgh.pa.us         320                 :             52 :                                 pstrdup(RelationGetRelationName(rel)),
                                321                 :                :                                 -1);
  197 msawada@postgresql.o      322                 :GNC          52 :             from->inh = (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE);
                                323                 :                : 
                                324                 :                :             /* Build query */
 4246 sfrost@snowman.net        325                 :CBC          52 :             select = makeNode(SelectStmt);
 3501                           326                 :             52 :             select->targetList = targetList;
 4246                           327                 :             52 :             select->fromClause = list_make1(from);
                                328                 :                : 
 3398 tgl@sss.pgh.pa.us         329                 :             52 :             query = makeNode(RawStmt);
                                330                 :             52 :             query->stmt = (Node *) select;
                                331                 :             52 :             query->stmt_location = stmt_location;
                                332                 :             52 :             query->stmt_len = stmt_len;
                                333                 :                : 
                                334                 :                :             /*
                                335                 :                :              * Close the relation for now, but keep the lock on it to prevent
                                336                 :                :              * changes between now and when we start the query-based COPY.
                                337                 :                :              *
                                338                 :                :              * We'll reopen it later as part of the query-based COPY.
                                339                 :                :              */
 2661 andres@anarazel.de        340                 :             52 :             table_close(rel, NoLock);
 4246 sfrost@snowman.net        341                 :             52 :             rel = NULL;
                                342                 :                :         }
                                343                 :                :     }
                                344                 :                :     else
                                345                 :                :     {
 5557 itagaki.takahiro@gma      346         [ -  + ]:            351 :         Assert(stmt->query);
                                347                 :                : 
 3398 tgl@sss.pgh.pa.us         348                 :            351 :         query = makeNode(RawStmt);
                                349                 :            351 :         query->stmt = stmt->query;
                                350                 :            351 :         query->stmt_location = stmt_location;
                                351                 :            351 :         query->stmt_len = stmt_len;
                                352                 :                : 
 4873 peter_e@gmx.net           353                 :            351 :         relid = InvalidOid;
 5557 itagaki.takahiro@gma      354                 :            351 :         rel = NULL;
                                355                 :                :     }
                                356                 :                : 
                                357         [ +  + ]:           6545 :     if (is_from)
                                358                 :                :     {
                                359                 :                :         CopyFromState cstate;
                                360                 :                : 
 5165 peter_e@gmx.net           361         [ -  + ]:           1127 :         Assert(rel);
                                362                 :                : 
                                363                 :                :         /* check read-only transaction and parallel mode */
 4887 tgl@sss.pgh.pa.us         364   [ -  +  -  - ]:           1127 :         if (XactReadOnly && !rel->rd_islocaltemp)
 5557 itagaki.takahiro@gma      365                 :UBC           0 :             PreventCommandIfReadOnly("COPY FROM");
                                366                 :                : 
 1989 heikki.linnakangas@i      367                 :CBC        1127 :         cstate = BeginCopyFrom(pstate, rel, whereClause,
                                368                 :           1127 :                                stmt->filename, stmt->is_program,
 3330 peter_e@gmx.net           369                 :           1127 :                                NULL, stmt->attlist, stmt->options);
 4875 rhaas@postgresql.org      370                 :            931 :         *processed = CopyFrom(cstate);  /* copy from file to database */
 5557 itagaki.takahiro@gma      371                 :            755 :         EndCopyFrom(cstate);
                                372                 :                :     }
                                373                 :                :     else
                                374                 :                :     {
                                375                 :                :         CopyToState cstate;
                                376                 :                : 
 3528 peter_e@gmx.net           377                 :           5418 :         cstate = BeginCopyTo(pstate, rel, query, relid,
 4815 heikki.linnakangas@i      378                 :           5418 :                              stmt->filename, stmt->is_program,
 1302 michael@paquier.xyz       379                 :           5418 :                              NULL, stmt->attlist, stmt->options);
 4875 rhaas@postgresql.org      380                 :           5220 :         *processed = DoCopyTo(cstate);  /* copy from database to file */
 5557 itagaki.takahiro@gma      381                 :           5219 :         EndCopyTo(cstate);
                                382                 :                :     }
                                383                 :                : 
                                384         [ +  + ]:           5974 :     if (rel != NULL)
 2181 akapila@postgresql.o      385                 :           5664 :         table_close(rel, NoLock);
 5557 itagaki.takahiro@gma      386                 :           5974 : }
                                387                 :                : 
                                388                 :                : /*
                                389                 :                :  * Extract the CopyFormatOptions.header_line value from a DefElem.
                                390                 :                :  *
                                391                 :                :  * Parses the HEADER option for COPY, which can be a boolean, an integer greater
                                392                 :                :  * than or equal to zero (number of lines to skip), or the special value
                                393                 :                :  * "match".
                                394                 :                :  */
                                395                 :                : static int
  306 fujii@postgresql.org      396                 :GNC         180 : defGetCopyHeaderOption(DefElem *def, bool is_from)
                                397                 :                : {
  103                           398                 :            180 :     int         ival = COPY_HEADER_FALSE;
                                399                 :                : 
                                400                 :                :     /*
                                401                 :                :      * If no parameter value given, assume "true" is meant.
                                402                 :                :      */
 1497 peter@eisentraut.org      403         [ +  + ]:CBC         180 :     if (def->arg == NULL)
                                404                 :             24 :         return COPY_HEADER_TRUE;
                                405                 :                : 
                                406                 :                :     /*
                                407                 :                :      * Allow an integer value greater than or equal to zero (integers
                                408                 :                :      * specified as strings are also accepted, mainly for file_fdw foreign
                                409                 :                :      * table options), "true", "false", "on", "off", or "match".
                                410                 :                :      */
                                411         [ +  + ]:            156 :     switch (nodeTag(def->arg))
                                412                 :                :     {
 1497 peter@eisentraut.org      413                 :GBC          24 :         case T_Integer:
  103 fujii@postgresql.org      414                 :GNC          24 :             ival = intVal(def->arg);
 1497 peter@eisentraut.org      415                 :GBC          24 :             break;
 1497 peter@eisentraut.org      416                 :CBC         132 :         default:
                                417                 :                :             {
 1454 tgl@sss.pgh.pa.us         418                 :            132 :                 char       *sval = defGetString(def);
                                419                 :                : 
                                420                 :                :                 /*
                                421                 :                :                  * The set of strings accepted here should match up with the
                                422                 :                :                  * grammar's opt_boolean_or_string production.
                                423                 :                :                  */
 1497 peter@eisentraut.org      424         [ +  + ]:            132 :                 if (pg_strcasecmp(sval, "true") == 0)
                                425                 :             37 :                     return COPY_HEADER_TRUE;
                                426         [ -  + ]:             95 :                 if (pg_strcasecmp(sval, "false") == 0)
 1497 peter@eisentraut.org      427                 :UBC           0 :                     return COPY_HEADER_FALSE;
 1497 peter@eisentraut.org      428         [ -  + ]:CBC          95 :                 if (pg_strcasecmp(sval, "on") == 0)
 1497 peter@eisentraut.org      429                 :UBC           0 :                     return COPY_HEADER_TRUE;
 1497 peter@eisentraut.org      430         [ +  + ]:CBC          95 :                 if (pg_strcasecmp(sval, "off") == 0)
                                431                 :              4 :                     return COPY_HEADER_FALSE;
                                432         [ +  + ]:             91 :                 if (pg_strcasecmp(sval, "match") == 0)
                                433                 :                :                 {
 1412 michael@paquier.xyz       434         [ +  + ]:             56 :                     if (!is_from)
                                435         [ +  - ]:              4 :                         ereport(ERROR,
                                436                 :                :                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                                437                 :                :                                  errmsg("cannot use \"%s\" with HEADER in COPY TO",
                                438                 :                :                                         sval)));
 1497 peter@eisentraut.org      439                 :             52 :                     return COPY_HEADER_MATCH;
                                440                 :                :                 }
                                441                 :                :                 else
                                442                 :                :                 {
  103 fujii@postgresql.org      443                 :GNC          35 :                     ErrorSaveContext escontext = {T_ErrorSaveContext};
                                444                 :                : 
                                445                 :                :                     /* Check if the header is a valid integer */
                                446                 :             35 :                     ival = pg_strtoint32_safe(sval, (Node *) &escontext);
                                447         [ +  + ]:             35 :                     if (escontext.error_occurred)
                                448         [ +  - ]:             14 :                         ereport(ERROR,
                                449                 :                :                                 (errcode(ERRCODE_SYNTAX_ERROR),
                                450                 :                :                         /*- translator: first %s is the name of a COPY option, e.g. ON_ERROR,
                                451                 :                :                         second %s is the special value "match" for that option */
                                452                 :                :                                  errmsg("%s requires a Boolean value, an integer "
                                453                 :                :                                         "value greater than or equal to zero, "
                                454                 :                :                                         "or the string \"%s\"",
                                455                 :                :                                         def->defname, "match")));
                                456                 :                :                 }
                                457                 :                :             }
 1497 peter@eisentraut.org      458                 :CBC          21 :             break;
                                459                 :                :     }
                                460                 :                : 
  103 fujii@postgresql.org      461         [ +  + ]:GNC          45 :     if (ival < 0)
                                462         [ +  - ]:              9 :         ereport(ERROR,
                                463                 :                :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                                464                 :                :                  errmsg("a negative integer value cannot be "
                                465                 :                :                         "specified for %s", def->defname)));
                                466                 :                : 
                                467   [ +  +  +  + ]:             36 :     if (!is_from && ival > 1)
                                468         [ +  - ]:              8 :         ereport(ERROR,
                                469                 :                :                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                                470                 :                :                  errmsg("cannot use multi-line header in COPY TO")));
                                471                 :                : 
                                472                 :             28 :     return ival;
                                473                 :                : }
                                474                 :                : 
                                475                 :                : /*
                                476                 :                :  * Extract a CopyOnErrorChoice value from a DefElem.
                                477                 :                :  */
                                478                 :                : static CopyOnErrorChoice
  837 akorotkov@postgresql      479                 :CBC         118 : defGetCopyOnErrorChoice(DefElem *def, ParseState *pstate, bool is_from)
                                480                 :                : {
  748 msawada@postgresql.o      481                 :            118 :     char       *sval = defGetString(def);
                                482                 :                : 
  840 akorotkov@postgresql      483         [ +  + ]:            118 :     if (!is_from)
                                484         [ +  - ]:             12 :         ereport(ERROR,
                                485                 :                :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                                486                 :                :         /*- translator: first %s is the name of a COPY option, e.g. ON_ERROR,
                                487                 :                :          second %s is a COPY with direction, e.g. COPY TO */
                                488                 :                :                  errmsg("COPY %s cannot be used with %s", "ON_ERROR", "COPY TO"),
                                489                 :                :                  parser_errposition(pstate, def->location)));
                                490                 :                : 
  837                           491         [ +  + ]:            106 :     if (pg_strcasecmp(sval, "stop") == 0)
                                492                 :              4 :         return COPY_ON_ERROR_STOP;
                                493         [ +  + ]:            102 :     if (pg_strcasecmp(sval, "ignore") == 0)
                                494                 :             59 :         return COPY_ON_ERROR_IGNORE;
   63 peter@eisentraut.org      495         [ +  + ]:GNC          43 :     if (pg_strcasecmp(sval, "set_null") == 0)
                                496                 :             38 :         return COPY_ON_ERROR_SET_NULL;
                                497                 :                : 
  840 akorotkov@postgresql      498         [ +  - ]:CBC           5 :     ereport(ERROR,
                                499                 :                :             (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                                500                 :                :     /*- translator: first %s is the name of a COPY option, e.g. ON_ERROR */
                                501                 :                :              errmsg("COPY %s \"%s\" not recognized", "ON_ERROR", sval),
                                502                 :                :              parser_errposition(pstate, def->location)));
                                503                 :                :     return COPY_ON_ERROR_STOP;  /* keep compiler quiet */
                                504                 :                : }
                                505                 :                : 
                                506                 :                : /*
                                507                 :                :  * Extract REJECT_LIMIT value from a DefElem.
                                508                 :                :  *
                                509                 :                :  * REJECT_LIMIT can be specified in two ways: as an int64 for the COPY command
                                510                 :                :  * option or as a single-quoted string for the foreign table option using
                                511                 :                :  * file_fdw. Therefore this function needs to handle both formats.
                                512                 :                :  */
                                513                 :                : static int64
  574 fujii@postgresql.org      514                 :             31 : defGetCopyRejectLimitOption(DefElem *def)
                                515                 :                : {
                                516                 :                :     int64       reject_limit;
                                517                 :                : 
  531                           518         [ -  + ]:             31 :     if (def->arg == NULL)
  531 fujii@postgresql.org      519         [ #  # ]:UBC           0 :         ereport(ERROR,
                                520                 :                :                 (errcode(ERRCODE_SYNTAX_ERROR),
                                521                 :                :                  errmsg("%s requires a numeric value",
                                522                 :                :                         def->defname)));
  117 heikki.linnakangas@i      523         [ +  + ]:GNC          31 :     else if (IsA(def->arg, String))
  531 fujii@postgresql.org      524                 :CBC           7 :         reject_limit = pg_strtoint64(strVal(def->arg));
                                525                 :                :     else
                                526                 :             24 :         reject_limit = defGetInt64(def);
                                527                 :                : 
  574                           528         [ +  + ]:             31 :     if (reject_limit <= 0)
                                529         [ +  - ]:              5 :         ereport(ERROR,
                                530                 :                :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                                531                 :                :                  errmsg("REJECT_LIMIT (%" PRId64 ") must be greater than zero",
                                532                 :                :                         reject_limit)));
                                533                 :                : 
                                534                 :             26 :     return reject_limit;
                                535                 :                : }
                                536                 :                : 
                                537                 :                : /*
                                538                 :                :  * Extract a CopyLogVerbosityChoice value from a DefElem.
                                539                 :                :  */
                                540                 :                : static CopyLogVerbosityChoice
  764 msawada@postgresql.o      541                 :             32 : defGetCopyLogVerbosityChoice(DefElem *def, ParseState *pstate)
                                542                 :                : {
                                543                 :                :     char       *sval;
                                544                 :                : 
                                545                 :                :     /*
                                546                 :                :      * Allow "silent", "default", or "verbose" values.
                                547                 :                :      */
                                548                 :             32 :     sval = defGetString(def);
  579 fujii@postgresql.org      549         [ +  + ]:             32 :     if (pg_strcasecmp(sval, "silent") == 0)
                                550                 :             11 :         return COPY_LOG_VERBOSITY_SILENT;
  764 msawada@postgresql.o      551         [ +  + ]:             21 :     if (pg_strcasecmp(sval, "default") == 0)
                                552                 :              4 :         return COPY_LOG_VERBOSITY_DEFAULT;
                                553         [ +  + ]:             17 :     if (pg_strcasecmp(sval, "verbose") == 0)
                                554                 :             12 :         return COPY_LOG_VERBOSITY_VERBOSE;
                                555                 :                : 
                                556         [ +  - ]:              5 :     ereport(ERROR,
                                557                 :                :             (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                                558                 :                :     /*- translator: first %s is the name of a COPY option, e.g. ON_ERROR */
                                559                 :                :              errmsg("COPY %s \"%s\" not recognized", "LOG_VERBOSITY", sval),
                                560                 :                :              parser_errposition(pstate, def->location)));
                                561                 :                :     return COPY_LOG_VERBOSITY_DEFAULT;  /* keep compiler quiet */
                                562                 :                : }
                                563                 :                : 
                                564                 :                : /*
                                565                 :                :  * Process the statement option list for COPY.
                                566                 :                :  *
                                567                 :                :  * Scan the options list (a list of DefElem) and transpose the information
                                568                 :                :  * into *opts_out, applying appropriate error checking.
                                569                 :                :  *
                                570                 :                :  * If 'opts_out' is not NULL, it is assumed to be filled with zeroes initially.
                                571                 :                :  *
                                572                 :                :  * This is exported so that external users of the COPY API can sanity-check
                                573                 :                :  * a list of options.  In that usage, 'opts_out' can be passed as NULL and
                                574                 :                :  * the collected data is just leaked until CurrentMemoryContext is reset.
                                575                 :                :  *
                                576                 :                :  * Note that additional checking, such as whether column names listed in FORCE
                                577                 :                :  * QUOTE actually exist, has to be applied later.  This just checks for
                                578                 :                :  * self-consistency of the options list.
                                579                 :                :  */
                                580                 :                : void
 3528 peter_e@gmx.net           581                 :           6839 : ProcessCopyOptions(ParseState *pstate,
                                582                 :                :                    CopyFormatOptions *opts_out,
                                583                 :                :                    bool is_from,
                                584                 :                :                    List *options)
                                585                 :                : {
 6070 tgl@sss.pgh.pa.us         586                 :           6839 :     bool        format_specified = false;
 2038 michael@paquier.xyz       587                 :           6839 :     bool        freeze_specified = false;
                                588                 :           6839 :     bool        header_specified = false;
  837 akorotkov@postgresql      589                 :           6839 :     bool        on_error_specified = false;
  764 msawada@postgresql.o      590                 :           6839 :     bool        log_verbosity_specified = false;
  574 fujii@postgresql.org      591                 :           6839 :     bool        reject_limit_specified = false;
   50 andrew@dunslane.net       592                 :GNC        6839 :     bool        force_array_specified = false;
                                593                 :                :     ListCell   *option;
                                594                 :                : 
                                595                 :                :     /* Support external use for option sanity checking */
 1989 heikki.linnakangas@i      596         [ +  + ]:CBC        6839 :     if (opts_out == NULL)
  146 michael@paquier.xyz       597                 :GNC          58 :         opts_out = palloc0_object(CopyFormatOptions);
                                598                 :                : 
 1989 heikki.linnakangas@i      599                 :CBC        6839 :     opts_out->file_encoding = -1;
                                600                 :                :     /* default format */
   50 andrew@dunslane.net       601                 :GNC        6839 :     opts_out->format = COPY_FORMAT_TEXT;
                                602                 :                : 
                                603                 :                :     /* Extract options from the statement node tree */
 5557 itagaki.takahiro@gma      604   [ +  +  +  +  :CBC        8468 :     foreach(option, options)
                                              +  + ]
                                605                 :                :     {
 3312 tgl@sss.pgh.pa.us         606                 :           1760 :         DefElem    *defel = lfirst_node(DefElem, option);
                                607                 :                : 
 6070                           608         [ +  + ]:           1760 :         if (strcmp(defel->defname, "format") == 0)
                                609                 :                :         {
 5912 bruce@momjian.us          610                 :            591 :             char       *fmt = defGetString(defel);
                                611                 :                : 
 6070 tgl@sss.pgh.pa.us         612         [ +  + ]:            591 :             if (format_specified)
 1755 dean.a.rasheed@gmail      613                 :              4 :                 errorConflictingDefElem(defel, pstate);
 6070 tgl@sss.pgh.pa.us         614                 :            587 :             format_specified = true;
                                615         [ +  + ]:            587 :             if (strcmp(fmt, "text") == 0)
   50 andrew@dunslane.net       616                 :GNC          52 :                 opts_out->format = COPY_FORMAT_TEXT;
 6070 tgl@sss.pgh.pa.us         617         [ +  + ]:CBC         535 :             else if (strcmp(fmt, "csv") == 0)
   50 andrew@dunslane.net       618                 :GNC         344 :                 opts_out->format = COPY_FORMAT_CSV;
 6070 tgl@sss.pgh.pa.us         619         [ +  + ]:CBC         191 :             else if (strcmp(fmt, "binary") == 0)
   50 andrew@dunslane.net       620                 :GNC          46 :                 opts_out->format = COPY_FORMAT_BINARY;
                                621         [ +  + ]:            145 :             else if (strcmp(fmt, "json") == 0)
                                622                 :            144 :                 opts_out->format = COPY_FORMAT_JSON;
                                623                 :                :             else
 6070 tgl@sss.pgh.pa.us         624         [ +  - ]:CBC           1 :                 ereport(ERROR,
                                625                 :                :                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                                626                 :                :                          errmsg("COPY format \"%s\" not recognized", fmt),
                                627                 :                :                          parser_errposition(pstate, defel->location)));
                                628                 :                :         }
 4903 simon@2ndQuadrant.co      629         [ +  + ]:           1169 :         else if (strcmp(defel->defname, "freeze") == 0)
                                630                 :                :         {
 2038 michael@paquier.xyz       631         [ +  + ]:             53 :             if (freeze_specified)
 1755 dean.a.rasheed@gmail      632                 :              4 :                 errorConflictingDefElem(defel, pstate);
 2038 michael@paquier.xyz       633                 :             49 :             freeze_specified = true;
 1989 heikki.linnakangas@i      634                 :             49 :             opts_out->freeze = defGetBoolean(defel);
                                635                 :                :         }
 8720 bruce@momjian.us          636         [ +  + ]:           1116 :         else if (strcmp(defel->defname, "delimiter") == 0)
                                637                 :                :         {
 1989 heikki.linnakangas@i      638         [ +  + ]:            195 :             if (opts_out->delim)
 1755 dean.a.rasheed@gmail      639                 :              4 :                 errorConflictingDefElem(defel, pstate);
 1989 heikki.linnakangas@i      640                 :            191 :             opts_out->delim = defGetString(defel);
                                641                 :                :         }
 8720 bruce@momjian.us          642         [ +  + ]:            921 :         else if (strcmp(defel->defname, "null") == 0)
                                643                 :                :         {
 1989 heikki.linnakangas@i      644         [ +  + ]:             89 :             if (opts_out->null_print)
 1755 dean.a.rasheed@gmail      645                 :              4 :                 errorConflictingDefElem(defel, pstate);
 1989 heikki.linnakangas@i      646                 :             85 :             opts_out->null_print = defGetString(defel);
                                647                 :                :         }
 1149 andrew@dunslane.net       648         [ +  + ]:            832 :         else if (strcmp(defel->defname, "default") == 0)
                                649                 :                :         {
                                650         [ -  + ]:             63 :             if (opts_out->default_print)
 1149 andrew@dunslane.net       651                 :UBC           0 :                 errorConflictingDefElem(defel, pstate);
 1149 andrew@dunslane.net       652                 :CBC          63 :             opts_out->default_print = defGetString(defel);
                                653                 :                :         }
 7668 bruce@momjian.us          654         [ +  + ]:            769 :         else if (strcmp(defel->defname, "header") == 0)
                                655                 :                :         {
 2038 michael@paquier.xyz       656         [ +  + ]:            184 :             if (header_specified)
 1755 dean.a.rasheed@gmail      657                 :              4 :                 errorConflictingDefElem(defel, pstate);
 2038 michael@paquier.xyz       658                 :            180 :             header_specified = true;
  306 fujii@postgresql.org      659                 :GNC         180 :             opts_out->header_line = defGetCopyHeaderOption(defel, is_from);
                                660                 :                :         }
 8051 bruce@momjian.us          661         [ +  + ]:CBC         585 :         else if (strcmp(defel->defname, "quote") == 0)
                                662                 :                :         {
 1989 heikki.linnakangas@i      663         [ +  + ]:             65 :             if (opts_out->quote)
 1755 dean.a.rasheed@gmail      664                 :              4 :                 errorConflictingDefElem(defel, pstate);
 1989 heikki.linnakangas@i      665                 :             61 :             opts_out->quote = defGetString(defel);
                                666                 :                :         }
 8051 bruce@momjian.us          667         [ +  + ]:            520 :         else if (strcmp(defel->defname, "escape") == 0)
                                668                 :                :         {
 1989 heikki.linnakangas@i      669         [ +  + ]:             60 :             if (opts_out->escape)
 1755 dean.a.rasheed@gmail      670                 :              4 :                 errorConflictingDefElem(defel, pstate);
 1989 heikki.linnakangas@i      671                 :             56 :             opts_out->escape = defGetString(defel);
                                672                 :                :         }
 8049 bruce@momjian.us          673         [ +  + ]:            460 :         else if (strcmp(defel->defname, "force_quote") == 0)
                                674                 :                :         {
 1989 heikki.linnakangas@i      675   [ +  +  -  + ]:             56 :             if (opts_out->force_quote || opts_out->force_quote_all)
 1755 dean.a.rasheed@gmail      676                 :              4 :                 errorConflictingDefElem(defel, pstate);
 6128 tgl@sss.pgh.pa.us         677   [ +  -  +  + ]:             52 :             if (defel->arg && IsA(defel->arg, A_Star))
 1989 heikki.linnakangas@i      678                 :             24 :                 opts_out->force_quote_all = true;
 6070 tgl@sss.pgh.pa.us         679   [ +  -  +  - ]:             28 :             else if (defel->arg && IsA(defel->arg, List))
 1989 heikki.linnakangas@i      680                 :             28 :                 opts_out->force_quote = castNode(List, defel->arg);
                                681                 :                :             else
 6070 tgl@sss.pgh.pa.us         682         [ #  # ]:UBC           0 :                 ereport(ERROR,
                                683                 :                :                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                                684                 :                :                          errmsg("argument to option \"%s\" must be a list of column names",
                                685                 :                :                                 defel->defname),
                                686                 :                :                          parser_errposition(pstate, defel->location)));
                                687                 :                :         }
 6070 tgl@sss.pgh.pa.us         688         [ +  + ]:CBC         404 :         else if (strcmp(defel->defname, "force_not_null") == 0)
                                689                 :                :         {
  948 andrew@dunslane.net       690   [ +  +  +  + ]:             62 :             if (opts_out->force_notnull || opts_out->force_notnull_all)
 1755 dean.a.rasheed@gmail      691                 :              8 :                 errorConflictingDefElem(defel, pstate);
  948 andrew@dunslane.net       692   [ +  -  +  + ]:             54 :             if (defel->arg && IsA(defel->arg, A_Star))
                                693                 :             24 :                 opts_out->force_notnull_all = true;
                                694   [ +  -  +  - ]:             30 :             else if (defel->arg && IsA(defel->arg, List))
 1989 heikki.linnakangas@i      695                 :             30 :                 opts_out->force_notnull = castNode(List, defel->arg);
                                696                 :                :             else
 6070 tgl@sss.pgh.pa.us         697         [ #  # ]:UBC           0 :                 ereport(ERROR,
                                698                 :                :                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                                699                 :                :                          errmsg("argument to option \"%s\" must be a list of column names",
                                700                 :                :                                 defel->defname),
                                701                 :                :                          parser_errposition(pstate, defel->location)));
                                702                 :                :         }
 4445 andrew@dunslane.net       703         [ +  + ]:CBC         342 :         else if (strcmp(defel->defname, "force_null") == 0)
                                704                 :                :         {
  948                           705   [ +  +  +  + ]:             62 :             if (opts_out->force_null || opts_out->force_null_all)
 1755 dean.a.rasheed@gmail      706                 :              8 :                 errorConflictingDefElem(defel, pstate);
  948 andrew@dunslane.net       707   [ +  -  +  + ]:             54 :             if (defel->arg && IsA(defel->arg, A_Star))
                                708                 :             24 :                 opts_out->force_null_all = true;
                                709   [ +  -  +  - ]:             30 :             else if (defel->arg && IsA(defel->arg, List))
 1989 heikki.linnakangas@i      710                 :             30 :                 opts_out->force_null = castNode(List, defel->arg);
                                711                 :                :             else
 4445 andrew@dunslane.net       712         [ #  # ]:UBC           0 :                 ereport(ERROR,
                                713                 :                :                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                                714                 :                :                          errmsg("argument to option \"%s\" must be a list of column names",
                                715                 :                :                                 defel->defname),
                                716                 :                :                          parser_errposition(pstate, defel->location)));
                                717                 :                :         }
 5045 tgl@sss.pgh.pa.us         718         [ +  + ]:CBC         280 :         else if (strcmp(defel->defname, "convert_selectively") == 0)
                                719                 :                :         {
                                720                 :                :             /*
                                721                 :                :              * Undocumented, not-accessible-from-SQL option: convert only the
                                722                 :                :              * named columns to binary form, storing the rest as NULLs. It's
                                723                 :                :              * allowed for the column list to be NIL.
                                724                 :                :              */
 1989 heikki.linnakangas@i      725         [ +  + ]:             11 :             if (opts_out->convert_selectively)
 1755 dean.a.rasheed@gmail      726                 :              4 :                 errorConflictingDefElem(defel, pstate);
 1989 heikki.linnakangas@i      727                 :              7 :             opts_out->convert_selectively = true;
 5045 tgl@sss.pgh.pa.us         728   [ +  +  +  - ]:              7 :             if (defel->arg == NULL || IsA(defel->arg, List))
 1989 heikki.linnakangas@i      729                 :              7 :                 opts_out->convert_select = castNode(List, defel->arg);
                                730                 :                :             else
 5045 tgl@sss.pgh.pa.us         731         [ #  # ]:UBC           0 :                 ereport(ERROR,
                                732                 :                :                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                                733                 :                :                          errmsg("argument to option \"%s\" must be a list of column names",
                                734                 :                :                                 defel->defname),
                                735                 :                :                          parser_errposition(pstate, defel->location)));
                                736                 :                :         }
 5552 itagaki.takahiro@gma      737         [ +  + ]:CBC         269 :         else if (strcmp(defel->defname, "encoding") == 0)
                                738                 :                :         {
 1989 heikki.linnakangas@i      739         [ +  + ]:             48 :             if (opts_out->file_encoding >= 0)
 1755 dean.a.rasheed@gmail      740                 :              4 :                 errorConflictingDefElem(defel, pstate);
 1989 heikki.linnakangas@i      741                 :             44 :             opts_out->file_encoding = pg_char_to_encoding(defGetString(defel));
                                742         [ -  + ]:             44 :             if (opts_out->file_encoding < 0)
 5552 itagaki.takahiro@gma      743         [ #  # ]:UBC           0 :                 ereport(ERROR,
                                744                 :                :                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                                745                 :                :                          errmsg("argument to option \"%s\" must be a valid encoding name",
                                746                 :                :                                 defel->defname),
                                747                 :                :                          parser_errposition(pstate, defel->location)));
                                748                 :                :         }
   50 andrew@dunslane.net       749         [ +  + ]:GNC         221 :         else if (strcmp(defel->defname, "force_array") == 0)
                                750                 :                :         {
                                751         [ -  + ]:             28 :             if (force_array_specified)
   50 andrew@dunslane.net       752                 :UNC           0 :                 errorConflictingDefElem(defel, pstate);
   50 andrew@dunslane.net       753                 :GNC          28 :             force_array_specified = true;
                                754                 :             28 :             opts_out->force_array = defGetBoolean(defel);
                                755                 :                :         }
  837 akorotkov@postgresql      756         [ +  + ]:CBC         193 :         else if (strcmp(defel->defname, "on_error") == 0)
                                757                 :                :         {
                                758         [ +  + ]:            126 :             if (on_error_specified)
  840                           759                 :              8 :                 errorConflictingDefElem(defel, pstate);
  837                           760                 :            118 :             on_error_specified = true;
                                761                 :            118 :             opts_out->on_error = defGetCopyOnErrorChoice(defel, pstate, is_from);
                                762                 :                :         }
  764 msawada@postgresql.o      763         [ +  + ]:             67 :         else if (strcmp(defel->defname, "log_verbosity") == 0)
                                764                 :                :         {
                                765         [ +  + ]:             36 :             if (log_verbosity_specified)
                                766                 :              4 :                 errorConflictingDefElem(defel, pstate);
                                767                 :             32 :             log_verbosity_specified = true;
                                768                 :             32 :             opts_out->log_verbosity = defGetCopyLogVerbosityChoice(defel, pstate);
                                769                 :                :         }
  574 fujii@postgresql.org      770         [ +  - ]:             31 :         else if (strcmp(defel->defname, "reject_limit") == 0)
                                771                 :                :         {
                                772         [ -  + ]:             31 :             if (reject_limit_specified)
  574 fujii@postgresql.org      773                 :UBC           0 :                 errorConflictingDefElem(defel, pstate);
  574 fujii@postgresql.org      774                 :CBC          31 :             reject_limit_specified = true;
                                775                 :             31 :             opts_out->reject_limit = defGetCopyRejectLimitOption(defel);
                                776                 :                :         }
                                777                 :                :         else
 6070 tgl@sss.pgh.pa.us         778         [ #  # ]:UBC           0 :             ereport(ERROR,
                                779                 :                :                     (errcode(ERRCODE_SYNTAX_ERROR),
                                780                 :                :                      errmsg("option \"%s\" not recognized",
                                781                 :                :                             defel->defname),
                                782                 :                :                      parser_errposition(pstate, defel->location)));
                                783                 :                :     }
                                784                 :                : 
                                785                 :                :     /*
                                786                 :                :      * Check for incompatible options (must do these three before inserting
                                787                 :                :      * defaults)
                                788                 :                :      */
   50 andrew@dunslane.net       789         [ +  + ]:GNC        6708 :     if (opts_out->delim &&
                                790         [ +  + ]:            187 :         (opts_out->format == COPY_FORMAT_BINARY ||
                                791         [ +  + ]:            183 :          opts_out->format == COPY_FORMAT_JSON))
 8325 tgl@sss.pgh.pa.us         792   [ +  -  +  + ]:CBC           8 :         ereport(ERROR,
                                793                 :                :                 errcode(ERRCODE_SYNTAX_ERROR),
                                794                 :                :                 opts_out->format == COPY_FORMAT_BINARY
                                795                 :                :                 ? errmsg("cannot specify %s in BINARY mode", "DELIMITER")
                                796                 :                :                 : errmsg("cannot specify %s in JSON mode", "DELIMITER"));
                                797                 :                : 
   50 andrew@dunslane.net       798         [ +  + ]:GNC        6700 :     if (opts_out->null_print &&
                                799         [ +  + ]:             81 :         (opts_out->format == COPY_FORMAT_BINARY ||
                                800         [ +  + ]:             77 :          opts_out->format == COPY_FORMAT_JSON))
 8325 tgl@sss.pgh.pa.us         801   [ +  -  +  + ]:CBC           8 :         ereport(ERROR,
                                802                 :                :                 errcode(ERRCODE_SYNTAX_ERROR),
                                803                 :                :                 opts_out->format == COPY_FORMAT_BINARY
                                804                 :                :                 ? errmsg("cannot specify %s in BINARY mode", "NULL")
                                805                 :                :                 : errmsg("cannot specify %s in JSON mode", "NULL"));
                                806                 :                : 
   50 andrew@dunslane.net       807         [ +  + ]:GNC        6692 :     if (opts_out->default_print &&
                                808         [ +  + ]:             63 :         (opts_out->format == COPY_FORMAT_BINARY ||
                                809         [ +  + ]:             59 :          opts_out->format == COPY_FORMAT_JSON))
 1149 andrew@dunslane.net       810   [ +  -  +  + ]:CBC           8 :         ereport(ERROR,
                                811                 :                :                 errcode(ERRCODE_SYNTAX_ERROR),
                                812                 :                :                 opts_out->format == COPY_FORMAT_BINARY
                                813                 :                :                 ? errmsg("cannot specify %s in BINARY mode", "DEFAULT")
                                814                 :                :                 : errmsg("cannot specify %s in JSON mode", "DEFAULT"));
                                815                 :                : 
                                816                 :                :     /* Set defaults for omitted options */
 1989 heikki.linnakangas@i      817         [ +  + ]:           6684 :     if (!opts_out->delim)
   50 andrew@dunslane.net       818         [ +  + ]:GNC        6505 :         opts_out->delim = (opts_out->format == COPY_FORMAT_CSV) ? "," : "\t";
                                819                 :                : 
 1989 heikki.linnakangas@i      820         [ +  + ]:CBC        6684 :     if (!opts_out->null_print)
   50 andrew@dunslane.net       821         [ +  + ]:GNC        6611 :         opts_out->null_print = (opts_out->format == COPY_FORMAT_CSV) ? "" : "\\N";
 1989 heikki.linnakangas@i      822                 :CBC        6684 :     opts_out->null_print_len = strlen(opts_out->null_print);
                                823                 :                : 
   50 andrew@dunslane.net       824         [ +  + ]:GNC        6684 :     if (opts_out->format == COPY_FORMAT_CSV)
                                825                 :                :     {
 1989 heikki.linnakangas@i      826         [ +  + ]:CBC         332 :         if (!opts_out->quote)
                                827                 :            281 :             opts_out->quote = "\"";
                                828         [ +  + ]:            332 :         if (!opts_out->escape)
                                829                 :            287 :             opts_out->escape = opts_out->quote;
                                830                 :                :     }
                                831                 :                : 
                                832                 :                :     /* Only single-byte delimiter strings are supported. */
                                833         [ +  + ]:           6684 :     if (strlen(opts_out->delim) != 1)
 8051 bruce@momjian.us          834         [ +  - ]:              1 :         ereport(ERROR,
                                835                 :                :                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                                836                 :                :                  errmsg("COPY delimiter must be a single one-byte character")));
                                837                 :                : 
                                838                 :                :     /* Disallow end-of-line characters */
 1989 heikki.linnakangas@i      839         [ +  - ]:           6683 :     if (strchr(opts_out->delim, '\r') != NULL ||
                                840         [ +  + ]:           6683 :         strchr(opts_out->delim, '\n') != NULL)
 7396 bruce@momjian.us          841         [ +  - ]:              1 :         ereport(ERROR,
                                842                 :                :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                                843                 :                :                  errmsg("COPY delimiter cannot be newline or carriage return")));
                                844                 :                : 
 1989 heikki.linnakangas@i      845         [ +  - ]:           6682 :     if (strchr(opts_out->null_print, '\r') != NULL ||
                                846         [ +  + ]:           6682 :         strchr(opts_out->null_print, '\n') != NULL)
 7396 bruce@momjian.us          847         [ +  - ]:              1 :         ereport(ERROR,
                                848                 :                :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                                849                 :                :                  errmsg("COPY null representation cannot use newline or carriage return")));
                                850                 :                : 
 1149 andrew@dunslane.net       851         [ +  + ]:           6681 :     if (opts_out->default_print)
                                852                 :                :     {
                                853                 :             55 :         opts_out->default_print_len = strlen(opts_out->default_print);
                                854                 :                : 
                                855         [ +  + ]:             55 :         if (strchr(opts_out->default_print, '\r') != NULL ||
                                856         [ +  + ]:             51 :             strchr(opts_out->default_print, '\n') != NULL)
                                857         [ +  - ]:              8 :             ereport(ERROR,
                                858                 :                :                     (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                                859                 :                :                      errmsg("COPY default representation cannot use newline or carriage return")));
                                860                 :                :     }
                                861                 :                : 
                                862                 :                :     /*
                                863                 :                :      * Disallow unsafe delimiter characters in non-CSV mode.  We can't allow
                                864                 :                :      * backslash because it would be ambiguous.  We can't allow the other
                                865                 :                :      * cases because data characters matching the delimiter must be
                                866                 :                :      * backslashed, and certain backslash combinations are interpreted
                                867                 :                :      * non-literally by COPY IN.  Disallowing all lower case ASCII letters is
                                868                 :                :      * more than strictly necessary, but seems best for consistency and
                                869                 :                :      * future-proofing.  Likewise we disallow all digits though only octal
                                870                 :                :      * digits are actually dangerous.
                                871                 :                :      */
   50 andrew@dunslane.net       872         [ +  + ]:GNC        6673 :     if (opts_out->format != COPY_FORMAT_CSV &&
 6704 tgl@sss.pgh.pa.us         873                 :CBC        6344 :         strchr("\\.abcdefghijklmnopqrstuvwxyz0123456789",
 1989 heikki.linnakangas@i      874         [ +  + ]:           6344 :                opts_out->delim[0]) != NULL)
 7396 bruce@momjian.us          875         [ +  - ]:              5 :         ereport(ERROR,
                                876                 :                :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                                877                 :                :                  errmsg("COPY delimiter cannot be \"%s\"", opts_out->delim)));
                                878                 :                : 
                                879                 :                :     /* Check header */
   50 andrew@dunslane.net       880         [ +  + ]:GNC        6668 :     if (opts_out->header_line != COPY_HEADER_FALSE &&
                                881         [ +  + ]:            137 :         (opts_out->format == COPY_FORMAT_BINARY ||
                                882         [ +  + ]:            136 :          opts_out->format == COPY_FORMAT_JSON))
 7668 bruce@momjian.us          883   [ +  -  +  + ]:CBC           9 :         ereport(ERROR,
                                884                 :                :                 errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                                885                 :                :         /*- translator: %s is the name of a COPY option, e.g. ON_ERROR */
                                886                 :                :                 opts_out->format == COPY_FORMAT_BINARY
                                887                 :                :                 ? errmsg("cannot specify %s in BINARY mode", "HEADER")
                                888                 :                :                 : errmsg("cannot specify %s in JSON mode", "HEADER"));
                                889                 :                : 
                                890                 :                :     /* Check quote */
   50 andrew@dunslane.net       891   [ +  +  +  + ]:GNC        6659 :     if (opts_out->format != COPY_FORMAT_CSV && opts_out->quote != NULL)
 8051 bruce@momjian.us          892         [ +  - ]:CBC           6 :         ereport(ERROR,
                                893                 :                :                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                                894                 :                :         /*- translator: %s is the name of a COPY option, e.g. ON_ERROR */
                                895                 :                :                  errmsg("COPY %s requires CSV mode", "QUOTE")));
                                896                 :                : 
   50 andrew@dunslane.net       897   [ +  +  +  + ]:GNC        6653 :     if (opts_out->format == COPY_FORMAT_CSV && strlen(opts_out->quote) != 1)
 8051 bruce@momjian.us          898         [ +  - ]:CBC           1 :         ereport(ERROR,
                                899                 :                :                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                                900                 :                :                  errmsg("COPY quote must be a single one-byte character")));
                                901                 :                : 
   50 andrew@dunslane.net       902   [ +  +  +  + ]:GNC        6652 :     if (opts_out->format == COPY_FORMAT_CSV && opts_out->delim[0] == opts_out->quote[0])
 6701 andrew@dunslane.net       903         [ +  - ]:CBC           1 :         ereport(ERROR,
                                904                 :                :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                                905                 :                :                  errmsg("COPY delimiter and quote must be different")));
                                906                 :                : 
                                907                 :                :     /* Check escape */
   50 andrew@dunslane.net       908   [ +  +  +  + ]:GNC        6651 :     if (opts_out->format != COPY_FORMAT_CSV && opts_out->escape != NULL)
 8051 bruce@momjian.us          909         [ +  - ]:CBC           7 :         ereport(ERROR,
                                910                 :                :                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                                911                 :                :         /*- translator: %s is the name of a COPY option, e.g. ON_ERROR */
                                912                 :                :                  errmsg("COPY %s requires CSV mode", "ESCAPE")));
                                913                 :                : 
   50 andrew@dunslane.net       914   [ +  +  +  + ]:GNC        6644 :     if (opts_out->format == COPY_FORMAT_CSV && strlen(opts_out->escape) != 1)
 8051 bruce@momjian.us          915         [ +  - ]:CBC           1 :         ereport(ERROR,
                                916                 :                :                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                                917                 :                :                  errmsg("COPY escape must be a single one-byte character")));
                                918                 :                : 
                                919                 :                :     /* Check force_quote */
   50 andrew@dunslane.net       920   [ +  +  +  +  :GNC        6643 :     if (opts_out->format != COPY_FORMAT_CSV && (opts_out->force_quote || opts_out->force_quote_all))
                                              +  + ]
 8051 bruce@momjian.us          921         [ +  - ]:CBC          12 :         ereport(ERROR,
                                922                 :                :                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                                923                 :                :         /*- translator: %s is the name of a COPY option, e.g. ON_ERROR */
                                924                 :                :                  errmsg("COPY %s requires CSV mode", "FORCE_QUOTE")));
 1989 heikki.linnakangas@i      925   [ +  +  +  +  :           6631 :     if ((opts_out->force_quote || opts_out->force_quote_all) && is_from)
                                              +  + ]
 8051 bruce@momjian.us          926         [ +  - ]:              8 :         ereport(ERROR,
                                927                 :                :                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                                928                 :                :         /*- translator: first %s is the name of a COPY option, e.g. ON_ERROR,
                                929                 :                :          second %s is a COPY with direction, e.g. COPY TO */
                                930                 :                :                  errmsg("COPY %s cannot be used with %s", "FORCE_QUOTE",
                                931                 :                :                         "COPY FROM")));
                                932                 :                : 
                                933                 :                :     /* Check force_notnull */
   50 andrew@dunslane.net       934   [ +  +  +  + ]:GNC        6623 :     if (opts_out->format != COPY_FORMAT_CSV && (opts_out->force_notnull != NIL ||
                                935         [ +  + ]:           6300 :                                                 opts_out->force_notnull_all))
 8051 bruce@momjian.us          936         [ +  - ]:CBC          13 :         ereport(ERROR,
                                937                 :                :                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                                938                 :                :         /*- translator: %s is the name of a COPY option, e.g. ON_ERROR */
                                939                 :                :                  errmsg("COPY %s requires CSV mode", "FORCE_NOT_NULL")));
  565 michael@paquier.xyz       940   [ +  +  +  + ]:           6610 :     if ((opts_out->force_notnull != NIL || opts_out->force_notnull_all) &&
                                941         [ +  + ]:             33 :         !is_from)
 8051 bruce@momjian.us          942         [ +  - ]:              8 :         ereport(ERROR,
                                943                 :                :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                                944                 :                :         /*- translator: first %s is the name of a COPY option, e.g. ON_ERROR,
                                945                 :                :          second %s is a COPY with direction, e.g. COPY TO */
                                946                 :                :                  errmsg("COPY %s cannot be used with %s", "FORCE_NOT_NULL",
                                947                 :                :                         "COPY TO")));
                                948                 :                : 
                                949                 :                :     /* Check force_null */
   50 andrew@dunslane.net       950   [ +  +  +  + ]:GNC        6602 :     if (opts_out->format != COPY_FORMAT_CSV && (opts_out->force_null != NIL ||
                                951         [ +  + ]:           6288 :                                                 opts_out->force_null_all))
 4445 andrew@dunslane.net       952         [ +  - ]:CBC          12 :         ereport(ERROR,
                                953                 :                :                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                                954                 :                :         /*- translator: %s is the name of a COPY option, e.g. ON_ERROR */
                                955                 :                :                  errmsg("COPY %s requires CSV mode", "FORCE_NULL")));
                                956                 :                : 
  565 michael@paquier.xyz       957   [ +  +  +  + ]:           6590 :     if ((opts_out->force_null != NIL || opts_out->force_null_all) &&
                                958         [ +  + ]:             33 :         !is_from)
 4445 andrew@dunslane.net       959         [ +  - ]:              8 :         ereport(ERROR,
                                960                 :                :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                                961                 :                :         /*- translator: first %s is the name of a COPY option, e.g. ON_ERROR,
                                962                 :                :          second %s is a COPY with direction, e.g. COPY TO */
                                963                 :                :                  errmsg("COPY %s cannot be used with %s", "FORCE_NULL",
                                964                 :                :                         "COPY TO")));
                                965                 :                : 
                                966                 :                :     /* Don't allow the delimiter to appear in the null string. */
 1989 heikki.linnakangas@i      967         [ +  + ]:           6582 :     if (strchr(opts_out->null_print, opts_out->delim[0]) != NULL)
 8051 bruce@momjian.us          968         [ +  - ]:              1 :         ereport(ERROR,
                                969                 :                :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                                970                 :                :         /*- translator: %s is the name of a COPY option, e.g. NULL */
                                971                 :                :                  errmsg("COPY delimiter character must not appear in the %s specification",
                                972                 :                :                         "NULL")));
                                973                 :                : 
                                974                 :                :     /* Don't allow the CSV quote char to appear in the null string. */
   50 andrew@dunslane.net       975         [ +  + ]:GNC        6581 :     if (opts_out->format == COPY_FORMAT_CSV &&
 1989 heikki.linnakangas@i      976         [ +  + ]:CBC         301 :         strchr(opts_out->null_print, opts_out->quote[0]) != NULL)
 8051 bruce@momjian.us          977         [ +  - ]:              1 :         ereport(ERROR,
                                978                 :                :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                                979                 :                :         /*- translator: %s is the name of a COPY option, e.g. NULL */
                                980                 :                :                  errmsg("CSV quote character must not appear in the %s specification",
                                981                 :                :                         "NULL")));
                                982                 :                : 
                                983                 :                :     /* Check freeze */
  904                           984   [ +  +  -  + ]:           6580 :     if (opts_out->freeze && !is_from)
  904 bruce@momjian.us          985         [ #  # ]:UBC           0 :         ereport(ERROR,
                                986                 :                :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                                987                 :                :         /*- translator: first %s is the name of a COPY option, e.g. ON_ERROR,
                                988                 :                :          second %s is a COPY with direction, e.g. COPY TO */
                                989                 :                :                  errmsg("COPY %s cannot be used with %s", "FREEZE",
                                990                 :                :                         "COPY TO")));
                                991                 :                : 
                                992                 :                :     /* Check json format */
   50 andrew@dunslane.net       993   [ +  +  +  + ]:GNC        6580 :     if (opts_out->format == COPY_FORMAT_JSON && is_from)
                                994         [ +  - ]:              4 :         ereport(ERROR,
                                995                 :                :                 errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                                996                 :                :                 errmsg("COPY %s is not supported for %s", "FORMAT JSON", "COPY FROM"));
                                997                 :                : 
                                998   [ +  +  +  + ]:           6576 :     if (opts_out->format != COPY_FORMAT_JSON && opts_out->force_array)
                                999         [ +  - ]:              4 :         ereport(ERROR,
                               1000                 :                :                 errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                               1001                 :                :                 errmsg("COPY %s can only be used with JSON mode", "FORCE_ARRAY"));
                               1002                 :                : 
 1149 andrew@dunslane.net      1003         [ +  + ]:CBC        6572 :     if (opts_out->default_print)
                               1004                 :                :     {
                               1005         [ +  + ]:             47 :         if (!is_from)
                               1006         [ +  - ]:              4 :             ereport(ERROR,
                               1007                 :                :                     (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                               1008                 :                :             /*- translator: first %s is the name of a COPY option, e.g. ON_ERROR,
                               1009                 :                :              second %s is a COPY with direction, e.g. COPY TO */
                               1010                 :                :                      errmsg("COPY %s cannot be used with %s", "DEFAULT",
                               1011                 :                :                             "COPY TO")));
                               1012                 :                : 
                               1013                 :                :         /* Don't allow the delimiter to appear in the default string. */
                               1014         [ +  + ]:             43 :         if (strchr(opts_out->default_print, opts_out->delim[0]) != NULL)
                               1015         [ +  - ]:              4 :             ereport(ERROR,
                               1016                 :                :                     (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                               1017                 :                :             /*- translator: %s is the name of a COPY option, e.g. NULL */
                               1018                 :                :                      errmsg("COPY delimiter character must not appear in the %s specification",
                               1019                 :                :                             "DEFAULT")));
                               1020                 :                : 
                               1021                 :                :         /* Don't allow the CSV quote char to appear in the default string. */
   50 andrew@dunslane.net      1022         [ +  + ]:GNC          39 :         if (opts_out->format == COPY_FORMAT_CSV &&
 1149 andrew@dunslane.net      1023         [ +  + ]:CBC          19 :             strchr(opts_out->default_print, opts_out->quote[0]) != NULL)
                               1024         [ +  - ]:              4 :             ereport(ERROR,
                               1025                 :                :                     (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                               1026                 :                :             /*- translator: %s is the name of a COPY option, e.g. NULL */
                               1027                 :                :                      errmsg("CSV quote character must not appear in the %s specification",
                               1028                 :                :                             "DEFAULT")));
                               1029                 :                : 
                               1030                 :                :         /* Don't allow the NULL and DEFAULT string to be the same */
                               1031         [ +  + ]:             35 :         if (opts_out->null_print_len == opts_out->default_print_len &&
                               1032                 :             16 :             strncmp(opts_out->null_print, opts_out->default_print,
                               1033         [ +  + ]:             16 :                     opts_out->null_print_len) == 0)
                               1034         [ +  - ]:              4 :             ereport(ERROR,
                               1035                 :                :                     (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                               1036                 :                :                      errmsg("NULL specification and DEFAULT specification cannot be the same")));
                               1037                 :                :     }
                               1038                 :                :     /* Check on_error */
   50 andrew@dunslane.net      1039   [ +  +  +  + ]:GNC        6556 :     if (opts_out->format == COPY_FORMAT_BINARY && opts_out->on_error != COPY_ON_ERROR_STOP)
  574 fujii@postgresql.org     1040         [ +  - ]:CBC           9 :         ereport(ERROR,
                               1041                 :                :                 (errcode(ERRCODE_SYNTAX_ERROR),
                               1042                 :                :                  errmsg("only ON_ERROR STOP is allowed in BINARY mode")));
                               1043                 :                : 
   63 peter@eisentraut.org     1044   [ +  +  +  + ]:GNC        6547 :     if (opts_out->reject_limit && opts_out->on_error != COPY_ON_ERROR_IGNORE)
  574 fujii@postgresql.org     1045         [ +  - ]:CBC          13 :         ereport(ERROR,
                               1046                 :                :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                               1047                 :                :         /*- translator: first and second %s are the names of COPY option, e.g.
                               1048                 :                :          * ON_ERROR, third is the value of the COPY option, e.g. IGNORE */
                               1049                 :                :                  errmsg("COPY %s requires %s to be set to %s",
                               1050                 :                :                         "REJECT_LIMIT", "ON_ERROR", "IGNORE")));
 5553 tgl@sss.pgh.pa.us        1051                 :           6534 : }
                               1052                 :                : 
                               1053                 :                : /*
                               1054                 :                :  * CopyGetAttnums - build an integer list of attnums to be copied
                               1055                 :                :  *
                               1056                 :                :  * The input attnamelist is either the user-specified column list,
                               1057                 :                :  * or NIL if there was none (in which case we want all the non-dropped
                               1058                 :                :  * columns).
                               1059                 :                :  *
                               1060                 :                :  * We don't include generated columns in the generated full list and we don't
                               1061                 :                :  * allow them to be specified explicitly.  They don't make sense for COPY
                               1062                 :                :  * FROM, but we could possibly allow them for COPY TO.  But this way it's at
                               1063                 :                :  * least ensured that whatever we copy out can be copied back in.
                               1064                 :                :  *
                               1065                 :                :  * rel can be NULL ... it's only used for error reports.
                               1066                 :                :  */
                               1067                 :                : List *
 1989 heikki.linnakangas@i     1068                 :          12790 : CopyGetAttnums(TupleDesc tupDesc, Relation rel, List *attnamelist)
                               1069                 :                : {
                               1070                 :          12790 :     List       *attnums = NIL;
                               1071                 :                : 
                               1072         [ +  + ]:          12790 :     if (attnamelist == NIL)
                               1073                 :                :     {
                               1074                 :                :         /* Generate default column list */
 8644 bruce@momjian.us         1075                 :           2618 :         int         attr_count = tupDesc->natts;
                               1076                 :                :         int         i;
                               1077                 :                : 
 8680                          1078         [ +  + ]:           9526 :         for (i = 0; i < attr_count; i++)
                               1079                 :                :         {
  501 drowley@postgresql.o     1080                 :           6908 :             CompactAttribute *attr = TupleDescCompactAttr(tupDesc, i);
                               1081                 :                : 
                               1082   [ +  +  +  + ]:           6908 :             if (attr->attisdropped || attr->attgenerated)
 2593 peter@eisentraut.org     1083                 :            209 :                 continue;
 8014 neilc@samurai.com        1084                 :           6699 :             attnums = lappend_int(attnums, i + 1);
                               1085                 :                :         }
                               1086                 :                :     }
                               1087                 :                :     else
                               1088                 :                :     {
                               1089                 :                :         /* Validate the user-supplied list and extract attnums */
                               1090                 :                :         ListCell   *l;
                               1091                 :                : 
 8677 tgl@sss.pgh.pa.us        1092   [ +  -  +  +  :          45184 :         foreach(l, attnamelist)
                                              +  + ]
                               1093                 :                :         {
 8660                          1094                 :          35068 :             char       *name = strVal(lfirst(l));
                               1095                 :                :             int         attnum;
                               1096                 :                :             int         i;
                               1097                 :                : 
                               1098                 :                :             /* Lookup column name */
 7188                          1099                 :          35068 :             attnum = InvalidAttrNumber;
                               1100         [ +  + ]:        4971093 :             for (i = 0; i < tupDesc->natts; i++)
                               1101                 :                :             {
 3180 andres@anarazel.de       1102                 :        4971073 :                 Form_pg_attribute att = TupleDescAttr(tupDesc, i);
                               1103                 :                : 
                               1104         [ +  + ]:        4971073 :                 if (att->attisdropped)
 7188 tgl@sss.pgh.pa.us        1105                 :            444 :                     continue;
 3180 andres@anarazel.de       1106         [ +  + ]:        4970629 :                 if (namestrcmp(&(att->attname), name) == 0)
                               1107                 :                :                 {
 2593 peter@eisentraut.org     1108         [ +  + ]:          35048 :                     if (att->attgenerated)
                               1109         [ +  - ]:             32 :                         ereport(ERROR,
                               1110                 :                :                                 (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
                               1111                 :                :                                  errmsg("column \"%s\" is a generated column",
                               1112                 :                :                                         name),
                               1113                 :                :                                  errdetail("Generated columns cannot be used in COPY.")));
 3180 andres@anarazel.de       1114                 :          35016 :                     attnum = att->attnum;
 7188 tgl@sss.pgh.pa.us        1115                 :          35016 :                     break;
                               1116                 :                :                 }
                               1117                 :                :             }
 7348                          1118         [ +  + ]:          35036 :             if (attnum == InvalidAttrNumber)
                               1119                 :                :             {
 7188                          1120         [ +  - ]:             20 :                 if (rel != NULL)
                               1121         [ +  - ]:             20 :                     ereport(ERROR,
                               1122                 :                :                             (errcode(ERRCODE_UNDEFINED_COLUMN),
                               1123                 :                :                              errmsg("column \"%s\" of relation \"%s\" does not exist",
                               1124                 :                :                                     name, RelationGetRelationName(rel))));
                               1125                 :                :                 else
 7188 tgl@sss.pgh.pa.us        1126         [ #  # ]:UBC           0 :                     ereport(ERROR,
                               1127                 :                :                             (errcode(ERRCODE_UNDEFINED_COLUMN),
                               1128                 :                :                              errmsg("column \"%s\" does not exist",
                               1129                 :                :                                     name)));
                               1130                 :                :             }
                               1131                 :                :             /* Check for duplicates */
 8014 neilc@samurai.com        1132         [ +  + ]:CBC       35016 :             if (list_member_int(attnums, attnum))
 8325 tgl@sss.pgh.pa.us        1133         [ +  - ]:              4 :                 ereport(ERROR,
                               1134                 :                :                         (errcode(ERRCODE_DUPLICATE_COLUMN),
                               1135                 :                :                          errmsg("column \"%s\" specified more than once",
                               1136                 :                :                                 name)));
 8014 neilc@samurai.com        1137                 :          35012 :             attnums = lappend_int(attnums, attnum);
                               1138                 :                :         }
                               1139                 :                :     }
                               1140                 :                : 
 8677 tgl@sss.pgh.pa.us        1141                 :          12734 :     return attnums;
                               1142                 :                : }
        

Generated by: LCOV version 2.5.0-beta