@@ -842,9 +842,10 @@ NextCopyFromRawFields(CopyFromState cstate, char ***fields, int *nfields)
842842/*
843843 * Read next tuple from file for COPY FROM. Return false if no more tuples.
844844 *
845- * 'econtext' is used to evaluate default expression for each column not
846- * read from the file. It can be NULL when no default values are used, i.e.
847- * when all columns are read from the file.
845+ * 'econtext' is used to evaluate default expression for each column that is
846+ * either not read from the file or is using the DEFAULT option of COPY FROM.
847+ * It can be NULL when no default values are used, i.e. when all columns are
848+ * read from the file, and DEFAULT option is unset.
848849 *
849850 * 'values' and 'nulls' arrays must be the same length as columns of the
850851 * relation passed to BeginCopyFrom. This function fills the arrays.
@@ -870,6 +871,7 @@ NextCopyFrom(CopyFromState cstate, ExprContext *econtext,
870871/* Initialize all values for row to NULL */
871872MemSet (values ,0 ,num_phys_attrs * sizeof (Datum ));
872873MemSet (nulls , true,num_phys_attrs * sizeof (bool ));
874+ cstate -> defaults = (bool * )palloc0 (num_phys_attrs * sizeof (bool ));
873875
874876if (!cstate -> opts .binary )
875877{
@@ -938,12 +940,27 @@ NextCopyFrom(CopyFromState cstate, ExprContext *econtext,
938940
939941cstate -> cur_attname = NameStr (att -> attname );
940942cstate -> cur_attval = string ;
941- values [m ]= InputFunctionCall (& in_functions [m ],
942- string ,
943- typioparams [m ],
944- att -> atttypmod );
943+
945944if (string != NULL )
946945nulls [m ]= false;
946+
947+ if (cstate -> defaults [m ])
948+ {
949+ /*
950+ * The caller must supply econtext and have switched into the
951+ * per-tuple memory context in it.
952+ */
953+ Assert (econtext != NULL );
954+ Assert (CurrentMemoryContext == econtext -> ecxt_per_tuple_memory );
955+
956+ values [m ]= ExecEvalExpr (defexprs [m ],econtext ,& nulls [m ]);
957+ }
958+ else
959+ values [m ]= InputFunctionCall (& in_functions [m ],
960+ string ,
961+ typioparams [m ],
962+ att -> atttypmod );
963+
947964cstate -> cur_attname = NULL ;
948965cstate -> cur_attval = NULL ;
949966}
@@ -1019,10 +1036,12 @@ NextCopyFrom(CopyFromState cstate, ExprContext *econtext,
10191036Assert (econtext != NULL );
10201037Assert (CurrentMemoryContext == econtext -> ecxt_per_tuple_memory );
10211038
1022- values [defmap [i ]]= ExecEvalExpr (defexprs [i ],econtext ,
1039+ values [defmap [i ]]= ExecEvalExpr (defexprs [defmap [ i ] ],econtext ,
10231040& nulls [defmap [i ]]);
10241041}
10251042
1043+ pfree (cstate -> defaults );
1044+
10261045return true;
10271046}
10281047
@@ -1663,6 +1682,31 @@ CopyReadAttributesText(CopyFromState cstate)
16631682if (input_len == cstate -> opts .null_print_len &&
16641683strncmp (start_ptr ,cstate -> opts .null_print ,input_len )== 0 )
16651684cstate -> raw_fields [fieldno ]= NULL ;
1685+ /* Check whether raw input matched default marker */
1686+ else if (cstate -> opts .default_print &&
1687+ input_len == cstate -> opts .default_print_len &&
1688+ strncmp (start_ptr ,cstate -> opts .default_print ,input_len )== 0 )
1689+ {
1690+ /* fieldno is 0-indexed and attnum is 1-indexed */
1691+ int m = list_nth_int (cstate -> attnumlist ,fieldno )- 1 ;
1692+
1693+ if (cstate -> defexprs [m ]!= NULL )
1694+ {
1695+ /* defaults contain entries for all physical attributes */
1696+ cstate -> defaults [m ]= true;
1697+ }
1698+ else
1699+ {
1700+ TupleDesc tupDesc = RelationGetDescr (cstate -> rel );
1701+ Form_pg_attribute att = TupleDescAttr (tupDesc ,m );
1702+
1703+ ereport (ERROR ,
1704+ (errcode (ERRCODE_BAD_COPY_FILE_FORMAT ),
1705+ errmsg ("unexpected DEFAULT in COPY data" ),
1706+ errdetail ("Column \"%s\" has no DEFAULT value." ,
1707+ NameStr (att -> attname ))));
1708+ }
1709+ }
16661710else
16671711{
16681712/*
@@ -1852,6 +1896,31 @@ CopyReadAttributesCSV(CopyFromState cstate)
18521896if (!saw_quote && input_len == cstate -> opts .null_print_len &&
18531897strncmp (start_ptr ,cstate -> opts .null_print ,input_len )== 0 )
18541898cstate -> raw_fields [fieldno ]= NULL ;
1899+ /* Check whether raw input matched default marker */
1900+ else if (cstate -> opts .default_print &&
1901+ input_len == cstate -> opts .default_print_len &&
1902+ strncmp (start_ptr ,cstate -> opts .default_print ,input_len )== 0 )
1903+ {
1904+ /* fieldno is 0-index and attnum is 1-index */
1905+ int m = list_nth_int (cstate -> attnumlist ,fieldno )- 1 ;
1906+
1907+ if (cstate -> defexprs [m ]!= NULL )
1908+ {
1909+ /* defaults contain entries for all physical attributes */
1910+ cstate -> defaults [m ]= true;
1911+ }
1912+ else
1913+ {
1914+ TupleDesc tupDesc = RelationGetDescr (cstate -> rel );
1915+ Form_pg_attribute att = TupleDescAttr (tupDesc ,m );
1916+
1917+ ereport (ERROR ,
1918+ (errcode (ERRCODE_BAD_COPY_FILE_FORMAT ),
1919+ errmsg ("unexpected DEFAULT in COPY data" ),
1920+ errdetail ("Column \"%s\" has no DEFAULT value." ,
1921+ NameStr (att -> attname ))));
1922+ }
1923+ }
18551924
18561925fieldno ++ ;
18571926/* Done if we hit EOL instead of a delim */