]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Make char(n) and varchar(n) types raise an error if the inserted string is
authorPeter Eisentraut <peter_e@gmx.net>
Mon, 21 May 2001 16:54:46 +0000 (16:54 +0000)
committerPeter Eisentraut <peter_e@gmx.net>
Mon, 21 May 2001 16:54:46 +0000 (16:54 +0000)
too long.  While I was adjusting the regression tests I moved the array
things all into array.sql, to make things more manageable.

14 files changed:
doc/src/sgml/datatype.sgml
src/backend/utils/adt/varchar.c
src/test/regress/expected/arrays.out
src/test/regress/expected/char.out
src/test/regress/expected/create_misc.out
src/test/regress/expected/create_table.out
src/test/regress/expected/strings.out
src/test/regress/expected/varchar.out
src/test/regress/sql/arrays.sql
src/test/regress/sql/char.sql
src/test/regress/sql/create_misc.sql
src/test/regress/sql/create_table.sql
src/test/regress/sql/strings.sql
src/test/regress/sql/varchar.sql

index 93f733e50fd38dab93905927496a1b46a48773f3..bbbc85197bb725b4df47fc3b9e85460d0918f80c 100644 (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,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>
 
index 588c735ca10faa6f703b719dbf80d1f062d9f17e..467a5cf7de3975223533af95ce35804d539949ac 100644 (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 $
  *
  *-------------------------------------------------------------------------
  */
  *****************************************************************************/
 
 /*
- * 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)
index b68783806402aed6a04cc6de7b54b63056d77fe7..74c1008d907582c812530250cb9b8a46104cc467 100644 (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)
 
index 63606fba2d254545829fd0398fec1b6221954709..0c46e07976233fc0c6e7e3f947b5c1c490111189 100644 (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  
 ------+------
index add55bc767afd1b57fe409bd0a93f07222f0a20f..c7600fd13ff0d329bcc4130d7f6da13760d3de2e 100644 (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 (
index a0ddd5ef609a3367d567673255ea75877381b1e7..3734960691d848c966748ed2d23c2cc32b0ec74e 100644 (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
index e59ba8e1df5f8494f7884339319af1098b17635f..7562a25fdca5399ae0c4b745243c76a38b4e1afe 100644 (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) 
-------------
- 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";
index 5f4c0f1f56f3b56cad70030f4bc46d8113652546..e33782eed74a818666bcc93591cd3d6fafeb9df5 100644 (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  
 ------+------
index 3b02acf6427252a14e57a2aca414fbc28e9a8ad7..a3300eae129d2fea48c7961bf8b5fec5b9cc1ffb 100644 (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],
index ba7167fc659b167c63154c3a06a267f7a079ef70..049f22fad39e5cbbdc7203db59932981d61c6203 100644 (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.*;
-
index cd73f64060513bb34dc15c48ec4b09cc506bfced..078450a754416d6fa421bebc42080f260b66f05f 100644 (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
index fe5470894483fa7cfadcb5293966f8342bfb5023..b6a0a8fe603d37d6b071657a9a4238c8799ddcca 100644 (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
index f1c7d5f298911bd586f0bbb835030cc5acdc9578..56510f83dddc9eee78dadaae42adfbc6340d8933 100644 (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";
 
index e28c8f9b932bc8e52f1fbbb82b8f591b53e79f94..70fa8afb4b3754bc06240f419f67363a9ec56f4b 100644 (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.*;
-