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.
This commit is contained in:
Peter Eisentraut 2001-05-21 16:54:46 +00:00
parent d27f363e3f
commit 5546ec289b
14 changed files with 351 additions and 236 deletions

View File

@ -1,5 +1,5 @@
<!--
$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,14 +550,77 @@ CREATE TABLE <replaceable class="parameter">tablename</replaceable> (<replaceabl
<see>character strings</see>
</indexterm>
<table tocentry="1">
<title>Character Types</title>
<tgroup cols="3">
<thead>
<row>
<entry>Type Name</entry>
<entry>Storage</entry>
<entry>Description</entry>
</row>
</thead>
<tbody>
<row>
<entry>character(n), char(n)</entry>
<entry>(4+n) bytes</entry>
<entry>Fixed-length blank padded</entry>
</row>
<row>
<entry>character varying(n), varchar(n)</entry>
<entry>(4+n) bytes</entry>
<entry>Variable-length with limit</entry>
</row>
<row>
<entry>text</entry>
<entry>(4+n) bytes</entry>
<entry>Variable unlimited length</entry>
</row>
</tbody>
</tgroup>
</table>
<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.
<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>
@ -566,48 +629,49 @@ CREATE TABLE <replaceable class="parameter">tablename</replaceable> (<replaceabl
for information about available operators and functions.
</para>
<para>
<table tocentry="1">
<title>Character Types</title>
<tgroup cols="4">
<thead>
<row>
<entry>Type Name</entry>
<entry>Storage</entry>
<entry>Recommendation</entry>
<entry>Description</entry>
</row>
</thead>
<tbody>
<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>
<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>
<note>
<para>
Although the type <type>text</type> is not SQL-compliant, many
other RDBMS packages have it as well.
</para>
</note>
</para>
<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
@ -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>

View File

@ -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;
#ifdef MULTIBYTE
size_t mbmaxlen = pg_mbcliplen(s, len, maxlen);
if (strspn(s + mbmaxlen, " ") == len - mbmaxlen)
len = mbmaxlen;
#else
if (strspn(s + maxlen, " ") == len - maxlen)
/* clip extra spaces */
len = maxlen;
#endif
else
elog(ERROR, "value too long for type character(%d)", maxlen);
}
else
#ifdef MULTIBYTE
{
/* If typmod is -1 (or invalid), use the actual string length */
maxlen = len;
/*
* truncate multi-byte string preserving multi-byte boundary
*/
len = pg_mbcliplen(s, atttypmod - VARHDRSZ, atttypmod - VARHDRSZ);
}
#else
len = atttypmod - VARHDRSZ;
#endif
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
result = (BpChar *) palloc(len);
VARATT_SIZEP(result) = len;
r = VARDATA(result);
#ifdef MULTIBYTE
/*
* 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;
#else
slen = VARSIZE(str) - VARHDRSZ;
#endif
s = VARDATA(str);
#ifdef STRINGDEBUG
printf("bpchar- string is '");
#endif
for (i = 0; (i < rlen) && (i < slen); i++)
if (len > maxlen)
{
#ifdef STRINGDEBUG
printf("%c", *s);
#ifdef MULTIBYTE
size_t maxmblen;
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(%d)",
maxlen - VARHDRSZ);
len = maxmblen;
#else
for (i = maxlen - VARHDRSZ; i < len - VARHDRSZ; i++)
if (*(VARDATA(source) + i) != ' ')
elog(ERROR, "value too long for type character(%d)",
maxlen - VARHDRSZ);
/* clip extra spaces */
len = maxlen;
#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) + VARHDRSZ;
if (atttypmod >= (int32) VARHDRSZ && len > atttypmod)
len = strlen(s);
maxlen = atttypmod - VARHDRSZ;
if (atttypmod >= (int32) VARHDRSZ && len > maxlen)
{
#ifdef MULTIBYTE
len = pg_mbcliplen(s, len - VARHDRSZ, atttypmod - VARHDRSZ) + VARHDRSZ;
#else
len = atttypmod; /* clip the string at max length */
#endif
size_t mbmaxlen = pg_mbcliplen(s, len, maxlen);
result = (VarChar *) palloc(len);
VARATT_SIZEP(result) = len;
memcpy(VARDATA(result), s, len - VARHDRSZ);
if (strspn(s + mbmaxlen, " ") == len - mbmaxlen)
len = mbmaxlen;
#else
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 = 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)

View File

@ -1,6 +1,32 @@
--
-- 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)

View File

@ -1,6 +1,5 @@
--
-- CHAR
-- all inputs are SILENTLY truncated at 1 character
--
-- 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
------+------

View File

@ -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 (

View File

@ -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

View File

@ -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)
------------
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 n
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";

View File

@ -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
------+------

View File

@ -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],

View File

@ -1,6 +1,5 @@
--
-- CHAR
-- all inputs are SILENTLY truncated at 1 character
--
-- 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.*;

View File

@ -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

View File

@ -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

View File

@ -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";

View File

@ -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.*;