diff --git a/doc/src/sgml/datatype.sgml b/doc/src/sgml/datatype.sgml index 93f733e50fd38dab93905927496a1b46a48773f3..bbbc85197bb725b4df47fc3b9e85460d0918f80c 100644 --- a/doc/src/sgml/datatype.sgml +++ b/doc/src/sgml/datatype.sgml @@ -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,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> diff --git a/src/backend/utils/adt/varchar.c b/src/backend/utils/adt/varchar.c index 588c735ca10faa6f703b719dbf80d1f062d9f17e..467a5cf7de3975223533af95ce35804d539949ac 100644 --- a/src/backend/utils/adt/varchar.c +++ b/src/backend/utils/adt/varchar.c @@ -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) diff --git a/src/test/regress/expected/arrays.out b/src/test/regress/expected/arrays.out index b68783806402aed6a04cc6de7b54b63056d77fe7..74c1008d907582c812530250cb9b8a46104cc467 100644 --- a/src/test/regress/expected/arrays.out +++ b/src/test/regress/expected/arrays.out @@ -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) diff --git a/src/test/regress/expected/char.out b/src/test/regress/expected/char.out index 63606fba2d254545829fd0398fec1b6221954709..0c46e07976233fc0c6e7e3f947b5c1c490111189 100644 --- a/src/test/regress/expected/char.out +++ b/src/test/regress/expected/char.out @@ -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 ------+------ diff --git a/src/test/regress/expected/create_misc.out b/src/test/regress/expected/create_misc.out index add55bc767afd1b57fe409bd0a93f07222f0a20f..c7600fd13ff0d329bcc4130d7f6da13760d3de2e 100644 --- a/src/test/regress/expected/create_misc.out +++ b/src/test/regress/expected/create_misc.out @@ -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 ( diff --git a/src/test/regress/expected/create_table.out b/src/test/regress/expected/create_table.out index a0ddd5ef609a3367d567673255ea75877381b1e7..3734960691d848c966748ed2d23c2cc32b0ec74e 100644 --- a/src/test/regress/expected/create_table.out +++ b/src/test/regress/expected/create_table.out @@ -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 diff --git a/src/test/regress/expected/strings.out b/src/test/regress/expected/strings.out index e59ba8e1df5f8494f7884339319af1098b17635f..7562a25fdca5399ae0c4b745243c76a38b4e1afe 100644 --- a/src/test/regress/expected/strings.out +++ b/src/test/regress/expected/strings.out @@ -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"; diff --git a/src/test/regress/expected/varchar.out b/src/test/regress/expected/varchar.out index 5f4c0f1f56f3b56cad70030f4bc46d8113652546..e33782eed74a818666bcc93591cd3d6fafeb9df5 100644 --- a/src/test/regress/expected/varchar.out +++ b/src/test/regress/expected/varchar.out @@ -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 ------+------ diff --git a/src/test/regress/sql/arrays.sql b/src/test/regress/sql/arrays.sql index 3b02acf6427252a14e57a2aca414fbc28e9a8ad7..a3300eae129d2fea48c7961bf8b5fec5b9cc1ffb 100644 --- a/src/test/regress/sql/arrays.sql +++ b/src/test/regress/sql/arrays.sql @@ -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], diff --git a/src/test/regress/sql/char.sql b/src/test/regress/sql/char.sql index ba7167fc659b167c63154c3a06a267f7a079ef70..049f22fad39e5cbbdc7203db59932981d61c6203 100644 --- a/src/test/regress/sql/char.sql +++ b/src/test/regress/sql/char.sql @@ -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.*; - diff --git a/src/test/regress/sql/create_misc.sql b/src/test/regress/sql/create_misc.sql index cd73f64060513bb34dc15c48ec4b09cc506bfced..078450a754416d6fa421bebc42080f260b66f05f 100644 --- a/src/test/regress/sql/create_misc.sql +++ b/src/test/regress/sql/create_misc.sql @@ -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 diff --git a/src/test/regress/sql/create_table.sql b/src/test/regress/sql/create_table.sql index fe5470894483fa7cfadcb5293966f8342bfb5023..b6a0a8fe603d37d6b071657a9a4238c8799ddcca 100644 --- a/src/test/regress/sql/create_table.sql +++ b/src/test/regress/sql/create_table.sql @@ -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 diff --git a/src/test/regress/sql/strings.sql b/src/test/regress/sql/strings.sql index f1c7d5f298911bd586f0bbb835030cc5acdc9578..56510f83dddc9eee78dadaae42adfbc6340d8933 100644 --- a/src/test/regress/sql/strings.sql +++ b/src/test/regress/sql/strings.sql @@ -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"; diff --git a/src/test/regress/sql/varchar.sql b/src/test/regress/sql/varchar.sql index e28c8f9b932bc8e52f1fbbb82b8f591b53e79f94..70fa8afb4b3754bc06240f419f67363a9ec56f4b 100644 --- a/src/test/regress/sql/varchar.sql +++ b/src/test/regress/sql/varchar.sql @@ -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.*; -