|
8 | 8 | * |
9 | 9 | * |
10 | 10 | * IDENTIFICATION |
11 | | - * $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.195 2003/04/22 00:08:06 tgl Exp $ |
| 11 | + * $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.196 2003/04/24 21:16:42 tgl Exp $ |
12 | 12 | * |
13 | 13 | *------------------------------------------------------------------------- |
14 | 14 | */ |
@@ -100,13 +100,13 @@ static const char BinarySignature[12] = "PGBCOPY\n\377\r\n\0"; |
100 | 100 | * Static communication variables ... pretty grotty, but COPY has |
101 | 101 | * never been reentrant... |
102 | 102 | */ |
103 | | -intcopy_lineno=0;/* exported for use by elog() -- dz */ |
104 | | - |
105 | 103 | staticCopyDestcopy_dest; |
106 | 104 | staticFILE*copy_file;/* if copy_dest == COPY_FILE */ |
107 | 105 | staticStringInfocopy_msgbuf;/* if copy_dest == COPY_NEW_FE */ |
108 | 106 | staticboolfe_eof;/* true if detected end of copy data */ |
109 | | -staticEolTypeeol_type; |
| 107 | +staticEolTypeeol_type;/* EOL type of input */ |
| 108 | +staticintcopy_lineno;/* line number for error messages */ |
| 109 | + |
110 | 110 |
|
111 | 111 | /* |
112 | 112 | * These static variables are used to avoid incurring overhead for each |
@@ -1000,6 +1000,16 @@ CopyTo(Relation rel, List *attnumlist, bool binary, bool oids, |
1000 | 1000 | } |
1001 | 1001 |
|
1002 | 1002 |
|
| 1003 | +/* |
| 1004 | + * error context callback for COPY FROM |
| 1005 | + */ |
| 1006 | +staticvoid |
| 1007 | +copy_in_error_callback(void*arg) |
| 1008 | +{ |
| 1009 | +errcontext("COPY FROM, line %d",copy_lineno); |
| 1010 | +} |
| 1011 | + |
| 1012 | + |
1003 | 1013 | /* |
1004 | 1014 | * Copy FROM file to relation. |
1005 | 1015 | */ |
@@ -1032,6 +1042,7 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids, |
1032 | 1042 | ExprState**defexprs;/* array of default att expressions */ |
1033 | 1043 | ExprContext*econtext;/* used for ExecEvalExpr for default atts */ |
1034 | 1044 | MemoryContextoldcontext=CurrentMemoryContext; |
| 1045 | +ErrorContextCallbackerrcontext; |
1035 | 1046 |
|
1036 | 1047 | tupDesc=RelationGetDescr(rel); |
1037 | 1048 | attr=tupDesc->attrs; |
@@ -1188,16 +1199,22 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids, |
1188 | 1199 | values= (Datum*)palloc(num_phys_attrs*sizeof(Datum)); |
1189 | 1200 | nulls= (char*)palloc(num_phys_attrs*sizeof(char)); |
1190 | 1201 |
|
1191 | | -/* Initialize static variables */ |
1192 | | -copy_lineno=0; |
1193 | | -eol_type=EOL_UNKNOWN; |
1194 | | -fe_eof= false; |
1195 | | - |
1196 | 1202 | /* Make room for a PARAM_EXEC value for domain constraint checks */ |
1197 | 1203 | if (hasConstraints) |
1198 | 1204 | econtext->ecxt_param_exec_vals= (ParamExecData*) |
1199 | 1205 | palloc0(sizeof(ParamExecData)); |
1200 | 1206 |
|
| 1207 | +/* Initialize static variables */ |
| 1208 | +fe_eof= false; |
| 1209 | +eol_type=EOL_UNKNOWN; |
| 1210 | +copy_lineno=0; |
| 1211 | + |
| 1212 | +/* Set up callback to identify error line number */ |
| 1213 | +errcontext.callback=copy_in_error_callback; |
| 1214 | +errcontext.arg=NULL; |
| 1215 | +errcontext.previous=error_context_stack; |
| 1216 | +error_context_stack=&errcontext; |
| 1217 | + |
1201 | 1218 | while (!done) |
1202 | 1219 | { |
1203 | 1220 | boolskip_tuple; |
@@ -1502,7 +1519,7 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids, |
1502 | 1519 | /* |
1503 | 1520 | * Done, clean up |
1504 | 1521 | */ |
1505 | | -copy_lineno=0; |
| 1522 | +error_context_stack=errcontext.previous; |
1506 | 1523 |
|
1507 | 1524 | MemoryContextSwitchTo(oldcontext); |
1508 | 1525 |
|
|