]> granicus.if.org Git - postgresql/commitdiff
Fixed this problem and added regression tests in domain.sql.
authorBruce Momjian <bruce@momjian.us>
Fri, 20 Sep 2002 03:52:50 +0000 (03:52 +0000)
committerBruce Momjian <bruce@momjian.us>
Fri, 20 Sep 2002 03:52:50 +0000 (03:52 +0000)
Also:
- Changed header file order (alphabetical)
- Changed to m = attnum - 1 in binary copy code for consistency

Rod Taylor

src/backend/commands/copy.c
src/test/regress/expected/domain.out
src/test/regress/sql/domain.sql

index d9da44c465732b3e60400e79e17f08073b8e2bb9..9ad7070f1e94f73bea1d1833e951caaa54f4f437 100644 (file)
@@ -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 $
  *
  *-------------------------------------------------------------------------
  */
 #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' : ' ';
                        }
                }
 
index 8bbed8c431ddf2e48aaf7fec82988f9004c09ce1..79953d472c53c9e5d773c242f010f21ef9116201 100644 (file)
@@ -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;
index a5690694cad3cb431e4f33642a2eaaa0778f3d16..98ed4248cc0b509a2d573345a631a3c6c712ead4 100644 (file)
@@ -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;