提交 5546ec28 编写于 作者: P Peter Eisentraut

Make char(n) and varchar(n) types raise an error if the inserted string is

too long.  While I was adjusting the regression tests I moved the array
things all into array.sql, to make things more manageable.
上级 d27f363e
<!--
$Header: /cvsroot/pgsql/doc/src/sgml/datatype.sgml,v 1.53 2001/05/12 22:51:34 petere Exp $
$Header: /cvsroot/pgsql/doc/src/sgml/datatype.sgml,v 1.54 2001/05/21 16:54:45 petere Exp $
-->
<chapter id="datatype">
......@@ -550,31 +550,13 @@ CREATE TABLE <replaceable class="parameter">tablename</replaceable> (<replaceabl
<see>character strings</see>
</indexterm>
<para>
<acronym>SQL</acronym> defines two primary character types:
<type>character</type> and <type>character varying</type>.
<productname>Postgres</productname> supports these types, in
addition to the more general <type>text</type> type,
which unlike <type>character varying</type>
does not require an explicit declared upper
limit on the size of the field.
</para>
<para>
Refer to <xref linkend="sql-syntax-strings"> for information about
the syntax of string literals, and to <xref linkend="functions">
for information about available operators and functions.
</para>
<para>
<table tocentry="1">
<title>Character Types</title>
<tgroup cols="4">
<tgroup cols="3">
<thead>
<row>
<entry>Type Name</entry>
<entry>Storage</entry>
<entry>Recommendation</entry>
<entry>Description</entry>
</row>
</thead>
......@@ -582,33 +564,115 @@ CREATE TABLE <replaceable class="parameter">tablename</replaceable> (<replaceabl
<row>
<entry>character(n), char(n)</entry>
<entry>(4+n) bytes</entry>
<entry><acronym>SQL</acronym>-compatible</entry>
<entry>Fixed-length blank padded</entry>
</row>
<row>
<entry>character varying(n), varchar(n)</entry>
<entry>(4+n) bytes</entry>
<entry><acronym>SQL</acronym>-compatible</entry>
<entry>Variable-length with limit</entry>
</row>
<row>
<entry>text</entry>
<entry>(4+n) bytes</entry>
<entry>Most flexible</entry>
<entry>Variable unlimited length</entry>
</row>
</tbody>
</tgroup>
</table>
<note>
<para>
Although the type <type>text</type> is not SQL-compliant, many
other RDBMS packages have it as well.
</para>
</note>
<para>
<acronym>SQL</acronym> defines two primary character types:
<type>character(<replaceable>n</>)</type> and <type>character
varying(<replaceable>n</>)</type>, where <replaceable>n</> is a
positive integer. Both of these types can store strings up to
<replaceable>n</> characters in length. An attempt to store a
longer string into a column of these types will result in an
error, unless the excess characters are all spaces, in which case
the string will be truncated to the maximum length. (This
somewhat bizarre exception is required by the SQL standard.) If
the string to be stored is shorter than the declared length,
values of type <type>character</type> will be space-padded; values
of type <type>character varying</type> will simply store the
shorter string.
</para>
<note>
<para>
Prior to PostgreSQL 7.2, strings that were too long were silently
truncated, no error was raised.
</para>
</note>
<para>
The notations <type>char(<replaceable>n</>)</type> and
<type>varchar(<replaceable>n</>)</type> are aliases for
<type>character(<replaceable>n</>)</type> and <type>character
varying(<replaceable>n</>)</type>,
respectively. <type>character</type> without length specifier is
equivalent to <type>character(1)</type>; if <type>character
varying</type> is used without length specifier, the type accepts
strings of any size. The latter is a PostgreSQL extension.
</para>
<para>
In addition, <productname>PostgreSQL</productname> supports the
more general <type>text</type> type, which stores strings of any
length. Unlike <type>character varying</type>, <type>text</type>
does not require an explicit declared upper limit on the size of
the string. Although the type <type>text</type> is not in the SQL
standard, many other RDBMS packages have it as well.
</para>
<para>
Refer to <xref linkend="sql-syntax-strings"> for information about
the syntax of string literals, and to <xref linkend="functions">
for information about available operators and functions.
</para>
<tip>
<para>
There are no performance differences between these three types,
apart from the increased storage size when using the blank-padded
type.
</para>
</tip>
<example>
<title>Using the character types</title>
<programlisting>
CREATE TABLE test1 (a character(4));
INSERT INTO test1 VALUES ('ok');
SELECT a, char_length(a) FROM test1; -- <co id="co.datatype-char">
<computeroutput>
a | char_length
------+-------------
ok | 4
</computeroutput>
CREATE TABLE test2 (b varchar(5));
INSERT INTO test2 VALUES ('ok');
INSERT INTO test2 VALUES ('good ');
INSERT INTO test2 VALUES ('too long');
<computeroutput>ERROR: value too long for type character varying(5)</computeroutput>
SELECT b, char_length(b) FROM test2;
<computeroutput>
b | char_length
-------+-------------
ok | 2
good | 5
</computeroutput>
</programlisting>
<calloutlist>
<callout arearefs="co.datatype-char">
<para>
The <function>char_length</function> function is discussed in
<xref linkend="functions-string">.
</para>
</callout>
</calloutlist>
</example>
<para>
There are two other fixed-length character types in
<productname>Postgres</productname>. The <type>name</type> type
......@@ -625,7 +689,6 @@ CREATE TABLE <replaceable class="parameter">tablename</replaceable> (<replaceabl
enumeration type.
</para>
<para>
<table tocentry="1">
<title>Specialty Character Type</title>
<tgroup cols="3">
......@@ -650,7 +713,6 @@ CREATE TABLE <replaceable class="parameter">tablename</replaceable> (<replaceabl
</tbody>
</tgroup>
</table>
</para>
</sect1>
......
......@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/adt/varchar.c,v 1.77 2001/05/03 19:00:36 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/utils/adt/varchar.c,v 1.78 2001/05/21 16:54:46 petere Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -55,9 +55,11 @@
*****************************************************************************/
/*
* bpcharin -
* converts a string of char() type to the internal representation.
* len is the length specified in () plus VARHDRSZ bytes.
* Convert a C string to CHARACTER internal representation. atttypmod
* is the declared length of the type plus VARHDRSZ.
*
* If the C string is too long, raise an error, unless the extra
* characters are spaces, in which case they're truncated. (per SQL)
*/
Datum
bpcharin(PG_FUNCTION_ARGS)
......@@ -71,30 +73,33 @@ bpcharin(PG_FUNCTION_ARGS)
int32 atttypmod = PG_GETARG_INT32(2);
BpChar *result;
char *r;
int len;
size_t len, maxlen;
int i;
if (atttypmod < (int32) VARHDRSZ)
len = strlen(s);
maxlen = atttypmod - VARHDRSZ;
if (atttypmod >= (int32) VARHDRSZ && len > maxlen)
{
/* If typmod is -1 (or invalid), use the actual string length */
len = strlen(s);
atttypmod = len + VARHDRSZ;
}
else
#ifdef MULTIBYTE
{
size_t mbmaxlen = pg_mbcliplen(s, len, maxlen);
/*
* truncate multi-byte string preserving multi-byte boundary
*/
len = pg_mbcliplen(s, atttypmod - VARHDRSZ, atttypmod - VARHDRSZ);
}
if (strspn(s + mbmaxlen, " ") == len - mbmaxlen)
len = mbmaxlen;
#else
len = atttypmod - VARHDRSZ;
if (strspn(s + maxlen, " ") == len - maxlen)
/* clip extra spaces */
len = maxlen;
#endif
else
elog(ERROR, "value too long for type character(%d)", maxlen);
}
else
/* If typmod is -1 (or invalid), use the actual string length */
maxlen = len;
result = (BpChar *) palloc(atttypmod);
VARATT_SIZEP(result) = atttypmod;
result = palloc(maxlen + VARHDRSZ);
VARATT_SIZEP(result) = maxlen + VARHDRSZ;
r = VARDATA(result);
for (i = 0; i < len; i++, r++, s++)
{
......@@ -108,16 +113,16 @@ bpcharin(PG_FUNCTION_ARGS)
#endif
/* blank pad the string if necessary */
#ifdef MULTIBYTE
for (; i < atttypmod - VARHDRSZ; i++)
#else
for (; i < len; i++)
#endif
for (; i < maxlen; i++)
*r++ = ' ';
PG_RETURN_BPCHAR_P(result);
}
/*
* Convert a CHARACTER value to a C string.
*/
Datum
bpcharout(PG_FUNCTION_ARGS)
{
......@@ -138,75 +143,70 @@ bpcharout(PG_FUNCTION_ARGS)
PG_RETURN_CSTRING(result);
}
/* bpchar()
* Converts a char() type to a specific internal length.
* len is the length specified in () plus VARHDRSZ bytes.
/*
* Converts a CHARACTER type to the specified size. maxlen is the new
* declared length plus VARHDRSZ bytes. Truncation
* rules see bpcharin() above.
*/
Datum
bpchar(PG_FUNCTION_ARGS)
{
BpChar *str = PG_GETARG_BPCHAR_P(0);
int32 len = PG_GETARG_INT32(1);
BpChar *source = PG_GETARG_BPCHAR_P(0);
int32 maxlen = PG_GETARG_INT32(1);
BpChar *result;
char *r,
*s;
int rlen,
slen;
int32 len;
char *r;
char *s;
int i;
len = VARSIZE(source);
/* No work if typmod is invalid or supplied data matches it already */
if (len < (int32) VARHDRSZ || len == VARSIZE(str))
PG_RETURN_BPCHAR_P(str);
if (len < (int32) VARHDRSZ || len == maxlen)
PG_RETURN_BPCHAR_P(source);
rlen = len - VARHDRSZ;
#ifdef STRINGDEBUG
printf("bpchar- convert string length %d (%d) ->%d (%d)\n",
VARSIZE(str) - VARHDRSZ, VARSIZE(str), rlen, len);
#endif
if (len > maxlen)
{
#ifdef MULTIBYTE
size_t maxmblen;
result = (BpChar *) palloc(len);
VARATT_SIZEP(result) = len;
r = VARDATA(result);
maxmblen = pg_mbcliplen(VARDATA(source), len - VARHDRSZ,
maxlen - VARHDRSZ) + VARHDRSZ;
#ifdef MULTIBYTE
for (i = maxmblen - VARHDRSZ; i < len - VARHDRSZ; i++)
if (*(VARDATA(source) + i) != ' ')
elog(ERROR, "value too long for type character(%d)",
maxlen - VARHDRSZ);
/*
* truncate multi-byte string in a way not to break multi-byte
* boundary
*/
if (VARSIZE(str) > len)
slen = pg_mbcliplen(VARDATA(str), VARSIZE(str) - VARHDRSZ, rlen);
else
slen = VARSIZE(str) - VARHDRSZ;
len = maxmblen;
#else
slen = VARSIZE(str) - VARHDRSZ;
#endif
s = VARDATA(str);
for (i = maxlen - VARHDRSZ; i < len - VARHDRSZ; i++)
if (*(VARDATA(source) + i) != ' ')
elog(ERROR, "value too long for type character(%d)",
maxlen - VARHDRSZ);
#ifdef STRINGDEBUG
printf("bpchar- string is '");
/* clip extra spaces */
len = maxlen;
#endif
for (i = 0; (i < rlen) && (i < slen); i++)
{
#ifdef STRINGDEBUG
printf("%c", *s);
#endif
*r++ = *s++;
}
#ifdef STRINGDEBUG
printf("'\n");
#endif
s = VARDATA(source);
result = palloc(maxlen);
VARATT_SIZEP(result) = maxlen;
r = VARDATA(result);
for (i = 0; (i < maxlen - VARHDRSZ) && (i < len - VARHDRSZ); i++)
*r++ = *s++;
/* blank pad the string if necessary */
for (; i < rlen; i++)
for (; i < maxlen - VARHDRSZ; i++)
*r++ = ' ';
PG_RETURN_BPCHAR_P(result);
}
/* _bpchar()
* Converts an array of char() elements to a specific internal length.
* len is the length specified in () plus VARHDRSZ bytes.
......@@ -330,9 +330,11 @@ name_bpchar(PG_FUNCTION_ARGS)
*****************************************************************************/
/*
* varcharin -
* converts a string of varchar() type to the internal representation.
* len is the length specified in () plus VARHDRSZ bytes.
* Convert a C string to VARCHAR internal representation. atttypmod
* is the declared length of the type plus VARHDRSZ.
*
* If the C string is too long, raise an error, unless the extra
* characters are spaces, in which case they're truncated. (per SQL)
*/
Datum
varcharin(PG_FUNCTION_ARGS)
......@@ -345,37 +347,52 @@ varcharin(PG_FUNCTION_ARGS)
#endif
int32 atttypmod = PG_GETARG_INT32(2);
VarChar *result;
int len;
size_t len, maxlen;
len = strlen(s);
maxlen = atttypmod - VARHDRSZ;
len = strlen(s) + VARHDRSZ;
if (atttypmod >= (int32) VARHDRSZ && len > atttypmod)
if (atttypmod >= (int32) VARHDRSZ && len > maxlen)
{
#ifdef MULTIBYTE
len = pg_mbcliplen(s, len - VARHDRSZ, atttypmod - VARHDRSZ) + VARHDRSZ;
size_t mbmaxlen = pg_mbcliplen(s, len, maxlen);
if (strspn(s + mbmaxlen, " ") == len - mbmaxlen)
len = mbmaxlen;
#else
len = atttypmod; /* clip the string at max length */
if (strspn(s + maxlen, " ") == len - maxlen)
/* clip extra spaces */
len = maxlen;
#endif
else
elog(ERROR, "value too long for type character varying(%d)", maxlen);
}
result = (VarChar *) palloc(len);
VARATT_SIZEP(result) = len;
memcpy(VARDATA(result), s, len - VARHDRSZ);
result = palloc(len + VARHDRSZ);
VARATT_SIZEP(result) = len + VARHDRSZ;
memcpy(VARDATA(result), s, len);
#ifdef CYR_RECODE
convertstr(VARDATA(result), len - VARHDRSZ, 0);
convertstr(VARDATA(result), len, 0);
#endif
PG_RETURN_VARCHAR_P(result);
}
/*
* Convert a VARCHAR value to a C string.
*/
Datum
varcharout(PG_FUNCTION_ARGS)
{
VarChar *s = PG_GETARG_VARCHAR_P(0);
char *result;
int len;
int32 len;
/* copy and add null term */
len = VARSIZE(s) - VARHDRSZ;
result = (char *) palloc(len + 1);
result = palloc(len + 1);
memcpy(result, VARDATA(s), len);
result[len] = '\0';
......@@ -386,42 +403,60 @@ varcharout(PG_FUNCTION_ARGS)
PG_RETURN_CSTRING(result);
}
/* varchar()
* Converts a varchar() type to the specified size.
* slen is the length specified in () plus VARHDRSZ bytes.
/*
* Converts a VARCHAR type to the specified size. maxlen is the new
* declared length plus VARHDRSZ bytes. Truncation
* rules see varcharin() above.
*/
Datum
varchar(PG_FUNCTION_ARGS)
{
VarChar *s = PG_GETARG_VARCHAR_P(0);
int32 slen = PG_GETARG_INT32(1);
VarChar *source = PG_GETARG_VARCHAR_P(0);
int32 maxlen = PG_GETARG_INT32(1);
VarChar *result;
int len;
int32 len;
int i;
len = VARSIZE(s);
if (slen < (int32) VARHDRSZ || len <= slen)
PG_RETURN_VARCHAR_P(s);
len = VARSIZE(source);
if (maxlen < (int32) VARHDRSZ || len <= maxlen)
PG_RETURN_VARCHAR_P(source);
/* only reach here if we need to truncate string... */
/* only reach here if string is too long... */
#ifdef MULTIBYTE
{
size_t maxmblen;
/*
* truncate multi-byte string preserving multi-byte boundary
*/
len = pg_mbcliplen(VARDATA(s), slen - VARHDRSZ, slen - VARHDRSZ);
slen = len + VARHDRSZ;
/* truncate multi-byte string preserving multi-byte boundary */
maxmblen = pg_mbcliplen(VARDATA(source), len - VARHDRSZ,
maxlen - VARHDRSZ) + VARHDRSZ;
for (i = maxmblen - VARHDRSZ; i < len - VARHDRSZ; i++)
if (*(VARDATA(source) + i) != ' ')
elog(ERROR, "value too long for type character varying(%d)",
maxlen - VARHDRSZ);
len = maxmblen;
}
#else
len = slen - VARHDRSZ;
for (i = maxlen - VARHDRSZ; i < len - VARHDRSZ; i++)
if (*(VARDATA(source) + i) != ' ')
elog(ERROR, "value too long for type character varying(%d)",
maxlen - VARHDRSZ);
/* clip extra spaces */
len = maxlen;
#endif
result = (VarChar *) palloc(slen);
VARATT_SIZEP(result) = slen;
memcpy(VARDATA(result), VARDATA(s), len);
result = palloc(len);
VARATT_SIZEP(result) = len;
memcpy(VARDATA(result), VARDATA(source), len - VARHDRSZ);
PG_RETURN_VARCHAR_P(result);
}
/* _varchar()
* Converts an array of varchar() elements to the specified size.
* len is the length specified in () plus VARHDRSZ bytes.
......@@ -452,6 +487,12 @@ _varchar(PG_FUNCTION_ARGS)
return array_map(&locfcinfo, VARCHAROID, VARCHAROID);
}
/*****************************************************************************
* Exported functions
*****************************************************************************/
/* "True" length (not counting trailing blanks) of a BpChar */
static int
bcTruelen(BpChar *arg)
......
--
-- ARRAYS
--
CREATE TABLE arrtest (
a int2[],
b int4[][][],
c name[],
d text[][],
e float8[],
f char(5)[],
g varchar(5)[]
);
--
-- only this array as a 0-based 'e', the others are 1-based.
-- 'e' is also a large object.
--
INSERT INTO arrtest (a[5], b[2][1][2], c, d, f, g)
VALUES ('{1,2,3,4,5}', '{{{},{1,2}}}', '{}', '{}', '{}', '{}');
UPDATE arrtest SET e[0] = '1.1';
UPDATE arrtest SET e[1] = '2.2';
INSERT INTO arrtest (f)
VALUES ('{"too long"}');
ERROR: value too long for type character(5)
INSERT INTO arrtest (a, b[2][2][1], c, d, e, f, g)
VALUES ('{11,12,23}', '{{3,4},{4,5}}', '{"foobar"}',
'{{"elt1", "elt2"}}', '{"3.4", "6.7"}',
'{"abc","abcde"}', '{"abc","abcde"}');
INSERT INTO arrtest (a, b[1][2][2], c, d[2][1])
VALUES ('{}', '{3,4}', '{foo,bar}', '{bar,foo}');
SELECT * FROM arrtest;
a | b | c | d | e | f | g
-------------+-----------------+---------------+-------------------+---------------+-------------------+-----------------
......@@ -75,8 +101,8 @@ SELECT a,b,c FROM arrtest;
a | b | c
---------------+-----------------------+-----------------------
{16,25,3,4,5} | {{{113,142},{1,147}}} | {}
{16,25,23} | {{3,4},{4,5}} | {"foobar","new_word"}
{} | {3,4} | {"foo","new_word"}
{16,25,23} | {{3,4},{4,5}} | {"foobar","new_word"}
(3 rows)
SELECT a[1:3],
......@@ -87,7 +113,7 @@ SELECT a[1:3],
a | b | c | d
------------+-----------------------+-----------------------+------------
{16,25,3} | {{{113,142},{1,147}}} | |
{16,25,23} | | {"foobar","new_word"} | {{"elt2"}}
| | {"foo","new_word"} |
{16,25,23} | | {"foobar","new_word"} | {{"elt2"}}
(3 rows)
--
-- CHAR
--
-- fixed-length by value
-- internally passed by value if <= 4 bytes in storage
......@@ -24,6 +23,8 @@ INSERT INTO CHAR_TBL (f1) VALUES ('3');
INSERT INTO CHAR_TBL (f1) VALUES ('');
-- try char's of greater than 1 length
INSERT INTO CHAR_TBL (f1) VALUES ('cd');
ERROR: value too long for type character(1)
INSERT INTO CHAR_TBL (f1) VALUES ('c ');
SELECT '' AS seven, CHAR_TBL.*;
seven | f1
-------+----
......@@ -108,6 +109,8 @@ INSERT INTO CHAR_TBL (f1) VALUES ('a');
INSERT INTO CHAR_TBL (f1) VALUES ('ab');
INSERT INTO CHAR_TBL (f1) VALUES ('abcd');
INSERT INTO CHAR_TBL (f1) VALUES ('abcde');
ERROR: value too long for type character(4)
INSERT INTO CHAR_TBL (f1) VALUES ('abcd ');
SELECT '' AS four, CHAR_TBL.*;
four | f1
------+------
......
......@@ -121,23 +121,6 @@ INSERT INTO f_star (class, f)
VALUES ('f', '(11111111,33333333),(22222222,44444444)'::polygon);
INSERT INTO f_star (class) VALUES ('f');
--
-- ARRAYS
--
--
-- only this array as a 0-based 'e', the others are 1-based.
-- 'e' is also a large object.
--
INSERT INTO arrtest (a[5], b[2][1][2], c, d, f, g)
VALUES ('{1,2,3,4,5}', '{{{},{1,2}}}', '{}', '{}', '{}', '{}');
UPDATE arrtest SET e[0] = '1.1';
UPDATE arrtest SET e[1] = '2.2';
INSERT INTO arrtest (a, b[2][2][1], c, d, e, f, g)
VALUES ('{11,12,23}', '{{3,4},{4,5}}', '{"foobar"}',
'{{"elt1", "elt2"}}', '{"3.4", "6.7"}',
'{"abc","abcdefgh"}', '{"abc","abcdefgh"}');
INSERT INTO arrtest (a, b[1][2][2], c, d[2][1])
VALUES ('{}', '{3,4}', '{foo,bar}', '{bar,foo}');
--
-- for internal portal (cursor) tests
--
CREATE TABLE iportaltest (
......
......@@ -147,15 +147,6 @@ CREATE TABLE aggtest (
a int2,
b float4
);
CREATE TABLE arrtest (
a int2[],
b int4[][][],
c name[],
d text[][],
e float8[],
f char(5)[],
g varchar(5)[]
);
CREATE TABLE hash_i4_heap (
seqno int4,
random int4
......
......@@ -45,11 +45,13 @@ SELECT CAST(name 'namefield' AS text) AS "text(name)";
namefield
(1 row)
SELECT CAST(f1 AS char(10)) AS "char(text)" FROM TEXT_TBL;
char(text)
------------
doh!
hi de ho n
SELECT CAST(f1 AS char(10)) AS "char(text)" FROM TEXT_TBL; -- fail
ERROR: value too long for type character(10)
SELECT CAST(f1 AS char(20)) AS "char(text)" FROM TEXT_TBL;
char(text)
----------------------
doh!
hi de ho neighbor
(2 rows)
SELECT CAST(f1 AS char(10)) AS "char(varchar)" FROM VARCHAR_TBL;
......@@ -479,10 +481,10 @@ SELECT text 'text' || ' and unknown' AS "Concat text to unknown type";
text and unknown
(1 row)
SELECT text 'text' || char(10) ' and characters' AS "Concat text to char";
SELECT text 'text' || char(20) ' and characters' AS "Concat text to char";
Concat text to char
---------------------
text and chara
text and characters
(1 row)
SELECT text 'text' || varchar ' and varchar' AS "Concat text to varchar";
......
......@@ -12,6 +12,8 @@ INSERT INTO VARCHAR_TBL (f1) VALUES ('3');
INSERT INTO VARCHAR_TBL (f1) VALUES ('');
-- try varchar's of greater than 1 length
INSERT INTO VARCHAR_TBL (f1) VALUES ('cd');
ERROR: value too long for type character varying(1)
INSERT INTO VARCHAR_TBL (f1) VALUES ('c ');
SELECT '' AS seven, VARCHAR_TBL.*;
seven | f1
-------+----
......@@ -96,6 +98,8 @@ INSERT INTO VARCHAR_TBL (f1) VALUES ('a');
INSERT INTO VARCHAR_TBL (f1) VALUES ('ab');
INSERT INTO VARCHAR_TBL (f1) VALUES ('abcd');
INSERT INTO VARCHAR_TBL (f1) VALUES ('abcde');
ERROR: value too long for type character varying(4)
INSERT INTO VARCHAR_TBL (f1) VALUES ('abcd ');
SELECT '' AS four, VARCHAR_TBL.*;
four | f1
------+------
......
......@@ -2,6 +2,40 @@
-- ARRAYS
--
CREATE TABLE arrtest (
a int2[],
b int4[][][],
c name[],
d text[][],
e float8[],
f char(5)[],
g varchar(5)[]
);
--
-- only this array as a 0-based 'e', the others are 1-based.
-- 'e' is also a large object.
--
INSERT INTO arrtest (a[5], b[2][1][2], c, d, f, g)
VALUES ('{1,2,3,4,5}', '{{{},{1,2}}}', '{}', '{}', '{}', '{}');
UPDATE arrtest SET e[0] = '1.1';
UPDATE arrtest SET e[1] = '2.2';
INSERT INTO arrtest (f)
VALUES ('{"too long"}');
INSERT INTO arrtest (a, b[2][2][1], c, d, e, f, g)
VALUES ('{11,12,23}', '{{3,4},{4,5}}', '{"foobar"}',
'{{"elt1", "elt2"}}', '{"3.4", "6.7"}',
'{"abc","abcde"}', '{"abc","abcde"}');
INSERT INTO arrtest (a, b[1][2][2], c, d[2][1])
VALUES ('{}', '{3,4}', '{foo,bar}', '{bar,foo}');
SELECT * FROM arrtest;
SELECT arrtest.a[1],
......
--
-- CHAR
--
-- fixed-length by value
......@@ -30,6 +29,7 @@ INSERT INTO CHAR_TBL (f1) VALUES ('');
-- try char's of greater than 1 length
INSERT INTO CHAR_TBL (f1) VALUES ('cd');
INSERT INTO CHAR_TBL (f1) VALUES ('c ');
SELECT '' AS seven, CHAR_TBL.*;
......@@ -70,6 +70,6 @@ INSERT INTO CHAR_TBL (f1) VALUES ('a');
INSERT INTO CHAR_TBL (f1) VALUES ('ab');
INSERT INTO CHAR_TBL (f1) VALUES ('abcd');
INSERT INTO CHAR_TBL (f1) VALUES ('abcde');
INSERT INTO CHAR_TBL (f1) VALUES ('abcd ');
SELECT '' AS four, CHAR_TBL.*;
......@@ -188,30 +188,6 @@ INSERT INTO f_star (class, f)
INSERT INTO f_star (class) VALUES ('f');
--
-- ARRAYS
--
--
-- only this array as a 0-based 'e', the others are 1-based.
-- 'e' is also a large object.
--
INSERT INTO arrtest (a[5], b[2][1][2], c, d, f, g)
VALUES ('{1,2,3,4,5}', '{{{},{1,2}}}', '{}', '{}', '{}', '{}');
UPDATE arrtest SET e[0] = '1.1';
UPDATE arrtest SET e[1] = '2.2';
INSERT INTO arrtest (a, b[2][2][1], c, d, e, f, g)
VALUES ('{11,12,23}', '{{3,4},{4,5}}', '{"foobar"}',
'{{"elt1", "elt2"}}', '{"3.4", "6.7"}',
'{"abc","abcdefgh"}', '{"abc","abcdefgh"}');
INSERT INTO arrtest (a, b[1][2][2], c, d[2][1])
VALUES ('{}', '{3,4}', '{foo,bar}', '{bar,foo}');
--
-- for internal portal (cursor) tests
......
......@@ -172,16 +172,6 @@ CREATE TABLE aggtest (
b float4
);
CREATE TABLE arrtest (
a int2[],
b int4[][][],
c name[],
d text[][],
e float8[],
f char(5)[],
g varchar(5)[]
);
CREATE TABLE hash_i4_heap (
seqno int4,
random int4
......
......@@ -25,7 +25,9 @@ SELECT CAST(f1 AS text) AS "text(varchar)" FROM VARCHAR_TBL;
SELECT CAST(name 'namefield' AS text) AS "text(name)";
SELECT CAST(f1 AS char(10)) AS "char(text)" FROM TEXT_TBL;
SELECT CAST(f1 AS char(10)) AS "char(text)" FROM TEXT_TBL; -- fail
SELECT CAST(f1 AS char(20)) AS "char(text)" FROM TEXT_TBL;
SELECT CAST(f1 AS char(10)) AS "char(varchar)" FROM VARCHAR_TBL;
......@@ -158,7 +160,7 @@ SELECT 'unknown' || ' and unknown' AS "Concat unknown types";
SELECT text 'text' || ' and unknown' AS "Concat text to unknown type";
SELECT text 'text' || char(10) ' and characters' AS "Concat text to char";
SELECT text 'text' || char(20) ' and characters' AS "Concat text to char";
SELECT text 'text' || varchar ' and varchar' AS "Concat text to varchar";
......@@ -20,6 +20,7 @@ INSERT INTO VARCHAR_TBL (f1) VALUES ('');
-- try varchar's of greater than 1 length
INSERT INTO VARCHAR_TBL (f1) VALUES ('cd');
INSERT INTO VARCHAR_TBL (f1) VALUES ('c ');
SELECT '' AS seven, VARCHAR_TBL.*;
......@@ -60,6 +61,6 @@ INSERT INTO VARCHAR_TBL (f1) VALUES ('a');
INSERT INTO VARCHAR_TBL (f1) VALUES ('ab');
INSERT INTO VARCHAR_TBL (f1) VALUES ('abcd');
INSERT INTO VARCHAR_TBL (f1) VALUES ('abcde');
INSERT INTO VARCHAR_TBL (f1) VALUES ('abcd ');
SELECT '' AS four, VARCHAR_TBL.*;
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册