More sensible character_octet_length
authorPeter Eisentraut <peter_e@gmx.net>
Tue, 7 Jul 2009 18:23:15 +0000 (18:23 +0000)
committerPeter Eisentraut <peter_e@gmx.net>
Tue, 7 Jul 2009 18:23:15 +0000 (18:23 +0000)
For character types with typmod, character_octet_length columns in the
information schema now show the maximum character length times the
maximum length of a character in the server encoding, instead of some
huge value as before.

doc/src/sgml/information_schema.sgml
src/backend/catalog/information_schema.sql
src/backend/utils/mb/mbutils.c
src/include/catalog/catversion.h
src/include/catalog/pg_proc.h
src/include/utils/builtins.h

index 8e145d7ef1163d8cfd1fd3689999378e71565523..6460862cfb00a2bb7e25a93a3c96f8cff5af890a 100644 (file)
       <entry><type>cardinal_number</type></entry>
       <entry>
        If <literal>data_type</literal> identifies a character type,
-       the maximum possible length in octets (bytes) of a datum (this
-       should not be of concern to
-       <productname>PostgreSQL</productname> users); null for all
-       other data types.
+       the maximum possible length in octets (bytes) of a datum; null
+       for all other data types.  The maximum octet length depends on
+       the declared character maximum length (see above) and the
+       server encoding.
       </entry>
      </row>
 
       <entry><type>cardinal_number</type></entry>
       <entry>
        If <literal>data_type</literal> identifies a character type,
-       the maximum possible length in octets (bytes) of a datum (this
-       should not be of concern to <productname>PostgreSQL</productname> users); null for all
-       other data types.
+       the maximum possible length in octets (bytes) of a datum; null
+       for all other data types.  The maximum octet length depends on
+       the declared character maximum length (see above) and the
+       server encoding.
       </entry>
      </row>
 
       <entry><type>cardinal_number</type></entry>
       <entry>
        If the domain has a character type, the maximum possible length
-       in octets (bytes) of a datum (this should not be of concern to
-       <productname>PostgreSQL</productname> users); null for all
-       other data types.
+       in octets (bytes) of a datum; null for all other data types.
+       The maximum octet length depends on the declared character
+       maximum length (see above) and the server encoding.
       </entry>
      </row>
 
index fe753221c6e6f097120a8b74804179592b4ff75a..27a15c9c979dfb515b7f008ce499b3c010adab04 100644 (file)
@@ -104,7 +104,10 @@ CREATE FUNCTION _pg_char_octet_length(typid oid, typmod int4) RETURNS integer
     AS
 $$SELECT
   CASE WHEN $1 IN (25, 1042, 1043) /* text, char, varchar */
-       THEN CAST(2^30 AS integer)
+       THEN CASE WHEN $2 = -1 /* default typmod */
+                 THEN CAST(2^30 AS integer)
+                 ELSE information_schema._pg_char_max_length($1, $2) * pg_catalog.pg_encoding_max_length((SELECT encoding FROM pg_database WHERE datname = current_database()))
+            END
        ELSE null
   END$$;
 
index 753c927df397ed9ca3c025de10f31e3d90108ce6..058493ca37a950cd223f7ee7d7980d80ef899a01 100644 (file)
@@ -482,6 +482,17 @@ length_in_encoding(PG_FUNCTION_ARGS)
 
 }
 
+Datum
+pg_encoding_max_length_sql(PG_FUNCTION_ARGS)
+{
+       int encoding = PG_GETARG_INT32(0);
+
+       if (PG_VALID_ENCODING(encoding))
+               return pg_wchar_table[encoding].maxmblen;
+       else
+               PG_RETURN_NULL();
+}
+
 /*
  * convert client encoding to server encoding.
  */
index 1e742511e4b72897cd1eed7b9d9dca2d81b0d252..98eba9b69969458f604f8a2c6d2462bf85f88e57 100644 (file)
@@ -53,6 +53,6 @@
  */
 
 /*                                                     yyyymmddN */
-#define CATALOG_VERSION_NO     200904091
+#define CATALOG_VERSION_NO     200907071
 
 #endif
index 0285acd154ab16ea3c75544e05ac3e1ca2573c81..e194d6a91d8bea7bc5243b17f935ce97309054cd 100644 (file)
@@ -2278,6 +2278,9 @@ DESCR("convert encoding name to encoding id");
 DATA(insert OID = 1597 (  pg_encoding_to_char     PGNSP PGUID 12 1 0 0 f f f t f s 1 0 19 "23" _null_ _null_ _null_ _null_ PG_encoding_to_char _null_ _null_ _null_ ));
 DESCR("convert encoding id to encoding name");
 
+DATA(insert OID = 2319 (  pg_encoding_max_length   PGNSP PGUID 12 1 0 0 f f f t f i 1 0 23 "23" _null_ _null_ _null_ _null_ pg_encoding_max_length_sql _null_ _null_ _null_ ));
+DESCR("maximum octet length of a character in an eocidng");
+
 DATA(insert OID = 1638 (  oidgt                                   PGNSP PGUID 12 1 0 0 f f f t f i 2 0 16 "26 26" _null_ _null_ _null_ _null_ oidgt _null_ _null_ _null_ ));
 DESCR("greater-than");
 DATA(insert OID = 1639 (  oidge                                   PGNSP PGUID 12 1 0 0 f f f t f i 2 0 16 "26 26" _null_ _null_ _null_ _null_ oidge _null_ _null_ _null_ ));
index c1b93932ee3d69b9ae2fbb93dc3b212f12953038..13fd41a9bc1868da97fd9670aafe15e1008c15f8 100644 (file)
@@ -948,6 +948,7 @@ extern Datum pg_convert(PG_FUNCTION_ARGS);
 extern Datum pg_convert_to(PG_FUNCTION_ARGS);
 extern Datum pg_convert_from(PG_FUNCTION_ARGS);
 extern Datum length_in_encoding(PG_FUNCTION_ARGS);
+extern Datum pg_encoding_max_length_sql(PG_FUNCTION_ARGS);
 
 /* format_type.c */
 extern Datum format_type(PG_FUNCTION_ARGS);