LCOV - differential code coverage report
Current view: top level - src/backend/commands - copy.c (source / functions) Coverage Total Hit UNC LBC UIC UBC GBC GIC GNC CBC EUB ECB DUB DCB
Current: Differential Code Coverage HEAD vs 15 Lines: 92.4 % 316 292 1 6 11 6 5 143 30 114 12 167 1 5
Current Date: 2023-04-08 17:13:01 Functions: 100.0 % 4 4 3 1 3
Baseline: 15 Line coverage date bins:
Baseline Date: 2023-04-08 15:09:40 [..60] days: 95.8 % 24 23 1 1 22 1
Legend: Lines: hit not hit (120,180] days: 100.0 % 8 8 8
(180,240] days: 100.0 % 2 2 2 2
(240..) days: 91.8 % 282 259 6 11 6 5 140 114 11 145
Function coverage date bins:
(240..) days: 57.1 % 7 4 3 1 3

 Age         Owner                  TLA  Line data    Source code
                                  1                 : /*-------------------------------------------------------------------------
                                  2                 :  *
                                  3                 :  * copy.c
                                  4                 :  *      Implements the COPY utility command
                                  5                 :  *
                                  6                 :  * Portions Copyright (c) 1996-2023, 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 "optimizer/optimizer.h"
                                 32                 : #include "parser/parse_coerce.h"
                                 33                 : #include "parser/parse_collate.h"
                                 34                 : #include "parser/parse_expr.h"
                                 35                 : #include "parser/parse_relation.h"
                                 36                 : #include "rewrite/rewriteHandler.h"
                                 37                 : #include "utils/acl.h"
                                 38                 : #include "utils/builtins.h"
                                 39                 : #include "utils/lsyscache.h"
                                 40                 : #include "utils/memutils.h"
                                 41                 : #include "utils/rel.h"
                                 42                 : #include "utils/rls.h"
                                 43                 : 
                                 44                 : /*
                                 45                 :  *   DoCopy executes the SQL COPY statement
                                 46                 :  *
                                 47                 :  * Either unload or reload contents of table <relation>, depending on <from>.
                                 48                 :  * (<from> = true means we are inserting into the table.)  In the "TO" case
                                 49                 :  * we also support copying the output of an arbitrary SELECT, INSERT, UPDATE
                                 50                 :  * or DELETE query.
                                 51                 :  *
                                 52                 :  * If <pipe> is false, transfer is between the table and the file named
                                 53                 :  * <filename>.  Otherwise, transfer is between the table and our regular
                                 54                 :  * input/output stream. The latter could be either stdin/stdout or a
                                 55                 :  * socket, depending on whether we're running under Postmaster control.
                                 56                 :  *
                                 57                 :  * Do not allow a Postgres user without the 'pg_read_server_files' or
                                 58                 :  * 'pg_write_server_files' role to read from or write to a file.
                                 59                 :  *
                                 60                 :  * Do not allow the copy if user doesn't have proper permission to access
                                 61                 :  * the table or the specifically requested columns.
                                 62                 :  */
                                 63                 : void
 2276 tgl                        64 CBC        4500 : DoCopy(ParseState *pstate, const CopyStmt *stmt,
                                 65                 :        int stmt_location, int stmt_len,
                                 66                 :        uint64 *processed)
                                 67                 : {
 4435 itagaki.takahiro           68            4500 :     bool        is_from = stmt->is_from;
                                 69            4500 :     bool        pipe = (stmt->filename == NULL);
                                 70                 :     Relation    rel;
                                 71                 :     Oid         relid;
 2276 tgl                        72            4500 :     RawStmt    *query = NULL;
 1466 andres                     73            4500 :     Node       *whereClause = NULL;
                                 74                 : 
                                 75                 :     /*
                                 76                 :      * Disallow COPY to/from file or program except to users with the
                                 77                 :      * appropriate role.
                                 78                 :      */
 1829 sfrost                     79            4500 :     if (!pipe)
                                 80                 :     {
 3693 heikki.linnakangas         81             448 :         if (stmt->is_program)
                                 82                 :         {
  377 mail                       83 UBC           0 :             if (!has_privs_of_role(GetUserId(), ROLE_PG_EXECUTE_SERVER_PROGRAM))
 1829 sfrost                     84               0 :                 ereport(ERROR,
                                 85                 :                         (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
                                 86                 :                          errmsg("permission denied to COPY to or from an external program"),
                                 87                 :                          errdetail("Only roles with privileges of the \"%s\" role may COPY to or from an external program.",
                                 88                 :                                    "pg_execute_server_program"),
                                 89                 :                          errhint("Anyone can COPY to stdout or from stdin. "
                                 90                 :                                  "psql's \\copy command also works for anyone.")));
                                 91                 :         }
                                 92                 :         else
                                 93                 :         {
  377 mail                       94 GIC         448 :             if (is_from && !has_privs_of_role(GetUserId(), ROLE_PG_READ_SERVER_FILES))
 1829 sfrost                     95 UIC           0 :                 ereport(ERROR,
 1829 sfrost                     96 ECB             :                         (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
                                 97                 :                          errmsg("permission denied to COPY from a file"),
                                 98                 :                          errdetail("Only roles with privileges of the \"%s\" role may COPY from a file.",
                                 99                 :                                    "pg_read_server_files"),
                                100                 :                          errhint("Anyone can COPY to stdout or from stdin. "
                                101                 :                                  "psql's \\copy command also works for anyone.")));
                                102                 : 
  377 mail                      103 GIC         448 :             if (!is_from && !has_privs_of_role(GetUserId(), ROLE_PG_WRITE_SERVER_FILES))
 1829 sfrost                    104 UIC           0 :                 ereport(ERROR,
                                105                 :                         (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
                                106                 :                          errmsg("permission denied to COPY to a file"),
                                107                 :                          errdetail("Only roles with privileges of the \"%s\" role may COPY to a file.",
                                108                 :                                    "pg_write_server_files"),
 1829 sfrost                    109 ECB             :                          errhint("Anyone can COPY to stdout or from stdin. "
 1829 sfrost                    110 EUB             :                                  "psql's \\copy command also works for anyone.")));
                                111                 :         }
                                112                 :     }
                                113                 : 
 4435 itagaki.takahiro          114 GIC        4500 :     if (stmt->relation)
                                115                 :     {
 1652 tgl                       116            4307 :         LOCKMODE    lockmode = is_from ? RowExclusiveLock : AccessShareLock;
                                117                 :         ParseNamespaceItem *nsitem;
                                118                 :         RTEPermissionInfo *perminfo;
                                119                 :         TupleDesc   tupDesc;
 4382 bruce                     120 ECB             :         List       *attnums;
                                121                 :         ListCell   *cur;
 4435 itagaki.takahiro          122                 : 
 4435 itagaki.takahiro          123 GIC        4307 :         Assert(!stmt->query);
                                124                 : 
                                125                 :         /* Open and lock the relation, using the appropriate lock type. */
 1539 andres                    126            4307 :         rel = table_openrv(stmt->relation, lockmode);
                                127                 : 
 3753 rhaas                     128            4306 :         relid = RelationGetRelid(rel);
 3753 rhaas                     129 ECB             : 
 1193 tgl                       130 GIC        4306 :         nsitem = addRangeTableEntryForRelation(pstate, rel, lockmode,
                                131                 :                                                NULL, false, false);
                                132                 : 
  124 alvherre                  133 GNC        4306 :         perminfo = nsitem->p_perminfo;
                                134            4306 :         perminfo->requiredPerms = (is_from ? ACL_INSERT : ACL_SELECT);
 4435 itagaki.takahiro          135 ECB             : 
 1541 tomas.vondra              136 GIC        4306 :         if (stmt->whereClause)
 1541 tomas.vondra              137 ECB             :         {
                                138                 :             /* add nsitem to query namespace */
 1193 tgl                       139 GIC          24 :             addNSItemToQuery(pstate, nsitem, false, true, true);
 1541 tomas.vondra              140 ECB             : 
                                141                 :             /* Transform the raw expression tree */
 1541 tomas.vondra              142 GIC          24 :             whereClause = transformExpr(pstate, stmt->whereClause, EXPR_KIND_COPY_WHERE);
 1541 tomas.vondra              143 ECB             : 
                                144                 :             /* Make sure it yields a boolean result. */
 1541 tomas.vondra              145 GIC           9 :             whereClause = coerce_to_boolean(pstate, whereClause, "WHERE");
 1541 tomas.vondra              146 ECB             : 
                                147                 :             /* we have to fix its collations too */
 1541 tomas.vondra              148 GIC           9 :             assign_expr_collations(pstate, whereClause);
 1541 tomas.vondra              149 ECB             : 
 1541 tomas.vondra              150 GIC           9 :             whereClause = eval_const_expressions(NULL, whereClause);
                                151                 : 
 1541 tomas.vondra              152 CBC           9 :             whereClause = (Node *) canonicalize_qual((Expr *) whereClause, false);
 1541 tomas.vondra              153 GIC           9 :             whereClause = (Node *) make_ands_implicit((Expr *) whereClause);
                                154                 :         }
 1541 tomas.vondra              155 ECB             : 
 4435 itagaki.takahiro          156 GIC        4291 :         tupDesc = RelationGetDescr(rel);
 4435 itagaki.takahiro          157 CBC        4291 :         attnums = CopyGetAttnums(tupDesc, rel, stmt->attlist);
 4431 tgl                       158 GIC       20212 :         foreach(cur, attnums)
 4435 itagaki.takahiro          159 ECB             :         {
                                160                 :             int         attno;
                                161                 :             Bitmapset **bms;
                                162                 : 
  124 alvherre                  163 GNC       15951 :             attno = lfirst_int(cur) - FirstLowInvalidHeapAttributeNumber;
                                164           15951 :             bms = is_from ? &perminfo->insertedCols : &perminfo->selectedCols;
                                165                 : 
                                166           15951 :             *bms = bms_add_member(*bms, attno);
                                167                 :         }
                                168            4261 :         ExecCheckPermissions(pstate->p_rtable, list_make1(perminfo), true);
                                169                 : 
 3124 sfrost                    170 ECB             :         /*
 3055                           171                 :          * Permission check for row security policies.
                                172                 :          *
 3124                           173                 :          * check_enable_rls will ereport(ERROR) if the user has requested
                                174                 :          * something invalid and will otherwise indicate if we should enable
                                175                 :          * RLS (returns RLS_ENABLED) or not for this COPY statement.
                                176                 :          *
                                177                 :          * If the relation has a row security policy and we are to apply it
                                178                 :          * then perform a "query" copy and allow the normal query processing
                                179                 :          * to handle the policies.
                                180                 :          *
                                181                 :          * If RLS is not enabled for this, then just fall through to the
                                182                 :          * normal non-filtering relation handling.
                                183                 :          */
  124 alvherre                  184 GNC        4219 :         if (check_enable_rls(relid, InvalidOid, false) == RLS_ENABLED)
                                185                 :         {
                                186                 :             SelectStmt *select;
                                187                 :             ColumnRef  *cr;
                                188                 :             ResTarget  *target;
                                189                 :             RangeVar   *from;
 2379 sfrost                    190 GIC          30 :             List       *targetList = NIL;
 3124 sfrost                    191 ECB             : 
 3124 sfrost                    192 GIC          30 :             if (is_from)
                                193               3 :                 ereport(ERROR,
                                194                 :                         (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                                195                 :                          errmsg("COPY FROM not supported with row-level security"),
                                196                 :                          errhint("Use INSERT statements instead.")));
 3124 sfrost                    197 ECB             : 
                                198                 :             /*
 2379                           199                 :              * Build target list
                                200                 :              *
                                201                 :              * If no columns are specified in the attribute list of the COPY
                                202                 :              * command, then the target list is 'all' columns. Therefore, '*'
                                203                 :              * should be used as the target list for the resulting SELECT
                                204                 :              * statement.
                                205                 :              *
                                206                 :              * In the case that columns are specified in the attribute list,
                                207                 :              * create a ColumnRef and ResTarget for each column and add them
                                208                 :              * to the target list for the resulting SELECT statement.
                                209                 :              */
 3124 sfrost                    210 GIC          27 :             if (!stmt->attlist)
                                211                 :             {
 2379                           212               9 :                 cr = makeNode(ColumnRef);
 3124                           213               9 :                 cr->fields = list_make1(makeNode(A_Star));
 2379                           214               9 :                 cr->location = -1;
                                215                 : 
                                216               9 :                 target = makeNode(ResTarget);
 2379 sfrost                    217 CBC           9 :                 target->name = NULL;
 2379 sfrost                    218 GIC           9 :                 target->indirection = NIL;
 2379 sfrost                    219 CBC           9 :                 target->val = (Node *) cr;
                                220               9 :                 target->location = -1;
 3124 sfrost                    221 ECB             : 
 2379 sfrost                    222 GIC           9 :                 targetList = list_make1(target);
 2379 sfrost                    223 ECB             :             }
                                224                 :             else
                                225                 :             {
                                226                 :                 ListCell   *lc;
 3124                           227                 : 
 2379 sfrost                    228 GIC          51 :                 foreach(lc, stmt->attlist)
 2379 sfrost                    229 ECB             :                 {
                                230                 :                     /*
                                231                 :                      * Build the ColumnRef for each column.  The ColumnRef
                                232                 :                      * 'fields' property is a String node that corresponds to
                                233                 :                      * the column name respectively.
                                234                 :                      */
 2379 sfrost                    235 CBC          33 :                     cr = makeNode(ColumnRef);
 2379 sfrost                    236 GIC          33 :                     cr->fields = list_make1(lfirst(lc));
                                237              33 :                     cr->location = -1;
                                238                 : 
                                239                 :                     /* Build the ResTarget and add the ColumnRef to it. */
                                240              33 :                     target = makeNode(ResTarget);
                                241              33 :                     target->name = NULL;
 2379 sfrost                    242 CBC          33 :                     target->indirection = NIL;
                                243              33 :                     target->val = (Node *) cr;
                                244              33 :                     target->location = -1;
                                245                 : 
                                246                 :                     /* Add each column to the SELECT statement's target list */
                                247              33 :                     targetList = lappend(targetList, target);
 2379 sfrost                    248 ECB             :                 }
                                249                 :             }
 3124                           250                 : 
 2813                           251                 :             /*
                                252                 :              * Build RangeVar for from clause, fully qualified based on the
                                253                 :              * relation which we have opened and locked.  Use "ONLY" so that
   30 tgl                       254                 :              * COPY retrieves rows from only the target table not any
                                255                 :              * inheritance children, the same as when RLS doesn't apply.
                                256                 :              */
 2813 sfrost                    257 GIC          27 :             from = makeRangeVar(get_namespace_name(RelationGetNamespace(rel)),
 2225 tgl                       258              27 :                                 pstrdup(RelationGetRelationName(rel)),
                                259                 :                                 -1);
   30                           260              27 :             from->inh = false;   /* apply ONLY */
                                261                 : 
                                262                 :             /* Build query */
 3124 sfrost                    263              27 :             select = makeNode(SelectStmt);
 2379 sfrost                    264 CBC          27 :             select->targetList = targetList;
 3124                           265              27 :             select->fromClause = list_make1(from);
                                266                 : 
 2276 tgl                       267              27 :             query = makeNode(RawStmt);
 2276 tgl                       268 GIC          27 :             query->stmt = (Node *) select;
                                269              27 :             query->stmt_location = stmt_location;
 2276 tgl                       270 CBC          27 :             query->stmt_len = stmt_len;
 3124 sfrost                    271 ECB             : 
 2813                           272                 :             /*
                                273                 :              * Close the relation for now, but keep the lock on it to prevent
                                274                 :              * changes between now and when we start the query-based COPY.
                                275                 :              *
                                276                 :              * We'll reopen it later as part of the query-based COPY.
                                277                 :              */
 1539 andres                    278 GIC          27 :             table_close(rel, NoLock);
 3124 sfrost                    279              27 :             rel = NULL;
                                280                 :         }
                                281                 :     }
                                282                 :     else
                                283                 :     {
 4435 itagaki.takahiro          284             193 :         Assert(stmt->query);
 4435 itagaki.takahiro          285 ECB             : 
  240 alvherre                  286                 :         /* MERGE is allowed by parser, but unimplemented. Reject for now */
  240 alvherre                  287 GIC         193 :         if (IsA(stmt->query, MergeStmt))
                                288               3 :             ereport(ERROR,
                                289                 :                     errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                                290                 :                     errmsg("MERGE not supported in COPY"));
  240 alvherre                  291 ECB             : 
 2276 tgl                       292 GIC         190 :         query = makeNode(RawStmt);
                                293             190 :         query->stmt = stmt->query;
 2276 tgl                       294 CBC         190 :         query->stmt_location = stmt_location;
                                295             190 :         query->stmt_len = stmt_len;
                                296                 : 
 3751 peter_e                   297 GIC         190 :         relid = InvalidOid;
 4435 itagaki.takahiro          298             190 :         rel = NULL;
 4435 itagaki.takahiro          299 ECB             :     }
                                300                 : 
 4435 itagaki.takahiro          301 CBC        4397 :     if (is_from)
 4435 itagaki.takahiro          302 ECB             :     {
                                303                 :         CopyFromState cstate;
  867 heikki.linnakangas        304                 : 
 4043 peter_e                   305 CBC         903 :         Assert(rel);
                                306                 : 
                                307                 :         /* check read-only transaction and parallel mode */
 3765 tgl                       308             903 :         if (XactReadOnly && !rel->rd_islocaltemp)
 4435 itagaki.takahiro          309 UIC           0 :             PreventCommandIfReadOnly("COPY FROM");
                                310                 : 
  867 heikki.linnakangas        311 GIC         903 :         cstate = BeginCopyFrom(pstate, rel, whereClause,
  867 heikki.linnakangas        312 CBC         903 :                                stmt->filename, stmt->is_program,
 2208 peter_e                   313 GIC         903 :                                NULL, stmt->attlist, stmt->options);
 3753 rhaas                     314             837 :         *processed = CopyFrom(cstate);  /* copy from file to database */
 4435 itagaki.takahiro          315 CBC         752 :         EndCopyFrom(cstate);
 4435 itagaki.takahiro          316 EUB             :     }
                                317                 :     else
 4435 itagaki.takahiro          318 ECB             :     {
  867 heikki.linnakangas        319                 :         CopyToState cstate;
                                320                 : 
 2406 peter_e                   321 CBC        3494 :         cstate = BeginCopyTo(pstate, rel, query, relid,
 3693 heikki.linnakangas        322            3494 :                              stmt->filename, stmt->is_program,
  180 michael                   323 GNC        3494 :                              NULL, stmt->attlist, stmt->options);
 3753 rhaas                     324 GIC        3400 :         *processed = DoCopyTo(cstate);  /* copy from database to file */
 4435 itagaki.takahiro          325            3399 :         EndCopyTo(cstate);
                                326                 :     }
                                327                 : 
 4435 itagaki.takahiro          328 CBC        4151 :     if (rel != NULL)
 1059 akapila                   329            3998 :         table_close(rel, NoLock);
 4435 itagaki.takahiro          330            4151 : }
 4435 itagaki.takahiro          331 ECB             : 
  375 peter                     332                 : /*
                                333                 :  * Extract a CopyHeaderChoice value from a DefElem.  This is like
                                334                 :  * defGetBoolean() but also accepts the special value "match".
                                335                 :  */
                                336                 : static CopyHeaderChoice
  290 michael                   337 CBC          78 : defGetCopyHeaderChoice(DefElem *def, bool is_from)
                                338                 : {
                                339                 :     /*
                                340                 :      * If no parameter value given, assume "true" is meant.
                                341                 :      */
  375 peter                     342 GIC          78 :     if (def->arg == NULL)
                                343               6 :         return COPY_HEADER_TRUE;
  375 peter                     344 ECB             : 
                                345                 :     /*
                                346                 :      * Allow 0, 1, "true", "false", "on", "off", or "match".
                                347                 :      */
  375 peter                     348 GIC          72 :     switch (nodeTag(def->arg))
  375 peter                     349 ECB             :     {
  375 peter                     350 LBC           0 :         case T_Integer:
  375 peter                     351 UIC           0 :             switch (intVal(def->arg))
                                352                 :             {
                                353               0 :                 case 0:
                                354               0 :                     return COPY_HEADER_FALSE;
  375 peter                     355 LBC           0 :                 case 1:
  375 peter                     356 UIC           0 :                     return COPY_HEADER_TRUE;
  375 peter                     357 UBC           0 :                 default:
  375 peter                     358 EUB             :                     /* otherwise, error out below */
  375 peter                     359 UIC           0 :                     break;
  375 peter                     360 EUB             :             }
  375 peter                     361 UBC           0 :             break;
  375 peter                     362 GBC          72 :         default:
  375 peter                     363 EUB             :             {
  332 tgl                       364 GBC          72 :                 char       *sval = defGetString(def);
                                365                 : 
  375 peter                     366 EUB             :                 /*
                                367                 :                  * The set of strings accepted here should match up with the
                                368                 :                  * grammar's opt_boolean_or_string production.
  375 peter                     369 ECB             :                  */
  375 peter                     370 GIC          72 :                 if (pg_strcasecmp(sval, "true") == 0)
  375 peter                     371 CBC          23 :                     return COPY_HEADER_TRUE;
  375 peter                     372 GIC          49 :                 if (pg_strcasecmp(sval, "false") == 0)
  375 peter                     373 UIC           0 :                     return COPY_HEADER_FALSE;
  375 peter                     374 GIC          49 :                 if (pg_strcasecmp(sval, "on") == 0)
  375 peter                     375 UIC           0 :                     return COPY_HEADER_TRUE;
  375 peter                     376 GIC          49 :                 if (pg_strcasecmp(sval, "off") == 0)
  375 peter                     377 CBC           3 :                     return COPY_HEADER_FALSE;
                                378              46 :                 if (pg_strcasecmp(sval, "match") == 0)
  290 michael                   379 ECB             :                 {
  290 michael                   380 GBC          43 :                     if (!is_from)
  290 michael                   381 CBC           3 :                         ereport(ERROR,
  290 michael                   382 EUB             :                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
  290 michael                   383 ECB             :                                  errmsg("cannot use \"%s\" with HEADER in COPY TO",
                                384                 :                                         sval)));
  375 peter                     385 CBC          40 :                     return COPY_HEADER_MATCH;
                                386                 :                 }
  375 peter                     387 ECB             :             }
  375 peter                     388 CBC           3 :             break;
                                389                 :     }
  375 peter                     390 GIC           3 :     ereport(ERROR,
                                391                 :             (errcode(ERRCODE_SYNTAX_ERROR),
  332 tgl                       392 ECB             :              errmsg("%s requires a Boolean value or \"match\"",
                                393                 :                     def->defname)));
                                394                 :     return COPY_HEADER_FALSE;   /* keep compiler quiet */
  375 peter                     395                 : }
                                396                 : 
 4435 itagaki.takahiro          397                 : /*
                                398                 :  * Process the statement option list for COPY.
                                399                 :  *
                                400                 :  * Scan the options list (a list of DefElem) and transpose the information
                                401                 :  * into *opts_out, applying appropriate error checking.
                                402                 :  *
                                403                 :  * If 'opts_out' is not NULL, it is assumed to be filled with zeroes initially.
                                404                 :  *
                                405                 :  * This is exported so that external users of the COPY API can sanity-check
                                406                 :  * a list of options.  In that usage, 'opts_out' can be passed as NULL and
                                407                 :  * the collected data is just leaked until CurrentMemoryContext is reset.
                                408                 :  *
                                409                 :  * Note that additional checking, such as whether column names listed in FORCE
                                410                 :  * QUOTE actually exist, has to be applied later.  This just checks for
                                411                 :  * self-consistency of the options list.
                                412                 :  */
                                413                 : void
 2406 peter_e                   414 GIC        4621 : ProcessCopyOptions(ParseState *pstate,
                                415                 :                    CopyFormatOptions *opts_out,
                                416                 :                    bool is_from,
                                417                 :                    List *options)
                                418                 : {
 4948 tgl                       419            4621 :     bool        format_specified = false;
  916 michael                   420            4621 :     bool        freeze_specified = false;
  916 michael                   421 CBC        4621 :     bool        header_specified = false;
                                422                 :     ListCell   *option;
                                423                 : 
                                424                 :     /* Support external use for option sanity checking */
  867 heikki.linnakangas        425 GIC        4621 :     if (opts_out == NULL)
  867 heikki.linnakangas        426 CBC          43 :         opts_out = (CopyFormatOptions *) palloc0(sizeof(CopyFormatOptions));
 1602 tgl                       427 ECB             : 
  867 heikki.linnakangas        428 CBC        4621 :     opts_out->file_encoding = -1;
                                429                 : 
                                430                 :     /* Extract options from the statement node tree */
 4435 itagaki.takahiro          431 GIC        5359 :     foreach(option, options)
 7598 bruce                     432 ECB             :     {
 2190 tgl                       433 CBC         781 :         DefElem    *defel = lfirst_node(DefElem, option);
                                434                 : 
 4948                           435             781 :         if (strcmp(defel->defname, "format") == 0)
                                436                 :         {
 4790 bruce                     437 GIC         243 :             char       *fmt = defGetString(defel);
 4948 tgl                       438 ECB             : 
 4948 tgl                       439 GIC         243 :             if (format_specified)
  633 dean.a.rasheed            440 CBC           3 :                 errorConflictingDefElem(defel, pstate);
 4948 tgl                       441 GIC         240 :             format_specified = true;
 4948 tgl                       442 CBC         240 :             if (strcmp(fmt, "text") == 0)
                                443                 :                  /* default format */ ;
                                444             211 :             else if (strcmp(fmt, "csv") == 0)
  867 heikki.linnakangas        445 GIC         182 :                 opts_out->csv_mode = true;
 4948 tgl                       446 CBC          29 :             else if (strcmp(fmt, "binary") == 0)
  867 heikki.linnakangas        447              28 :                 opts_out->binary = true;
 4948 tgl                       448 ECB             :             else
 4948 tgl                       449 CBC           1 :                 ereport(ERROR,
                                450                 :                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
 2406 peter_e                   451 ECB             :                          errmsg("COPY format \"%s\" not recognized", fmt),
                                452                 :                          parser_errposition(pstate, defel->location)));
 7598 bruce                     453                 :         }
 3781 simon                     454 CBC         538 :         else if (strcmp(defel->defname, "freeze") == 0)
                                455                 :         {
  916 michael                   456              35 :             if (freeze_specified)
  633 dean.a.rasheed            457 GIC           3 :                 errorConflictingDefElem(defel, pstate);
  916 michael                   458              32 :             freeze_specified = true;
  867 heikki.linnakangas        459              32 :             opts_out->freeze = defGetBoolean(defel);
                                460                 :         }
 7598 bruce                     461 CBC         503 :         else if (strcmp(defel->defname, "delimiter") == 0)
                                462                 :         {
  867 heikki.linnakangas        463             132 :             if (opts_out->delim)
  633 dean.a.rasheed            464               3 :                 errorConflictingDefElem(defel, pstate);
  867 heikki.linnakangas        465             129 :             opts_out->delim = defGetString(defel);
 7598 bruce                     466 ECB             :         }
 7598 bruce                     467 GIC         371 :         else if (strcmp(defel->defname, "null") == 0)
 7598 bruce                     468 ECB             :         {
  867 heikki.linnakangas        469 GIC          63 :             if (opts_out->null_print)
  633 dean.a.rasheed            470 CBC           3 :                 errorConflictingDefElem(defel, pstate);
  867 heikki.linnakangas        471              60 :             opts_out->null_print = defGetString(defel);
 6929 bruce                     472 ECB             :         }
   27 andrew                    473 GNC         308 :         else if (strcmp(defel->defname, "default") == 0)
                                474                 :         {
                                475              42 :             if (opts_out->default_print)
   27 andrew                    476 UNC           0 :                 errorConflictingDefElem(defel, pstate);
   27 andrew                    477 GNC          42 :             opts_out->default_print = defGetString(defel);
                                478                 :         }
 6546 bruce                     479 GIC         266 :         else if (strcmp(defel->defname, "header") == 0)
 6546 bruce                     480 ECB             :         {
  916 michael                   481 GIC          81 :             if (header_specified)
  633 dean.a.rasheed            482 CBC           3 :                 errorConflictingDefElem(defel, pstate);
  916 michael                   483              78 :             header_specified = true;
  290                           484              78 :             opts_out->header_line = defGetCopyHeaderChoice(defel, is_from);
                                485                 :         }
 6929 bruce                     486             185 :         else if (strcmp(defel->defname, "quote") == 0)
                                487                 :         {
  867 heikki.linnakangas        488              42 :             if (opts_out->quote)
  633 dean.a.rasheed            489 GBC           3 :                 errorConflictingDefElem(defel, pstate);
  867 heikki.linnakangas        490 CBC          39 :             opts_out->quote = defGetString(defel);
                                491                 :         }
 6929 bruce                     492             143 :         else if (strcmp(defel->defname, "escape") == 0)
                                493                 :         {
  867 heikki.linnakangas        494              38 :             if (opts_out->escape)
  633 dean.a.rasheed            495               3 :                 errorConflictingDefElem(defel, pstate);
  867 heikki.linnakangas        496              35 :             opts_out->escape = defGetString(defel);
 6929 bruce                     497 ECB             :         }
 6927 bruce                     498 GIC         105 :         else if (strcmp(defel->defname, "force_quote") == 0)
 6929 bruce                     499 ECB             :         {
  867 heikki.linnakangas        500 GIC          33 :             if (opts_out->force_quote || opts_out->force_quote_all)
  633 dean.a.rasheed            501 CBC           3 :                 errorConflictingDefElem(defel, pstate);
 5006 tgl                       502              30 :             if (defel->arg && IsA(defel->arg, A_Star))
  867 heikki.linnakangas        503               9 :                 opts_out->force_quote_all = true;
 4948 tgl                       504 GIC          21 :             else if (defel->arg && IsA(defel->arg, List))
  867 heikki.linnakangas        505 CBC          21 :                 opts_out->force_quote = castNode(List, defel->arg);
                                506                 :             else
 4948 tgl                       507 LBC           0 :                 ereport(ERROR,
 4790 bruce                     508 ECB             :                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                                509                 :                          errmsg("argument to option \"%s\" must be a list of column names",
                                510                 :                                 defel->defname),
 2406 peter_e                   511                 :                          parser_errposition(pstate, defel->location)));
                                512                 :         }
 4948 tgl                       513 CBC          72 :         else if (strcmp(defel->defname, "force_not_null") == 0)
 6929 bruce                     514 ECB             :         {
  867 heikki.linnakangas        515 CBC          26 :             if (opts_out->force_notnull)
  633 dean.a.rasheed            516               3 :                 errorConflictingDefElem(defel, pstate);
 4948 tgl                       517              23 :             if (defel->arg && IsA(defel->arg, List))
  867 heikki.linnakangas        518              23 :                 opts_out->force_notnull = castNode(List, defel->arg);
                                519                 :             else
 4948 tgl                       520 UBC           0 :                 ereport(ERROR,
                                521                 :                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                                522                 :                          errmsg("argument to option \"%s\" must be a list of column names",
                                523                 :                                 defel->defname),
                                524                 :                          parser_errposition(pstate, defel->location)));
                                525                 :         }
 3323 andrew                    526 CBC          46 :         else if (strcmp(defel->defname, "force_null") == 0)
                                527                 :         {
  867 heikki.linnakangas        528              26 :             if (opts_out->force_null)
  633 dean.a.rasheed            529               3 :                 errorConflictingDefElem(defel, pstate);
 3323 andrew                    530              23 :             if (defel->arg && IsA(defel->arg, List))
  867 heikki.linnakangas        531              23 :                 opts_out->force_null = castNode(List, defel->arg);
                                532                 :             else
 3323 andrew                    533 UBC           0 :                 ereport(ERROR,
                                534                 :                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                                535                 :                          errmsg("argument to option \"%s\" must be a list of column names",
                                536                 :                                 defel->defname),
                                537                 :                          parser_errposition(pstate, defel->location)));
                                538                 :         }
 3923 tgl                       539 CBC          20 :         else if (strcmp(defel->defname, "convert_selectively") == 0)
                                540                 :         {
 3923 tgl                       541 ECB             :             /*
 3602 bruce                     542                 :              * Undocumented, not-accessible-from-SQL option: convert only the
                                543                 :              * named columns to binary form, storing the rest as NULLs. It's
                                544                 :              * allowed for the column list to be NIL.
                                545                 :              */
  867 heikki.linnakangas        546 GBC           8 :             if (opts_out->convert_selectively)
  633 dean.a.rasheed            547 GIC           3 :                 errorConflictingDefElem(defel, pstate);
  867 heikki.linnakangas        548               5 :             opts_out->convert_selectively = true;
 3923 tgl                       549               5 :             if (defel->arg == NULL || IsA(defel->arg, List))
  867 heikki.linnakangas        550               5 :                 opts_out->convert_select = castNode(List, defel->arg);
                                551                 :             else
 3923 tgl                       552 LBC           0 :                 ereport(ERROR,
                                553                 :                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                                554                 :                          errmsg("argument to option \"%s\" must be a list of column names",
                                555                 :                                 defel->defname),
                                556                 :                          parser_errposition(pstate, defel->location)));
                                557                 :         }
 4430 itagaki.takahiro          558 GIC          12 :         else if (strcmp(defel->defname, "encoding") == 0)
 4430 itagaki.takahiro          559 ECB             :         {
  867 heikki.linnakangas        560 CBC          12 :             if (opts_out->file_encoding >= 0)
  633 dean.a.rasheed            561               3 :                 errorConflictingDefElem(defel, pstate);
  867 heikki.linnakangas        562               9 :             opts_out->file_encoding = pg_char_to_encoding(defGetString(defel));
                                563               9 :             if (opts_out->file_encoding < 0)
 4430 itagaki.takahiro          564 UIC           0 :                 ereport(ERROR,
 4430 itagaki.takahiro          565 EUB             :                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                                566                 :                          errmsg("argument to option \"%s\" must be a valid encoding name",
                                567                 :                                 defel->defname),
                                568                 :                          parser_errposition(pstate, defel->location)));
                                569                 :         }
                                570                 :         else
 4948 tgl                       571 LBC           0 :             ereport(ERROR,
                                572                 :                     (errcode(ERRCODE_SYNTAX_ERROR),
 4948 tgl                       573 ECB             :                      errmsg("option \"%s\" not recognized",
 2406 peter_e                   574                 :                             defel->defname),
      tgl                       575                 :                      parser_errposition(pstate, defel->location)));
 7598 bruce                     576                 :     }
 7598 bruce                     577 EUB             : 
                                578                 :     /*
                                579                 :      * Check for incompatible options (must do these two before inserting
                                580                 :      * defaults)
                                581                 :      */
  867 heikki.linnakangas        582 GIC        4578 :     if (opts_out->binary && opts_out->delim)
 7203 tgl                       583               3 :         ereport(ERROR,
 7203 tgl                       584 EUB             :                 (errcode(ERRCODE_SYNTAX_ERROR),
                                585                 :                  errmsg("cannot specify DELIMITER in BINARY mode")));
                                586                 : 
  867 heikki.linnakangas        587 GIC        4575 :     if (opts_out->binary && opts_out->null_print)
 7203 tgl                       588               3 :         ereport(ERROR,
                                589                 :                 (errcode(ERRCODE_SYNTAX_ERROR),
                                590                 :                  errmsg("cannot specify NULL in BINARY mode")));
                                591                 : 
   27 andrew                    592 GNC        4572 :     if (opts_out->binary && opts_out->default_print)
                                593               3 :         ereport(ERROR,
                                594                 :                 (errcode(ERRCODE_SYNTAX_ERROR),
                                595                 :                  errmsg("cannot specify DEFAULT in BINARY mode")));
                                596                 : 
                                597                 :     /* Set defaults for omitted options */
  867 heikki.linnakangas        598 GIC        4569 :     if (!opts_out->delim)
                                599            4446 :         opts_out->delim = opts_out->csv_mode ? "," : "\t";
 6797 bruce                     600 ECB             : 
  867 heikki.linnakangas        601 CBC        4569 :     if (!opts_out->null_print)
  867 heikki.linnakangas        602 GIC        4515 :         opts_out->null_print = opts_out->csv_mode ? "" : "\\N";
                                603            4569 :     opts_out->null_print_len = strlen(opts_out->null_print);
                                604                 : 
  867 heikki.linnakangas        605 CBC        4569 :     if (opts_out->csv_mode)
 6929 bruce                     606 ECB             :     {
  867 heikki.linnakangas        607 GIC         179 :         if (!opts_out->quote)
                                608             145 :             opts_out->quote = "\"";
                                609             179 :         if (!opts_out->escape)
  867 heikki.linnakangas        610 CBC         150 :             opts_out->escape = opts_out->quote;
 6929 bruce                     611 ECB             :     }
                                612                 : 
                                613                 :     /* Only single-byte delimiter strings are supported. */
  867 heikki.linnakangas        614 GIC        4569 :     if (strlen(opts_out->delim) != 1)
 6929 bruce                     615               1 :         ereport(ERROR,
 6929 bruce                     616 ECB             :                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 2118 tgl                       617                 :                  errmsg("COPY delimiter must be a single one-byte character")));
                                618                 : 
 6274 bruce                     619                 :     /* Disallow end-of-line characters */
  867 heikki.linnakangas        620 CBC        4568 :     if (strchr(opts_out->delim, '\r') != NULL ||
                                621            4568 :         strchr(opts_out->delim, '\n') != NULL)
 6274 bruce                     622 GIC           1 :         ereport(ERROR,
 6274 bruce                     623 ECB             :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                                624                 :                  errmsg("COPY delimiter cannot be newline or carriage return")));
                                625                 : 
  867 heikki.linnakangas        626 CBC        4567 :     if (strchr(opts_out->null_print, '\r') != NULL ||
                                627            4567 :         strchr(opts_out->null_print, '\n') != NULL)
 6274 bruce                     628               1 :         ereport(ERROR,
                                629                 :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                                630                 :                  errmsg("COPY null representation cannot use newline or carriage return")));
                                631                 : 
   27 andrew                    632 GNC        4566 :     if (opts_out->default_print)
                                633                 :     {
                                634              39 :         opts_out->default_print_len = strlen(opts_out->default_print);
                                635                 : 
                                636              39 :         if (strchr(opts_out->default_print, '\r') != NULL ||
                                637              36 :             strchr(opts_out->default_print, '\n') != NULL)
                                638               6 :             ereport(ERROR,
                                639                 :                     (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                                640                 :                      errmsg("COPY default representation cannot use newline or carriage return")));
                                641                 :     }
                                642                 : 
 5582 tgl                       643 ECB             :     /*
                                644                 :      * Disallow unsafe delimiter characters in non-CSV mode.  We can't allow
                                645                 :      * backslash because it would be ambiguous.  We can't allow the other
                                646                 :      * cases because data characters matching the delimiter must be
                                647                 :      * backslashed, and certain backslash combinations are interpreted
                                648                 :      * non-literally by COPY IN.  Disallowing all lower case ASCII letters is
 5050 bruce                     649                 :      * more than strictly necessary, but seems best for consistency and
 5582 tgl                       650                 :      * future-proofing.  Likewise we disallow all digits though only octal
                                651                 :      * digits are actually dangerous.
                                652                 :      */
  867 heikki.linnakangas        653 GIC        4560 :     if (!opts_out->csv_mode &&
 5582 tgl                       654            4384 :         strchr("\\.abcdefghijklmnopqrstuvwxyz0123456789",
  867 heikki.linnakangas        655 CBC        4384 :                opts_out->delim[0]) != NULL)
 6274 bruce                     656               5 :         ereport(ERROR,
 6274 bruce                     657 ECB             :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                                658                 :                  errmsg("COPY delimiter cannot be \"%s\"", opts_out->delim)));
                                659                 : 
                                660                 :     /* Check header */
  436 peter                     661 CBC        4555 :     if (opts_out->binary && opts_out->header_line)
 6546 bruce                     662 GIC           1 :         ereport(ERROR,
 6546 bruce                     663 ECB             :                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                                664                 :                  errmsg("cannot specify HEADER in BINARY mode")));
                                665                 : 
 6547                           666                 :     /* Check quote */
  867 heikki.linnakangas        667 CBC        4554 :     if (!opts_out->csv_mode && opts_out->quote != NULL)
 6929 bruce                     668 GIC           2 :         ereport(ERROR,
                                669                 :                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                                670                 :                  errmsg("COPY quote available only in CSV mode")));
                                671                 : 
  867 heikki.linnakangas        672            4552 :     if (opts_out->csv_mode && strlen(opts_out->quote) != 1)
 6929 bruce                     673               1 :         ereport(ERROR,
                                674                 :                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                                675                 :                  errmsg("COPY quote must be a single one-byte character")));
                                676                 : 
  867 heikki.linnakangas        677            4551 :     if (opts_out->csv_mode && opts_out->delim[0] == opts_out->quote[0])
 5579 andrew                    678               1 :         ereport(ERROR,
                                679                 :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                                680                 :                  errmsg("COPY delimiter and quote must be different")));
                                681                 : 
 6547 bruce                     682 ECB             :     /* Check escape */
  867 heikki.linnakangas        683 CBC        4550 :     if (!opts_out->csv_mode && opts_out->escape != NULL)
 6929 bruce                     684               3 :         ereport(ERROR,
 6929 bruce                     685 ECB             :                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                                686                 :                  errmsg("COPY escape available only in CSV mode")));
                                687                 : 
  867 heikki.linnakangas        688 GIC        4547 :     if (opts_out->csv_mode && strlen(opts_out->escape) != 1)
 6929 bruce                     689               1 :         ereport(ERROR,
 6929 bruce                     690 ECB             :                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 5127 tgl                       691                 :                  errmsg("COPY escape must be a single one-byte character")));
                                692                 : 
                                693                 :     /* Check force_quote */
  867 heikki.linnakangas        694 GIC        4546 :     if (!opts_out->csv_mode && (opts_out->force_quote || opts_out->force_quote_all))
 6929 bruce                     695               3 :         ereport(ERROR,
 6929 bruce                     696 ECB             :                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 6927                           697                 :                  errmsg("COPY force quote available only in CSV mode")));
  867 heikki.linnakangas        698 GIC        4543 :     if ((opts_out->force_quote || opts_out->force_quote_all) && is_from)
 6929 bruce                     699               3 :         ereport(ERROR,
                                700                 :                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 6385 bruce                     701 ECB             :                  errmsg("COPY force quote only available using COPY TO")));
 6929                           702                 : 
                                703                 :     /* Check force_notnull */
  867 heikki.linnakangas        704 GIC        4540 :     if (!opts_out->csv_mode && opts_out->force_notnull != NIL)
 6929 bruce                     705               4 :         ereport(ERROR,
 6929 bruce                     706 ECB             :                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 6385                           707                 :                  errmsg("COPY force not null available only in CSV mode")));
  867 heikki.linnakangas        708 GIC        4536 :     if (opts_out->force_notnull != NIL && !is_from)
 6929 bruce                     709               3 :         ereport(ERROR,
                                710                 :                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                                711                 :                  errmsg("COPY force not null only available using COPY FROM")));
 6929 bruce                     712 ECB             : 
 3323 andrew                    713                 :     /* Check force_null */
  867 heikki.linnakangas        714 GIC        4533 :     if (!opts_out->csv_mode && opts_out->force_null != NIL)
 3323 andrew                    715               3 :         ereport(ERROR,
                                716                 :                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 3323 andrew                    717 ECB             :                  errmsg("COPY force null available only in CSV mode")));
                                718                 : 
  867 heikki.linnakangas        719 GIC        4530 :     if (opts_out->force_null != NIL && !is_from)
 3323 andrew                    720               3 :         ereport(ERROR,
                                721                 :                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                                722                 :                  errmsg("COPY force null only available using COPY FROM")));
 3323 andrew                    723 ECB             : 
 6547 bruce                     724                 :     /* Don't allow the delimiter to appear in the null string. */
  867 heikki.linnakangas        725 GIC        4527 :     if (strchr(opts_out->null_print, opts_out->delim[0]) != NULL)
 6929 bruce                     726               1 :         ereport(ERROR,
 6929 bruce                     727 ECB             :                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 2118 tgl                       728                 :                  errmsg("COPY delimiter must not appear in the NULL specification")));
                                729                 : 
                                730                 :     /* Don't allow the CSV quote char to appear in the null string. */
  867 heikki.linnakangas        731 GIC        4526 :     if (opts_out->csv_mode &&
                                732             163 :         strchr(opts_out->null_print, opts_out->quote[0]) != NULL)
 6929 bruce                     733 CBC           1 :         ereport(ERROR,
 6929 bruce                     734 ECB             :                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                                735                 :                  errmsg("CSV quote character must not appear in the NULL specification")));
                                736                 : 
   27 andrew                    737 GNC        4525 :     if (opts_out->default_print)
                                738                 :     {
                                739              33 :         if (!is_from)
                                740               3 :             ereport(ERROR,
                                741                 :                     (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                                742                 :                      errmsg("COPY DEFAULT only available using COPY FROM")));
                                743                 : 
                                744                 :         /* Don't allow the delimiter to appear in the default string. */
                                745              30 :         if (strchr(opts_out->default_print, opts_out->delim[0]) != NULL)
                                746               3 :             ereport(ERROR,
                                747                 :                     (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                                748                 :                      errmsg("COPY delimiter must not appear in the DEFAULT specification")));
                                749                 : 
                                750                 :         /* Don't allow the CSV quote char to appear in the default string. */
                                751              27 :         if (opts_out->csv_mode &&
                                752              15 :             strchr(opts_out->default_print, opts_out->quote[0]) != NULL)
                                753               3 :             ereport(ERROR,
                                754                 :                     (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                                755                 :                      errmsg("CSV quote character must not appear in the DEFAULT specification")));
                                756                 : 
                                757                 :         /* Don't allow the NULL and DEFAULT string to be the same */
                                758              24 :         if (opts_out->null_print_len == opts_out->default_print_len &&
                                759              12 :             strncmp(opts_out->null_print, opts_out->default_print,
                                760              12 :                     opts_out->null_print_len) == 0)
                                761               3 :             ereport(ERROR,
                                762                 :                     (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                                763                 :                      errmsg("NULL specification and DEFAULT specification cannot be the same")));
                                764                 :     }
 4431 tgl                       765 GIC        4513 : }
 4431 tgl                       766 ECB             : 
                                767                 : /*
                                768                 :  * CopyGetAttnums - build an integer list of attnums to be copied
                                769                 :  *
                                770                 :  * The input attnamelist is either the user-specified column list,
                                771                 :  * or NIL if there was none (in which case we want all the non-dropped
  867 heikki.linnakangas        772                 :  * columns).
 4431 tgl                       773                 :  *
                                774                 :  * We don't include generated columns in the generated full list and we don't
                                775                 :  * allow them to be specified explicitly.  They don't make sense for COPY
                                776                 :  * FROM, but we could possibly allow them for COPY TO.  But this way it's at
  867 heikki.linnakangas        777                 :  * least ensured that whatever we copy out can be copied back in.
 4431 tgl                       778                 :  *
                                779                 :  * rel can be NULL ... it's only used for error reports.
                                780                 :  */
                                781                 : List *
  867 heikki.linnakangas        782 GIC        8760 : CopyGetAttnums(TupleDesc tupDesc, Relation rel, List *attnamelist)
 4431 tgl                       783 ECB             : {
  867 heikki.linnakangas        784 CBC        8760 :     List       *attnums = NIL;
                                785                 : 
  867 heikki.linnakangas        786 GIC        8760 :     if (attnamelist == NIL)
                                787                 :     {
                                788                 :         /* Generate default column list */
 7522 bruce                     789 CBC        1585 :         int         attr_count = tupDesc->natts;
 7555 tgl                       790 ECB             :         int         i;
 7558 bruce                     791                 : 
 7558 bruce                     792 GIC        5336 :         for (i = 0; i < attr_count; i++)
                                793                 :         {
 2058 andres                    794            3751 :             if (TupleDescAttr(tupDesc, i)->attisdropped)
 7555 tgl                       795 CBC          98 :                 continue;
 1471 peter                     796 GIC        3653 :             if (TupleDescAttr(tupDesc, i)->attgenerated)
 1471 peter                     797 CBC          27 :                 continue;
 6892 neilc                     798            3626 :             attnums = lappend_int(attnums, i + 1);
                                799                 :         }
                                800                 :     }
                                801                 :     else
                                802                 :     {
 7555 tgl                       803 ECB             :         /* Validate the user-supplied list and extract attnums */
 6892 neilc                     804                 :         ListCell   *l;
                                805                 : 
 7555 tgl                       806 GIC       35538 :         foreach(l, attnamelist)
                                807                 :         {
 7538                           808           28393 :             char       *name = strVal(lfirst(l));
 7555 tgl                       809 ECB             :             int         attnum;
 6066                           810                 :             int         i;
 7555                           811                 : 
                                812                 :             /* Lookup column name */
 6066 tgl                       813 GIC       28393 :             attnum = InvalidAttrNumber;
                                814         4936742 :             for (i = 0; i < tupDesc->natts; i++)
                                815                 :             {
 2058 andres                    816 CBC     4936727 :                 Form_pg_attribute att = TupleDescAttr(tupDesc, i);
 2058 andres                    817 ECB             : 
 2058 andres                    818 CBC     4936727 :                 if (att->attisdropped)
 6066 tgl                       819             386 :                     continue;
 2058 andres                    820 GIC     4936341 :                 if (namestrcmp(&(att->attname), name) == 0)
                                821                 :                 {
 1471 peter                     822           28378 :                     if (att->attgenerated)
 1471 peter                     823 CBC          12 :                         ereport(ERROR,
                                824                 :                                 (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
                                825                 :                                  errmsg("column \"%s\" is a generated column",
                                826                 :                                         name),
                                827                 :                                  errdetail("Generated columns cannot be used in COPY.")));
 2058 andres                    828 GIC       28366 :                     attnum = att->attnum;
 6066 tgl                       829           28366 :                     break;
                                830                 :                 }
                                831                 :             }
 6226                           832           28381 :             if (attnum == InvalidAttrNumber)
                                833                 :             {
 6066                           834              15 :                 if (rel != NULL)
                                835              15 :                     ereport(ERROR,
                                836                 :                             (errcode(ERRCODE_UNDEFINED_COLUMN),
                                837                 :                              errmsg("column \"%s\" of relation \"%s\" does not exist",
                                838                 :                                     name, RelationGetRelationName(rel))));
                                839                 :                 else
 6066 tgl                       840 LBC           0 :                     ereport(ERROR,
                                841                 :                             (errcode(ERRCODE_UNDEFINED_COLUMN),
 6031 bruce                     842 ECB             :                              errmsg("column \"%s\" does not exist",
                                843                 :                                     name)));
 6066 tgl                       844                 :             }
                                845                 :             /* Check for duplicates */
 6892 neilc                     846 GIC       28366 :             if (list_member_int(attnums, attnum))
 7203 tgl                       847 CBC           3 :                 ereport(ERROR,
                                848                 :                         (errcode(ERRCODE_DUPLICATE_COLUMN),
                                849                 :                          errmsg("column \"%s\" specified more than once",
 6797 bruce                     850 ECB             :                                 name)));
 6892 neilc                     851 GIC       28363 :             attnums = lappend_int(attnums, attnum);
 7558 bruce                     852 ECB             :         }
                                853                 :     }
 7570                           854                 : 
 7555 tgl                       855 CBC        8730 :     return attnums;
 7555 tgl                       856 ECB             : }
        

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