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
This commit is contained in:
parent
24bebf0b72
commit
07a6fa9df1
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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/copy.h"
|
||||||
#include "commands/trigger.h"
|
#include "commands/trigger.h"
|
||||||
#include "executor/executor.h"
|
#include "executor/executor.h"
|
||||||
#include "rewrite/rewriteHandler.h"
|
|
||||||
#include "libpq/libpq.h"
|
#include "libpq/libpq.h"
|
||||||
|
#include "mb/pg_wchar.h"
|
||||||
#include "miscadmin.h"
|
#include "miscadmin.h"
|
||||||
|
#include "nodes/makefuncs.h"
|
||||||
|
#include "parser/parse_coerce.h"
|
||||||
#include "parser/parse_relation.h"
|
#include "parser/parse_relation.h"
|
||||||
|
#include "rewrite/rewriteHandler.h"
|
||||||
#include "tcop/pquery.h"
|
#include "tcop/pquery.h"
|
||||||
#include "tcop/tcopprot.h"
|
#include "tcop/tcopprot.h"
|
||||||
#include "utils/acl.h"
|
#include "utils/acl.h"
|
||||||
@ -39,7 +42,6 @@
|
|||||||
#include "utils/relcache.h"
|
#include "utils/relcache.h"
|
||||||
#include "utils/lsyscache.h"
|
#include "utils/lsyscache.h"
|
||||||
#include "utils/syscache.h"
|
#include "utils/syscache.h"
|
||||||
#include "mb/pg_wchar.h"
|
|
||||||
|
|
||||||
#define ISOCTAL(c) (((c) >= '0') && ((c) <= '7'))
|
#define ISOCTAL(c) (((c) >= '0') && ((c) <= '7'))
|
||||||
#define OCTVALUE(c) ((c) - '0')
|
#define OCTVALUE(c) ((c) - '0')
|
||||||
@ -744,6 +746,8 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
|
|||||||
num_defaults;
|
num_defaults;
|
||||||
FmgrInfo *in_functions;
|
FmgrInfo *in_functions;
|
||||||
Oid *elements;
|
Oid *elements;
|
||||||
|
bool *isDomain;
|
||||||
|
bool hasDomain = false;
|
||||||
int i;
|
int i;
|
||||||
List *cur;
|
List *cur;
|
||||||
Oid in_func_oid;
|
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);
|
defexprs = (Node **) palloc(sizeof(Node *) * num_phys_attrs);
|
||||||
in_functions = (FmgrInfo *) palloc(num_phys_attrs * sizeof(FmgrInfo));
|
in_functions = (FmgrInfo *) palloc(num_phys_attrs * sizeof(FmgrInfo));
|
||||||
elements = (Oid *) palloc(num_phys_attrs * sizeof(Oid));
|
elements = (Oid *) palloc(num_phys_attrs * sizeof(Oid));
|
||||||
|
isDomain = (bool *) palloc(num_phys_attrs * sizeof(bool));
|
||||||
|
|
||||||
for (i = 0; i < num_phys_attrs; i++)
|
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)
|
if (attr[i]->attisdropped)
|
||||||
continue;
|
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);
|
in_func_oid = (Oid) GetInputFunction(attr[i]->atttypid);
|
||||||
fmgr_info(in_func_oid, &in_functions[i]);
|
fmgr_info(in_func_oid, &in_functions[i]);
|
||||||
elements[i] = GetTypeElement(attr[i]->atttypid);
|
elements[i] = GetTypeElement(attr[i]->atttypid);
|
||||||
@ -1011,6 +1026,7 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
|
|||||||
foreach(cur, attnumlist)
|
foreach(cur, attnumlist)
|
||||||
{
|
{
|
||||||
int attnum = lfirsti(cur);
|
int attnum = lfirsti(cur);
|
||||||
|
int m = attnum - 1;
|
||||||
|
|
||||||
i++;
|
i++;
|
||||||
|
|
||||||
@ -1019,9 +1035,9 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
|
|||||||
elog(ERROR, "COPY BINARY: unexpected EOF");
|
elog(ERROR, "COPY BINARY: unexpected EOF");
|
||||||
if (fld_size == 0)
|
if (fld_size == 0)
|
||||||
continue; /* it's NULL; nulls[attnum-1] already set */
|
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",
|
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)
|
if (fld_size == -1)
|
||||||
{
|
{
|
||||||
/* varlena field */
|
/* varlena field */
|
||||||
@ -1040,9 +1056,9 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
|
|||||||
fp);
|
fp);
|
||||||
if (CopyGetEof(fp))
|
if (CopyGetEof(fp))
|
||||||
elog(ERROR, "COPY BINARY: unexpected EOF");
|
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 */
|
/* fixed-length pass-by-reference */
|
||||||
Pointer refval_ptr;
|
Pointer refval_ptr;
|
||||||
@ -1052,7 +1068,7 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
|
|||||||
CopyGetData(refval_ptr, fld_size, fp);
|
CopyGetData(refval_ptr, fld_size, fp);
|
||||||
if (CopyGetEof(fp))
|
if (CopyGetEof(fp))
|
||||||
elog(ERROR, "COPY BINARY: unexpected EOF");
|
elog(ERROR, "COPY BINARY: unexpected EOF");
|
||||||
values[attnum - 1] = PointerGetDatum(refval_ptr);
|
values[m] = PointerGetDatum(refval_ptr);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -1067,10 +1083,56 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
|
|||||||
CopyGetData(&datumBuf, fld_size, fp);
|
CopyGetData(&datumBuf, fld_size, fp);
|
||||||
if (CopyGetEof(fp))
|
if (CopyGetEof(fp))
|
||||||
elog(ERROR, "COPY BINARY: unexpected EOF");
|
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' : ' ';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
INSERT INTO basictest values ('88', 'haha', 'short text', '123.12'); -- Bad varchar
|
||||||
ERROR: value too long for type character varying(5)
|
ERROR: value too long for type character varying(5)
|
||||||
INSERT INTO basictest values ('88', 'haha', 'short', '123.1212'); -- Truncate numeric
|
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;
|
select * from basictest;
|
||||||
testint4 | testtext | testvarchar | testnumeric
|
testint4 | testtext | testvarchar | testnumeric
|
||||||
----------+----------+-------------+-------------
|
----------+----------+-------------+-------------
|
||||||
88 | haha | short | 123.12
|
88 | haha | short | 123.12
|
||||||
88 | haha | short | 123.12
|
88 | haha | short | 123.12
|
||||||
(2 rows)
|
| | short |
|
||||||
|
(3 rows)
|
||||||
|
|
||||||
-- check that domains inherit operations from base types
|
-- check that domains inherit operations from base types
|
||||||
select testtext || testvarchar as concat, testnumeric + 42 as sum
|
select testtext || testvarchar as concat, testnumeric + 42 as sum
|
||||||
@ -51,7 +57,8 @@ from basictest;
|
|||||||
-----------+--------
|
-----------+--------
|
||||||
hahashort | 165.12
|
hahashort | 165.12
|
||||||
hahashort | 165.12
|
hahashort | 165.12
|
||||||
(2 rows)
|
|
|
||||||
|
(3 rows)
|
||||||
|
|
||||||
drop table basictest;
|
drop table basictest;
|
||||||
drop domain domainvarchar restrict;
|
drop domain domainvarchar restrict;
|
||||||
@ -111,12 +118,18 @@ ERROR: Domain dnotnull does not allow NULL values
|
|||||||
INSERT INTO nulltest values ('a', 'b', NULL, 'd');
|
INSERT INTO nulltest values ('a', 'b', NULL, 'd');
|
||||||
ERROR: ExecInsert: Fail to add null value in not null attribute col3
|
ERROR: ExecInsert: Fail to add null value in not null attribute col3
|
||||||
INSERT INTO nulltest values ('a', 'b', 'c', NULL); -- Good
|
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;
|
select * from nulltest;
|
||||||
col1 | col2 | col3 | col4
|
col1 | col2 | col3 | col4
|
||||||
------+------+------+------
|
------+------+------+------
|
||||||
a | b | c | d
|
a | b | c | d
|
||||||
a | b | c |
|
a | b | c |
|
||||||
(2 rows)
|
a | b | c |
|
||||||
|
(3 rows)
|
||||||
|
|
||||||
-- Test out coerced (casted) constraints
|
-- Test out coerced (casted) constraints
|
||||||
SELECT cast('1' as dnotnull);
|
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;
|
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;
|
select * from defaulttest;
|
||||||
col1 | col2 | col3 | col4 | col5 | col6 | col7 | col8
|
col1 | col2 | col3 | col4 | col5 | col6 | col7 | col8
|
||||||
------+------+------+------+------+------+------+-------
|
------+------+------+------+------+------+------+-------
|
||||||
3 | 12 | 5 | 1 | 3 | 88 | 8000 | 12.12
|
3 | 12 | 5 | 1 | 3 | 88 | 8000 | 12.12
|
||||||
3 | 12 | 5 | 2 | 3 | 88 | 8000 | 12.12
|
3 | 12 | 5 | 2 | 3 | 88 | 8000 | 12.12
|
||||||
3 | 12 | 5 | 3 | 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 sequence ddef4_seq;
|
||||||
drop table defaulttest;
|
drop table defaulttest;
|
||||||
|
@ -35,6 +35,16 @@ create table basictest
|
|||||||
INSERT INTO basictest values ('88', 'haha', 'short', '123.12'); -- Good
|
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 text', '123.12'); -- Bad varchar
|
||||||
INSERT INTO basictest values ('88', 'haha', 'short', '123.1212'); -- Truncate numeric
|
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;
|
select * from basictest;
|
||||||
|
|
||||||
-- check that domains inherit operations from base types
|
-- 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', NULL, 'c', 'd');
|
||||||
INSERT INTO nulltest values ('a', 'b', NULL, 'd');
|
INSERT INTO nulltest values ('a', 'b', NULL, 'd');
|
||||||
INSERT INTO nulltest values ('a', 'b', 'c', NULL); -- Good
|
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;
|
select * from nulltest;
|
||||||
|
|
||||||
-- Test out coerced (casted) constraints
|
-- 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;
|
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;
|
select * from defaulttest;
|
||||||
|
|
||||||
drop sequence ddef4_seq;
|
drop sequence ddef4_seq;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user