OSDN Git Service

Tweak parser so that there is a defined representation for datatypes
authorTom Lane <tgl@sss.pgh.pa.us>
Mon, 12 Nov 2001 21:04:46 +0000 (21:04 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Mon, 12 Nov 2001 21:04:46 +0000 (21:04 +0000)
bpchar, bit, numeric with typmod -1.  Alter format_type so that this
representation is printed when the typmod is -1.  This ensures that
tables having such columns can be pg_dump'd and reloaded correctly.
Also, remove the rather useless and non-SQL-compliant default
precision and scale for type NUMERIC.  A numeric column declared as
such (with no precision/scale) will now have typmod -1 which means
that numeric values of any precision/scale can be stored in it,
without conversion to a uniform scale.  This seems significantly
more useful than the former behavior.  Part of response to bug #513.

doc/src/sgml/datatype.sgml
src/backend/parser/analyze.c
src/backend/parser/gram.y
src/backend/utils/adt/format_type.c

index 83ffcca..5a9e927 100644 (file)
@@ -1,5 +1,5 @@
 <!--
-$Header: /cvsroot/pgsql/doc/src/sgml/datatype.sgml,v 1.68 2001/11/08 23:36:55 petere Exp $
+$Header: /cvsroot/pgsql/doc/src/sgml/datatype.sgml,v 1.69 2001/11/12 21:04:45 tgl Exp $
 -->
 
  <chapter id="datatype">
@@ -533,14 +533,18 @@ NUMERIC(<replaceable>precision</replaceable>, <replaceable>scale</replaceable>)
 <programlisting>
 NUMERIC(<replaceable>precision</replaceable>)
 </programlisting>
-     selects a scale of 0.  Merely specifying
+     selects a scale of 0.  Specifying
 <programlisting>
 NUMERIC
 </programlisting>
-     uses a default precision and scale, which is currently (30,6).
-     (The SQL standard requires a default scale of 0.  We find this a
-     bit useless.  If you're concerned about portability, always
-     specify the precision and scale explicitly.)
+     without any precision or scale creates a column in which numeric
+     values of any precision and scale can be stored, up to the implementation
+     limit on precision.  A column of this kind will not coerce input
+     values to any particular scale, whereas <type>numeric</type> columns
+     with a declared scale will coerce input values to that scale.
+     (The SQL standard requires a default scale of 0, ie, coercion to
+     integer accuracy.  We find this a bit useless.  If you're concerned about
+     portability, always specify the precision and scale explicitly.)
     </para>
 
     <para>
@@ -852,13 +856,17 @@ CREATE TABLE <replaceable class="parameter">tablename</replaceable> (<replaceabl
    <para>
     The storage requirement for data of these types is 4 bytes plus
     the actual string, and in case of <type>character</type> plus the
-    padding.  Long strings will actually be compressed by the system
-    automatically.  In any case, the longest possible character string
+    padding.  Long strings will be compressed by the system
+    automatically, so the physical requirement on-disk may be less.
+    In any case, the longest possible character string
     that can be stored is about 1 GB.  (The maximum value that will be
     allowed for <replaceable>n</> in the data type declaration is
-    actually larger than that.  It wouldn't be very useful to change
+    less than that.  It wouldn't be very useful to change
     this because with multibyte character encodings the number of
-    characters and bytes can be quite different anyway.)
+    characters and bytes can be quite different anyway.  If you desire
+    to store long strings with no specific upper limit, use <type>text</type>
+    or <type>character varying</type> without a length specifier,
+    rather than making up an arbitrary length limit.)
    </para>
 
    <tip>
@@ -916,7 +924,7 @@ SELECT b, char_length(b) FROM test2;
     <productname>Postgres</productname>.  The <type>name</type> type
     exists <emphasis>only</emphasis> for storage of internal catalog
     names and is not intended for use by the general user.  Its length
-    is currently defined as 32 bytes (31 characters plus terminator)
+    is currently defined as 32 bytes (31 usable characters plus terminator)
     but should be referenced using the macro
     <symbol>NAMEDATALEN</symbol>.  The length is set at compile time
     (and is therefore adjustable for special uses); the default
index 104e1ab..87df6f5 100644 (file)
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- *     $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.211 2001/11/05 17:46:26 momjian Exp $
+ *     $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.212 2001/11/12 21:04:45 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -34,7 +34,6 @@
 #include "rewrite/rewriteManip.h"
 #include "utils/builtins.h"
 #include "utils/fmgroids.h"
-#include "utils/numeric.h"
 #include "utils/relcache.h"
 #include "utils/syscache.h"
 #include "utils/temprel.h"
@@ -3180,32 +3179,6 @@ transformColumnType(ParseState *pstate, ColumnDef *column)
        Type            ctype = typenameType(typename->name);
 
        /*
-        * If the column doesn't have an explicitly specified typmod, check to
-        * see if we want to insert a default length.
-        *
-        * Note that we deliberately do NOT look at array or set information
-        * here; "numeric[]" needs the same default typmod as "numeric".
-        */
-       if (typename->typmod == -1)
-       {
-               switch (typeTypeId(ctype))
-               {
-                       case BPCHAROID:
-                               /* "char" -> "char(1)" */
-                               typename->typmod = VARHDRSZ + 1;
-                               break;
-                       case NUMERICOID:
-                               typename->typmod = VARHDRSZ +
-                                       ((NUMERIC_DEFAULT_PRECISION << 16) | NUMERIC_DEFAULT_SCALE);
-                               break;
-                       case BITOID:
-                               /* 'bit' -> 'bit(1)' */
-                               typename->typmod = 1;
-                               break;
-               }
-       }
-
-       /*
         * Is this the name of a complex type? If so, implement it as a set.
         *
         * XXX this is a hangover from ancient Berkeley code that probably
index 6c6b7e3..5a2324d 100644 (file)
@@ -11,7 +11,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.273 2001/11/10 22:31:49 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.274 2001/11/12 21:04:45 tgl Exp $
  *
  * HISTORY
  *       AUTHOR                        DATE                    MAJOR EVENT
@@ -4156,7 +4156,7 @@ opt_numeric:  '(' Iconst ',' Iconst ')'
                                }
                | /*EMPTY*/
                                {
-                                       /* Insert "-1" meaning "default"; may be replaced later */
+                                       /* Insert "-1" meaning "no limit" */
                                        $$ = -1;
                                }
                ;
@@ -4182,7 +4182,7 @@ opt_decimal:  '(' Iconst ',' Iconst ')'
                                }
                | /*EMPTY*/
                                {
-                                       /* Insert "-1" meaning "default"; may be replaced later */
+                                       /* Insert "-1" meaning "no limit" */
                                        $$ = -1;
                                }
                ;
@@ -4208,8 +4208,11 @@ Bit:  bit '(' Iconst ')'
                                {
                                        $$ = makeNode(TypeName);
                                        $$->name = $1;
-                                       /* default length, if needed, will be inserted later */
-                                       $$->typmod = -1;
+                                       /* bit defaults to bit(1), varbit to no limit */
+                                       if (strcmp($1, "bit") == 0)
+                                               $$->typmod = 1;
+                                       else
+                                               $$->typmod = -1;
                                }
                ;
 
@@ -4259,8 +4262,11 @@ Character:  character '(' Iconst ')' opt_charset
                                {
                                        $$ = makeNode(TypeName);
                                        $$->name = $1;
-                                       /* default length, if needed, will be inserted later */
-                                       $$->typmod = -1;
+                                       /* char defaults to char(1), varchar to no limit */
+                                       if (strcmp($1, "bpchar") == 0)
+                                               $$->typmod = VARHDRSZ + 1;
+                                       else
+                                               $$->typmod = -1;
 
                                        if (($2 != NULL) && (strcmp($2, "sql_text") != 0)) {
                                                char *type;
index af92893..55caa8d 100644 (file)
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/utils/adt/format_type.c,v 1.21 2001/10/25 05:49:44 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/utils/adt/format_type.c,v 1.22 2001/11/12 21:04:46 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -163,6 +163,21 @@ format_type_internal(Oid type_oid, int32 typemod, bool allow_invalid)
 
        switch (type_oid)
        {
+               case BITOID:
+                       if (with_typemod)
+                               buf = psnprintf(5 + MAX_INT32_LEN + 1, "bit(%d)",
+                                                               (int) typemod);
+                       else
+                       {
+                               /*
+                                * bit with no typmod is not the same as BIT, which means
+                                * BIT(1) per SQL spec.  Report it as the quoted typename
+                                * so that parser will not assign a bogus typmod.
+                                */
+                               buf = pstrdup("\"bit\"");
+                       }
+                       break;
+
                case BOOLOID:
                        buf = pstrdup("boolean");
                        break;
@@ -172,11 +187,17 @@ format_type_internal(Oid type_oid, int32 typemod, bool allow_invalid)
                                buf = psnprintf(11 + MAX_INT32_LEN + 1, "character(%d)",
                                                                (int) (typemod - VARHDRSZ));
                        else
-                               buf = pstrdup("character");
+                       {
+                               /*
+                                * bpchar with no typmod is not the same as CHARACTER,
+                                * which means CHARACTER(1) per SQL spec.  Report it as
+                                * bpchar so that parser will not assign a bogus typmod.
+                                */
+                               buf = pstrdup("bpchar");
+                       }
                        break;
 
                case CHAROID:
-
                        /*
                         * This char type is the single-byte version. You have to
                         * double-quote it to get at it in the parser.
@@ -329,14 +350,6 @@ format_type_internal(Oid type_oid, int32 typemod, bool allow_invalid)
                                buf = pstrdup("character varying");
                        break;
 
-               case BITOID:
-                       if (with_typemod)
-                               buf = psnprintf(5 + MAX_INT32_LEN + 1, "bit(%d)",
-                                                               (int) typemod);
-                       else
-                               buf = pstrdup("bit");
-                       break;
-
                default:
                        name = NameStr(((Form_pg_type) GETSTRUCT(tuple))->typname);
                        if (strspn(name, "abcdefghijklmnopqrstuvwxyz0123456789_") != strlen(name)