From: Bruce Momjian Date: Fri, 20 Sep 2002 03:52:50 +0000 (+0000) Subject: Fixed this problem and added regression tests in domain.sql. X-Git-Tag: REL7_3~448 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=07a6fa9df1dbb7a1d6466fdc833983bcd0d616eb;p=postgresql Fixed this problem and added regression tests in domain.sql. Also: - Changed header file order (alphabetical) - Changed to m = attnum - 1 in binary copy code for consistency Rod Taylor --- diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c index d9da44c465..9ad7070f1e 100644 --- a/src/backend/commands/copy.c +++ b/src/backend/commands/copy.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.171 2002/09/04 20:31:14 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.172 2002/09/20 03:52:50 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -28,10 +28,13 @@ #include "commands/copy.h" #include "commands/trigger.h" #include "executor/executor.h" -#include "rewrite/rewriteHandler.h" #include "libpq/libpq.h" +#include "mb/pg_wchar.h" #include "miscadmin.h" +#include "nodes/makefuncs.h" +#include "parser/parse_coerce.h" #include "parser/parse_relation.h" +#include "rewrite/rewriteHandler.h" #include "tcop/pquery.h" #include "tcop/tcopprot.h" #include "utils/acl.h" @@ -39,7 +42,6 @@ #include "utils/relcache.h" #include "utils/lsyscache.h" #include "utils/syscache.h" -#include "mb/pg_wchar.h" #define ISOCTAL(c) (((c) >= '0') && ((c) <= '7')) #define OCTVALUE(c) ((c) - '0') @@ -744,6 +746,8 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids, num_defaults; FmgrInfo *in_functions; Oid *elements; + bool *isDomain; + bool hasDomain = false; int i; List *cur; Oid in_func_oid; @@ -796,6 +800,7 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids, defexprs = (Node **) palloc(sizeof(Node *) * num_phys_attrs); in_functions = (FmgrInfo *) palloc(num_phys_attrs * sizeof(FmgrInfo)); elements = (Oid *) palloc(num_phys_attrs * sizeof(Oid)); + isDomain = (bool *) palloc(num_phys_attrs * sizeof(bool)); for (i = 0; i < num_phys_attrs; i++) { @@ -803,6 +808,16 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids, if (attr[i]->attisdropped) continue; + /* Test for the base type */ + if (getBaseType(attr[i]->atttypid) != attr[i]->atttypid) + { + hasDomain = true; + isDomain[i] = true; + } + else + isDomain[i] = false; + + /* Fetch the input function */ in_func_oid = (Oid) GetInputFunction(attr[i]->atttypid); fmgr_info(in_func_oid, &in_functions[i]); elements[i] = GetTypeElement(attr[i]->atttypid); @@ -1011,6 +1026,7 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids, foreach(cur, attnumlist) { int attnum = lfirsti(cur); + int m = attnum - 1; i++; @@ -1019,9 +1035,9 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids, elog(ERROR, "COPY BINARY: unexpected EOF"); if (fld_size == 0) continue; /* it's NULL; nulls[attnum-1] already set */ - if (fld_size != attr[attnum - 1]->attlen) + if (fld_size != attr[m]->attlen) elog(ERROR, "COPY BINARY: sizeof(field %d) is %d, expected %d", - i, (int) fld_size, (int) attr[attnum - 1]->attlen); + i, (int) fld_size, (int) attr[m]->attlen); if (fld_size == -1) { /* varlena field */ @@ -1040,9 +1056,9 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids, fp); if (CopyGetEof(fp)) elog(ERROR, "COPY BINARY: unexpected EOF"); - values[attnum - 1] = PointerGetDatum(varlena_ptr); + values[m] = PointerGetDatum(varlena_ptr); } - else if (!attr[attnum - 1]->attbyval) + else if (!attr[m]->attbyval) { /* fixed-length pass-by-reference */ Pointer refval_ptr; @@ -1052,7 +1068,7 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids, CopyGetData(refval_ptr, fld_size, fp); if (CopyGetEof(fp)) elog(ERROR, "COPY BINARY: unexpected EOF"); - values[attnum - 1] = PointerGetDatum(refval_ptr); + values[m] = PointerGetDatum(refval_ptr); } else { @@ -1067,10 +1083,56 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids, CopyGetData(&datumBuf, fld_size, fp); if (CopyGetEof(fp)) elog(ERROR, "COPY BINARY: unexpected EOF"); - values[attnum - 1] = fetch_att(&datumBuf, true, fld_size); + values[m] = fetch_att(&datumBuf, true, fld_size); } - nulls[attnum - 1] = ' '; + nulls[m] = ' '; + } + } + + /* Deal with domains */ + if (hasDomain) + { + ParseState *pstate; + pstate = make_parsestate(NULL); + + foreach(cur, attnumlist) + { + int attnum = lfirsti(cur); + int m = attnum - 1; + + Const *con; + Node *node; + bool isNull = (nulls[m] == 'n'); + + /* This is not a domain, so lets skip it */ + if (!isDomain[m]) + continue; + + /* + * This is a domain. As such, we must process it's input + * function and coerce_type_constraints. The simplest way + * of doing that is to allow coerce_type to accomplish its + * job from an unknown constant + */ + + /* Create a constant */ + con = makeConst(attr[m]->atttypid, + attr[m]->attlen, + values[m], + isNull, + attr[m]->attbyval, + false, /* not a set */ + false); /* not coerced */ + + /* Process constraints */ + node = coerce_type_constraints(pstate, (Node *) con, + attr[m]->atttypid, true); + + values[m] = ExecEvalExpr(node, econtext, + &isNull, NULL); + + nulls[m] = isNull ? 'n' : ' '; } } diff --git a/src/test/regress/expected/domain.out b/src/test/regress/expected/domain.out index 8bbed8c431..79953d472c 100644 --- a/src/test/regress/expected/domain.out +++ b/src/test/regress/expected/domain.out @@ -37,12 +37,18 @@ INSERT INTO basictest values ('88', 'haha', 'short', '123.12'); -- Good INSERT INTO basictest values ('88', 'haha', 'short text', '123.12'); -- Bad varchar ERROR: value too long for type character varying(5) INSERT INTO basictest values ('88', 'haha', 'short', '123.1212'); -- Truncate numeric +-- Test copy +COPY basictest (testvarchar) FROM stdin; -- fail +ERROR: copy: line 1, value too long for type character varying(5) +lost synchronization with server, resetting connection +COPY basictest (testvarchar) FROM stdin; select * from basictest; testint4 | testtext | testvarchar | testnumeric ----------+----------+-------------+------------- 88 | haha | short | 123.12 88 | haha | short | 123.12 -(2 rows) + | | short | +(3 rows) -- check that domains inherit operations from base types select testtext || testvarchar as concat, testnumeric + 42 as sum @@ -51,7 +57,8 @@ from basictest; -----------+-------- hahashort | 165.12 hahashort | 165.12 -(2 rows) + | +(3 rows) drop table basictest; drop domain domainvarchar restrict; @@ -111,12 +118,18 @@ ERROR: Domain dnotnull does not allow NULL values INSERT INTO nulltest values ('a', 'b', NULL, 'd'); ERROR: ExecInsert: Fail to add null value in not null attribute col3 INSERT INTO nulltest values ('a', 'b', 'c', NULL); -- Good +-- Test copy +COPY nulltest FROM stdin; --fail +ERROR: copy: line 1, CopyFrom: Fail to add null value in not null attribute col3 +lost synchronization with server, resetting connection +COPY nulltest FROM stdin; select * from nulltest; col1 | col2 | col3 | col4 ------+------+------+------ a | b | c | d a | b | c | -(2 rows) + a | b | c | +(3 rows) -- Test out coerced (casted) constraints SELECT cast('1' as dnotnull); @@ -156,13 +169,16 @@ NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index 'defaulttest_pkey insert into defaulttest default values; insert into defaulttest default values; insert into defaulttest default values; +-- Test defaults with copy +COPY defaulttest(col5) FROM stdin; select * from defaulttest; col1 | col2 | col3 | col4 | col5 | col6 | col7 | col8 ------+------+------+------+------+------+------+------- 3 | 12 | 5 | 1 | 3 | 88 | 8000 | 12.12 3 | 12 | 5 | 2 | 3 | 88 | 8000 | 12.12 3 | 12 | 5 | 3 | 3 | 88 | 8000 | 12.12 -(3 rows) + 3 | 12 | 5 | 4 | 42 | 88 | 8000 | 12.12 +(4 rows) drop sequence ddef4_seq; drop table defaulttest; diff --git a/src/test/regress/sql/domain.sql b/src/test/regress/sql/domain.sql index a5690694ca..98ed4248cc 100644 --- a/src/test/regress/sql/domain.sql +++ b/src/test/regress/sql/domain.sql @@ -35,6 +35,16 @@ create table basictest INSERT INTO basictest values ('88', 'haha', 'short', '123.12'); -- Good INSERT INTO basictest values ('88', 'haha', 'short text', '123.12'); -- Bad varchar INSERT INTO basictest values ('88', 'haha', 'short', '123.1212'); -- Truncate numeric + +-- Test copy +COPY basictest (testvarchar) FROM stdin; -- fail +notsoshorttext +\. + +COPY basictest (testvarchar) FROM stdin; +short +\. + select * from basictest; -- check that domains inherit operations from base types @@ -84,6 +94,16 @@ INSERT INTO nulltest values (NULL, 'b', 'c', 'd'); INSERT INTO nulltest values ('a', NULL, 'c', 'd'); INSERT INTO nulltest values ('a', 'b', NULL, 'd'); INSERT INTO nulltest values ('a', 'b', 'c', NULL); -- Good + +-- Test copy +COPY nulltest FROM stdin; --fail +a b \N d +\. + +COPY nulltest FROM stdin; +a b c \N +\. + select * from nulltest; -- Test out coerced (casted) constraints @@ -119,6 +139,12 @@ create table defaulttest insert into defaulttest default values; insert into defaulttest default values; insert into defaulttest default values; + +-- Test defaults with copy +COPY defaulttest(col5) FROM stdin; +42 +\. + select * from defaulttest; drop sequence ddef4_seq;