@ -842,9 +842,10 @@ NextCopyFromRawFields(CopyFromState cstate, char ***fields, int *nfields)
/*
* Read next tuple from file for COPY FROM . Return false if no more tuples .
*
* ' econtext ' is used to evaluate default expression for each column not
* read from the file . It can be NULL when no default values are used , i . e .
* when all columns are read from the file .
* ' econtext ' is used to evaluate default expression for each column that is
* either not read from the file or is using the DEFAULT option of COPY FROM .
* It can be NULL when no default values are used , i . e . when all columns are
* read from the file , and DEFAULT option is unset .
*
* ' values ' and ' nulls ' arrays must be the same length as columns of the
* relation passed to BeginCopyFrom . This function fills the arrays .
@ -870,6 +871,7 @@ NextCopyFrom(CopyFromState cstate, ExprContext *econtext,
/* Initialize all values for row to NULL */
MemSet ( values , 0 , num_phys_attrs * sizeof ( Datum ) ) ;
MemSet ( nulls , true , num_phys_attrs * sizeof ( bool ) ) ;
cstate - > defaults = ( bool * ) palloc0 ( num_phys_attrs * sizeof ( bool ) ) ;
if ( ! cstate - > opts . binary )
{
@ -938,12 +940,27 @@ NextCopyFrom(CopyFromState cstate, ExprContext *econtext,
cstate - > cur_attname = NameStr ( att - > attname ) ;
cstate - > cur_attval = string ;
if ( string ! = NULL )
nulls [ m ] = false ;
if ( cstate - > defaults [ m ] )
{
/*
* The caller must supply econtext and have switched into the
* per - tuple memory context in it .
*/
Assert ( econtext ! = NULL ) ;
Assert ( CurrentMemoryContext = = econtext - > ecxt_per_tuple_memory ) ;
values [ m ] = ExecEvalExpr ( defexprs [ m ] , econtext , & nulls [ m ] ) ;
}
else
values [ m ] = InputFunctionCall ( & in_functions [ m ] ,
string ,
typioparams [ m ] ,
att - > atttypmod ) ;
if ( string ! = NULL )
nulls [ m ] = false ;
cstate - > cur_attname = NULL ;
cstate - > cur_attval = NULL ;
}
@ -1019,10 +1036,12 @@ NextCopyFrom(CopyFromState cstate, ExprContext *econtext,
Assert ( econtext ! = NULL ) ;
Assert ( CurrentMemoryContext = = econtext - > ecxt_per_tuple_memory ) ;
values [ defmap [ i ] ] = ExecEvalExpr ( defexprs [ i ] , econtext ,
values [ defmap [ i ] ] = ExecEvalExpr ( defexprs [ defmap [ i ] ] , econtext ,
& nulls [ defmap [ i ] ] ) ;
}
pfree ( cstate - > defaults ) ;
return true ;
}
@ -1663,6 +1682,31 @@ CopyReadAttributesText(CopyFromState cstate)
if ( input_len = = cstate - > opts . null_print_len & &
strncmp ( start_ptr , cstate - > opts . null_print , input_len ) = = 0 )
cstate - > raw_fields [ fieldno ] = NULL ;
/* Check whether raw input matched default marker */
else if ( cstate - > opts . default_print & &
input_len = = cstate - > opts . default_print_len & &
strncmp ( start_ptr , cstate - > opts . default_print , input_len ) = = 0 )
{
/* fieldno is 0-indexed and attnum is 1-indexed */
int m = list_nth_int ( cstate - > attnumlist , fieldno ) - 1 ;
if ( cstate - > defexprs [ m ] ! = NULL )
{
/* defaults contain entries for all physical attributes */
cstate - > defaults [ m ] = true ;
}
else
{
TupleDesc tupDesc = RelationGetDescr ( cstate - > rel ) ;
Form_pg_attribute att = TupleDescAttr ( tupDesc , m ) ;
ereport ( ERROR ,
( errcode ( ERRCODE_BAD_COPY_FILE_FORMAT ) ,
errmsg ( " unexpected DEFAULT in COPY data " ) ,
errdetail ( " Column \" %s \" has no DEFAULT value. " ,
NameStr ( att - > attname ) ) ) ) ;
}
}
else
{
/*
@ -1852,6 +1896,31 @@ endfield:
if ( ! saw_quote & & input_len = = cstate - > opts . null_print_len & &
strncmp ( start_ptr , cstate - > opts . null_print , input_len ) = = 0 )
cstate - > raw_fields [ fieldno ] = NULL ;
/* Check whether raw input matched default marker */
else if ( cstate - > opts . default_print & &
input_len = = cstate - > opts . default_print_len & &
strncmp ( start_ptr , cstate - > opts . default_print , input_len ) = = 0 )
{
/* fieldno is 0-index and attnum is 1-index */
int m = list_nth_int ( cstate - > attnumlist , fieldno ) - 1 ;
if ( cstate - > defexprs [ m ] ! = NULL )
{
/* defaults contain entries for all physical attributes */
cstate - > defaults [ m ] = true ;
}
else
{
TupleDesc tupDesc = RelationGetDescr ( cstate - > rel ) ;
Form_pg_attribute att = TupleDescAttr ( tupDesc , m ) ;
ereport ( ERROR ,
( errcode ( ERRCODE_BAD_COPY_FILE_FORMAT ) ,
errmsg ( " unexpected DEFAULT in COPY data " ) ,
errdetail ( " Column \" %s \" has no DEFAULT value. " ,
NameStr ( att - > attname ) ) ) ) ;
}
}
fieldno + + ;
/* Done if we hit EOL instead of a delim */