提交 ca869e25 编写于 作者: J Jim Doty 提交者: Jacob Champion

COPY: fix transfer of "unknown" data type

The "unknown" type has an attlen of -2, which signifies that the actual
length is determined by strlen(). We weren't handling this case, so
handle it now.
Co-authored-by: NJacob Champion <pchampion@pivotal.io>
上级 fdd878ea
......@@ -5025,10 +5025,8 @@ retry:
(errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
errmsg("unexpected EOF in COPY data")));
}
else
else if (attr[attnum - 1]->attlen == -1)
{
Assert (attr[attnum - 1]->attlen == -1);
/* For simplicity, varlen's are always transmitted in "long" format */
if (CopyGetData(cstate, &len, sizeof(len)) != sizeof(len))
ereport(ERROR,
......@@ -5043,6 +5041,29 @@ retry:
(errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
errmsg("unexpected EOF in COPY data")));
}
else if (attr[attnum - 1]->attlen == -2)
{
/*
* Like the varlen case above, cstrings are sent with a length
* prefix and no terminator, so we have to NULL-terminate in
* memory after reading them in.
*/
if (CopyGetData(cstate, &len, sizeof(len)) != sizeof(len))
ereport(ERROR,
(errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
errmsg("unexpected EOF in COPY data")));
p = palloc(len + 1);
if (CopyGetData(cstate, p, len) != len)
ereport(ERROR,
(errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
errmsg("unexpected EOF in COPY data")));
p[len] = '\0';
}
else
{
elog(ERROR, "attribute %d has invalid length %d",
attnum, attr[attnum - 1]->attlen);
}
value = PointerGetDatum(p);
}
......@@ -5165,7 +5186,7 @@ SendCopyFromForwardedTuple(CopyState cstate,
{
appendBinaryStringInfo(msgbuf, DatumGetPointer(values[i]), attr[i]->attlen);
}
else
else if (attr[attnum - 1]->attlen == -1)
{
int32 len;
char *ptr;
......@@ -5176,7 +5197,6 @@ SendCopyFromForwardedTuple(CopyState cstate,
* in the master, and the default value comes from another table as a toast
* pointer.
*/
Assert (attr[attnum - 1]->attlen == -1);
/* For simplicity, varlen's are always transmitted in "long" format */
len = VARSIZE(values[i]);
......@@ -5185,6 +5205,36 @@ SendCopyFromForwardedTuple(CopyState cstate,
appendBinaryStringInfo(msgbuf, &len, sizeof(int32));
appendBinaryStringInfo(msgbuf, ptr, len - VARHDRSZ);
}
else if (attr[attnum - 1]->attlen == -2)
{
/*
* These attrs are NULL-terminated in memory, but we send
* them length-prefixed (like the varlen case above) so that
* the receiver can preallocate a data buffer.
*/
int32 len;
size_t slen;
char *ptr;
ptr = DatumGetPointer(values[i]);
slen = strlen(ptr);
if (slen > PG_INT32_MAX)
{
elog(ERROR, "attribute %d is too long (%lld bytes)",
attnum, (long long) slen);
}
len = (int32) slen;
appendBinaryStringInfo(msgbuf, &len, sizeof(len));
appendBinaryStringInfo(msgbuf, ptr, len);
}
else
{
elog(ERROR, "attribute %d has invalid length %d",
attnum, attr[attnum - 1]->attlen);
}
}
num_sent_fields++;
......
......@@ -177,6 +177,15 @@ SELECT * FROM testnull;
|
(4 rows)
-- "unknown" types can be dumped and restored: these attributes are
-- NULL-terminated in memory (attlen == -2), so the COPY code needs to handle
-- them explicitly.
CREATE TEMP TABLE type_unknown ( a unknown );
WARNING: column "a" has type "unknown"
DETAIL: Proceeding with relation creation anyway.
COPY type_unknown FROM stdin;
COPY type_unknown TO stdout;
unknown
DROP TABLE x, y;
DROP FUNCTION fn_x_before();
DROP FUNCTION fn_x_after();
......@@ -178,6 +178,16 @@ COPY testnull FROM stdin WITH NULL AS E'\\0';
SELECT * FROM testnull;
-- "unknown" types can be dumped and restored: these attributes are
-- NULL-terminated in memory (attlen == -2), so the COPY code needs to handle
-- them explicitly.
CREATE TEMP TABLE type_unknown ( a unknown );
COPY type_unknown FROM stdin;
unknown
\.
COPY type_unknown TO stdout;
DROP TABLE x, y;
DROP FUNCTION fn_x_before();
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册