From: Tom Lane Date: Mon, 12 Nov 2001 21:04:46 +0000 (+0000) Subject: Tweak parser so that there is a defined representation for datatypes X-Git-Tag: REL9_0_0~19102 X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=a585c20d12d0e22befc8308e9f8ccb6f54a5df69;p=pg-rex%2Fsyncrep.git Tweak parser so that there is a defined representation for datatypes 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. --- diff --git a/doc/src/sgml/datatype.sgml b/doc/src/sgml/datatype.sgml index 83ffcca275..5a9e927745 100644 --- a/doc/src/sgml/datatype.sgml +++ b/doc/src/sgml/datatype.sgml @@ -1,5 +1,5 @@ @@ -533,14 +533,18 @@ NUMERIC(precision, scale) NUMERIC(precision) - selects a scale of 0. Merely specifying + selects a scale of 0. Specifying NUMERIC - 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 numeric 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.) @@ -852,13 +856,17 @@ CREATE TABLE tablename ( The storage requirement for data of these types is 4 bytes plus the actual string, and in case of character 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 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 text + or character varying without a length specifier, + rather than making up an arbitrary length limit.) @@ -916,7 +924,7 @@ SELECT b, char_length(b) FROM test2; Postgres. The name type exists only 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 NAMEDATALEN. The length is set at compile time (and is therefore adjustable for special uses); the default diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c index 104e1ab3ba..87df6f55e7 100644 --- a/src/backend/parser/analyze.c +++ b/src/backend/parser/analyze.c @@ -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 diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index 6c6b7e359c..5a2324de20 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -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; diff --git a/src/backend/utils/adt/format_type.c b/src/backend/utils/adt/format_type.c index af928933dd..55caa8d1b6 100644 --- a/src/backend/utils/adt/format_type.c +++ b/src/backend/utils/adt/format_type.c @@ -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)