]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Instead of storing pg_statistic stavalues entries as text strings, store
authorTom Lane <tgl@sss.pgh.pa.us>
Sun, 23 Mar 2003 05:14:37 +0000 (05:14 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Sun, 23 Mar 2003 05:14:37 +0000 (05:14 +0000)
them as arrays of the internal datatype.  This requires treating the
stavalues columns as 'anyarray' rather than 'text[]', which is not 100%
kosher but seems to work fine for the purposes we need for pg_statistic.
Perhaps in the future 'anyarray' will be allowed more generally.

doc/src/sgml/catalogs.sgml
src/backend/catalog/heap.c
src/backend/commands/analyze.c
src/backend/utils/adt/selfuncs.c
src/backend/utils/cache/lsyscache.c
src/include/catalog/catversion.h
src/include/catalog/pg_statistic.h
src/test/regress/expected/rules.out

index 4b50e8f442769ba60ce540e5ab8a0fca4eae4787..ddac7b384204f9f5ecf8fb88d82880733289526c 100644 (file)
@@ -1,6 +1,6 @@
 <!--
  Documentation of the system catalogs, directed toward PostgreSQL developers
- $Header: /cvsroot/pgsql/doc/src/sgml/catalogs.sgml,v 2.66 2003/02/22 00:45:03 tgl Exp $
+ $Header: /cvsroot/pgsql/doc/src/sgml/catalogs.sgml,v 2.67 2003/03/23 05:14:36 tgl Exp $
  -->
 
 <chapter id="catalogs">
 
      <row>
       <entry>stavaluesN</entry>
-      <entry><type>text[]</type></entry>
+      <entry><type>anyarray</type></entry>
       <entry></entry>
       <entry>Column data values of the appropriate kind for the Nth
-      <quote>slot</quote>, or NULL if the slot kind does not store any data values.
-      For data-type independence, all column data values are converted
-      to external textual form and stored as TEXT datums.
+      <quote>slot</quote>, or NULL if the slot kind does not store any data
+      values.
+      Each array's element values are actually of the specific column's
+      datatype, so there is no way to define these columns' type more
+      specifically than <quote>anyarray</>.
       </entry>
      </row>
     </tbody>
index 105026a50e9a1e802d10f48d16e8ff76fbeeacb0..802f5932f7375b6ea907af719ea7372f50c7783d 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.240 2003/03/20 03:34:55 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.241 2003/03/23 05:14:36 tgl Exp $
  *
  *
  * INTERFACE ROUTINES
@@ -421,8 +421,12 @@ CheckAttributeType(const char *attname, Oid atttypid)
                         "\n\tProceeding with relation creation anyway",
                         attname);
        else if (att_typtype == 'p')
-               elog(ERROR, "Attribute \"%s\" has pseudo-type %s",
-                        attname, format_type_be(atttypid));
+       {
+               /* Special hack for pg_statistic: allow ANYARRAY during initdb */
+               if (atttypid != ANYARRAYOID || IsUnderPostmaster)
+                       elog(ERROR, "Attribute \"%s\" has pseudo-type %s",
+                                attname, format_type_be(atttypid));
+       }
        else if (att_typtype == 'c')
        {
                Oid             typrelid = get_typ_typrelid(atttypid);
index 2af7a3cd7c322d242225229b0bc2e871f9da4542..09862f6d8403dec8e859f3807d179be5699eb284 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/commands/analyze.c,v 1.51 2002/11/29 21:39:10 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/commands/analyze.c,v 1.52 2003/03/23 05:14:36 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1694,7 +1694,6 @@ update_attstats(Oid relid, int natts, VacAttrStats **vacattrstats)
        for (attno = 0; attno < natts; attno++)
        {
                VacAttrStats *stats = vacattrstats[attno];
-               FmgrInfo        out_function;
                HeapTuple       stup,
                                        oldtup;
                int                     i,
@@ -1708,8 +1707,6 @@ update_attstats(Oid relid, int natts, VacAttrStats **vacattrstats)
                if (!stats->stats_valid)
                        continue;
 
-               fmgr_info(stats->attrtype->typoutput, &out_function);
-
                /*
                 * Construct a new pg_statistic tuple
                 */
@@ -1758,33 +1755,16 @@ update_attstats(Oid relid, int natts, VacAttrStats **vacattrstats)
                }
                for (k = 0; k < STATISTIC_NUM_SLOTS; k++)
                {
-                       int                     ntxt = stats->numvalues[k];
-
-                       if (ntxt > 0)
+                       if (stats->numvalues[k] > 0)
                        {
-                               Datum      *txtdatums = (Datum *) palloc(ntxt * sizeof(Datum));
                                ArrayType  *arry;
 
-                               for (n = 0; n < ntxt; n++)
-                               {
-                                       /*
-                                        * Convert data values to a text string to be inserted
-                                        * into the text array.
-                                        */
-                                       Datum           stringdatum;
-
-                                       stringdatum =
-                                               FunctionCall3(&out_function,
-                                                                         stats->stavalues[k][n],
-                                                         ObjectIdGetDatum(stats->attrtype->typelem),
-                                                                 Int32GetDatum(stats->attr->atttypmod));
-                                       txtdatums[n] = DirectFunctionCall1(textin, stringdatum);
-                                       pfree(DatumGetPointer(stringdatum));
-                               }
-                               /* XXX knows more than it should about type text: */
-                               arry = construct_array(txtdatums, ntxt,
-                                                                          TEXTOID,
-                                                                          -1, false, 'i');
+                               arry = construct_array(stats->stavalues[k],
+                                                                          stats->numvalues[k],
+                                                                          stats->attr->atttypid,
+                                                                          stats->attrtype->typlen,
+                                                                          stats->attrtype->typbyval,
+                                                                          stats->attrtype->typalign);
                                values[i++] = PointerGetDatum(arry);    /* stavaluesN */
                        }
                        else
index 208b7eb29089a9c7c62fbacc4ecf67ed93cdd119..2a5ceb767f445f112911260ab39c652b50d52271 100644 (file)
@@ -15,7 +15,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/utils/adt/selfuncs.c,v 1.133 2003/03/23 01:49:02 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/utils/adt/selfuncs.c,v 1.134 2003/03/23 05:14:36 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1826,16 +1826,11 @@ mergejoinscansel(Query *root, Node *clause,
        /*
         * Now skip any binary-compatible relabeling; there can only be one level
         * since constant-expression folder eliminates adjacent RelabelTypes.
-        *
-        * XXX can't enable this quite yet, it exposes regproc uncertainty problems
-        * in regression tests.  FIXME soon.
         */
-#if 0
        if (IsA(left, RelabelType))
                left = (Var *) ((RelabelType *) left)->arg;
        if (IsA(right, RelabelType))
                right = (Var *) ((RelabelType *) right)->arg;
-#endif
 
        /* Can't do anything if inputs are not Vars */
        if (!IsA(left, Var) ||
index abc00a9204e02f1845f71f2f225d9cbbe8559ea2..277793905e096e8c7c9d6ce06f75e0979ed29c16 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/utils/cache/lsyscache.c,v 1.90 2003/02/03 21:15:44 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/utils/cache/lsyscache.c,v 1.91 2003/03/23 05:14:36 tgl Exp $
  *
  * NOTES
  *       Eventually, the index information should go through here, too.
@@ -28,6 +28,7 @@
 #include "nodes/makefuncs.h"
 #include "utils/array.h"
 #include "utils/builtins.h"
+#include "utils/datum.h"
 #include "utils/lsyscache.h"
 #include "utils/syscache.h"
 
@@ -1387,8 +1388,7 @@ get_attstatsslot(HeapTuple statstuple,
        ArrayType  *statarray;
        int                     narrayelem;
        HeapTuple       typeTuple;
-       FmgrInfo        inputproc;
-       Oid                     typelem;
+       Form_pg_type typeForm;
 
        for (i = 0; i < STATISTIC_NUM_SLOTS; i++)
        {
@@ -1408,48 +1408,40 @@ get_attstatsslot(HeapTuple statstuple,
                        elog(ERROR, "get_attstatsslot: stavalues is null");
                statarray = DatumGetArrayTypeP(val);
 
-               /*
-                * Do initial examination of the array.  This produces a list of
-                * text Datums --- ie, pointers into the text array value.
-                */
-               deconstruct_array(statarray,
-                                                 TEXTOID, -1, false, 'i',
-                                                 values, nvalues);
-               narrayelem = *nvalues;
-
-               /*
-                * We now need to replace each text Datum by its internal
-                * equivalent.
-                *
-                * Get the type input proc and typelem for the column datatype.
-                */
+               /* Need to get info about the array element type */
                typeTuple = SearchSysCache(TYPEOID,
                                                                   ObjectIdGetDatum(atttype),
                                                                   0, 0, 0);
                if (!HeapTupleIsValid(typeTuple))
                        elog(ERROR, "get_attstatsslot: Cache lookup failed for type %u",
                                 atttype);
-               fmgr_info(((Form_pg_type) GETSTRUCT(typeTuple))->typinput, &inputproc);
-               typelem = ((Form_pg_type) GETSTRUCT(typeTuple))->typelem;
-               ReleaseSysCache(typeTuple);
+               typeForm = (Form_pg_type) GETSTRUCT(typeTuple);
+
+               /* Deconstruct array into Datum elements */
+               deconstruct_array(statarray,
+                                                 atttype,
+                                                 typeForm->typlen,
+                                                 typeForm->typbyval,
+                                                 typeForm->typalign,
+                                                 values, nvalues);
 
                /*
-                * Do the conversions.  The palloc'd array of Datums is reused in
-                * place.
+                * If the element type is pass-by-reference, we now have a bunch
+                * of Datums that are pointers into the syscache value.  Copy them
+                * to avoid problems if syscache decides to drop the entry.
                 */
-               for (j = 0; j < narrayelem; j++)
+               if (!typeForm->typbyval)
                {
-                       char       *strval;
-
-                       strval = DatumGetCString(DirectFunctionCall1(textout,
-                                                                                                                (*values)[j]));
-                       (*values)[j] = FunctionCall3(&inputproc,
-                                                                                CStringGetDatum(strval),
-                                                                                ObjectIdGetDatum(typelem),
-                                                                                Int32GetDatum(atttypmod));
-                       pfree(strval);
+                       for (j = 0; j < *nvalues; j++)
+                       {
+                               (*values)[j] = datumCopy((*values)[j],
+                                                                                typeForm->typbyval,
+                                                                                typeForm->typlen);
+                       }
                }
 
+               ReleaseSysCache(typeTuple);
+
                /*
                 * Free statarray if it's a detoasted copy.
                 */
index 1bbd5f6636613a37a799d0ca18e169ab941b94df..a551518106019c596babcff1918042f0ae3fa58a 100644 (file)
@@ -37,7 +37,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: catversion.h,v 1.182 2003/03/21 01:58:04 tgl Exp $
+ * $Id: catversion.h,v 1.183 2003/03/23 05:14:37 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -53,6 +53,6 @@
  */
 
 /*                                                     yyyymmddN */
-#define CATALOG_VERSION_NO     200303201
+#define CATALOG_VERSION_NO     200303221
 
 #endif
index 8c8806a159a68fb0650516300045974a98cca223..c72c68265db47d567f3d486866ffa1e740eb6aef 100644 (file)
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: pg_statistic.h,v 1.19 2003/03/10 22:28:21 tgl Exp $
+ * $Id: pg_statistic.h,v 1.20 2003/03/23 05:14:37 tgl Exp $
  *
  * NOTES
  *       the genbki.sh script reads this file and generates .bki
  * ----------------
  */
 
+/*
+ * Keep C compiler happy with anyarray, below.  This will need to go elsewhere
+ * if we ever use anyarray for more than pg_statistic.
+ */
+typedef struct varlena anyarray;
+
 /* ----------------
  *             pg_statistic definition.  cpp turns this into
  *             typedef struct FormData_pg_statistic
@@ -109,14 +115,14 @@ CATALOG(pg_statistic) BKI_WITHOUT_OIDS
        float4          stanumbers4[1];
 
        /*
-        * Values in these text arrays are external representations of values
-        * of the column's data type.  To re-create the actual Datum, do
-        * datatypein(textout(arrayelement)).
+        * Values in these arrays are values of the column's data type.  We
+        * presently have to cheat quite a bit to allow polymorphic arrays
+        * of this kind, but perhaps someday it'll be a less bogus facility.
         */
-       text            stavalues1[1];
-       text            stavalues2[1];
-       text            stavalues3[1];
-       text            stavalues4[1];
+       anyarray        stavalues1;
+       anyarray        stavalues2;
+       anyarray        stavalues3;
+       anyarray        stavalues4;
 } FormData_pg_statistic;
 
 #define STATISTIC_NUM_SLOTS  4
index c0127828f22708eaa43922bbcdcbe9c809aa8644..f173b6cf5440cb40e50e6ae56613ad1c9bc967dc 100644 (file)
@@ -1267,8 +1267,8 @@ drop table cchild;
 -- Check that ruleutils are working
 --
 SELECT viewname, definition FROM pg_views WHERE schemaname <> 'information_schema' ORDER BY viewname;
-         viewname         |                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   definition                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
---------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+         viewname         |                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     definition                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      
+--------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  iexit                    | SELECT ih.name, ih.thepath, interpt_pp(ih.thepath, r.thepath) AS exit FROM ihighway ih, ramp r WHERE (ih.thepath ## r.thepath);
  pg_indexes               | SELECT n.nspname AS schemaname, c.relname AS tablename, i.relname AS indexname, pg_get_indexdef(i.oid) AS indexdef FROM (((pg_index x JOIN pg_class c ON ((c.oid = x.indrelid))) JOIN pg_class i ON ((i.oid = x.indexrelid))) LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace))) WHERE ((c.relkind = 'r'::"char") AND (i.relkind = 'i'::"char"));
  pg_locks                 | SELECT l.relation, l."database", l."transaction", l.pid, l."mode", l.granted FROM pg_lock_status() l(relation oid, "database" oid, "transaction" xid, pid integer, "mode" text, granted boolean);
@@ -1291,7 +1291,7 @@ SELECT viewname, definition FROM pg_views WHERE schemaname <> 'information_schem
  pg_statio_user_indexes   | SELECT pg_statio_all_indexes.relid, pg_statio_all_indexes.indexrelid, pg_statio_all_indexes.schemaname, pg_statio_all_indexes.relname, pg_statio_all_indexes.indexrelname, pg_statio_all_indexes.idx_blks_read, pg_statio_all_indexes.idx_blks_hit FROM pg_statio_all_indexes WHERE ((pg_statio_all_indexes.schemaname <> 'pg_catalog'::name) AND (pg_statio_all_indexes.schemaname <> 'pg_toast'::name));
  pg_statio_user_sequences | SELECT pg_statio_all_sequences.relid, pg_statio_all_sequences.schemaname, pg_statio_all_sequences.relname, pg_statio_all_sequences.blks_read, pg_statio_all_sequences.blks_hit FROM pg_statio_all_sequences WHERE ((pg_statio_all_sequences.schemaname <> 'pg_catalog'::name) AND (pg_statio_all_sequences.schemaname <> 'pg_toast'::name));
  pg_statio_user_tables    | SELECT pg_statio_all_tables.relid, pg_statio_all_tables.schemaname, pg_statio_all_tables.relname, pg_statio_all_tables.heap_blks_read, pg_statio_all_tables.heap_blks_hit, pg_statio_all_tables.idx_blks_read, pg_statio_all_tables.idx_blks_hit, pg_statio_all_tables.toast_blks_read, pg_statio_all_tables.toast_blks_hit, pg_statio_all_tables.tidx_blks_read, pg_statio_all_tables.tidx_blks_hit FROM pg_statio_all_tables WHERE ((pg_statio_all_tables.schemaname <> 'pg_catalog'::name) AND (pg_statio_all_tables.schemaname <> 'pg_toast'::name));
- pg_stats                 | SELECT nspname AS schemaname, relname AS tablename, attname, stanullfrac AS null_frac, stawidth AS avg_width, stadistinct AS n_distinct, CASE WHEN (1 = stakind1) THEN stavalues1 WHEN (1 = stakind2) THEN stavalues2 WHEN (1 = stakind3) THEN stavalues3 WHEN (1 = stakind4) THEN stavalues4 ELSE NULL::text[] END AS most_common_vals, CASE WHEN (1 = stakind1) THEN stanumbers1 WHEN (1 = stakind2) THEN stanumbers2 WHEN (1 = stakind3) THEN stanumbers3 WHEN (1 = stakind4) THEN stanumbers4 ELSE NULL::real[] END AS most_common_freqs, CASE WHEN (2 = stakind1) THEN stavalues1 WHEN (2 = stakind2) THEN stavalues2 WHEN (2 = stakind3) THEN stavalues3 WHEN (2 = stakind4) THEN stavalues4 ELSE NULL::text[] END AS histogram_bounds, CASE WHEN (3 = stakind1) THEN stanumbers1[1] WHEN (3 = stakind2) THEN stanumbers2[1] WHEN (3 = stakind3) THEN stanumbers3[1] WHEN (3 = stakind4) THEN stanumbers4[1] ELSE NULL::real END AS correlation FROM (((pg_statistic s JOIN pg_class c ON ((c.oid = s.starelid))) JOIN pg_attribute a ON (((c.oid = a.attrelid) AND (a.attnum = s.staattnum)))) LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace))) WHERE has_table_privilege(c.oid, 'select'::text);
+ pg_stats                 | SELECT nspname AS schemaname, relname AS tablename, attname, stanullfrac AS null_frac, stawidth AS avg_width, stadistinct AS n_distinct, CASE WHEN (1 = stakind1) THEN stavalues1 WHEN (1 = stakind2) THEN stavalues2 WHEN (1 = stakind3) THEN stavalues3 WHEN (1 = stakind4) THEN stavalues4 ELSE NULL::anyarray END AS most_common_vals, CASE WHEN (1 = stakind1) THEN stanumbers1 WHEN (1 = stakind2) THEN stanumbers2 WHEN (1 = stakind3) THEN stanumbers3 WHEN (1 = stakind4) THEN stanumbers4 ELSE NULL::real[] END AS most_common_freqs, CASE WHEN (2 = stakind1) THEN stavalues1 WHEN (2 = stakind2) THEN stavalues2 WHEN (2 = stakind3) THEN stavalues3 WHEN (2 = stakind4) THEN stavalues4 ELSE NULL::anyarray END AS histogram_bounds, CASE WHEN (3 = stakind1) THEN stanumbers1[1] WHEN (3 = stakind2) THEN stanumbers2[1] WHEN (3 = stakind3) THEN stanumbers3[1] WHEN (3 = stakind4) THEN stanumbers4[1] ELSE NULL::real END AS correlation FROM (((pg_statistic s JOIN pg_class c ON ((c.oid = s.starelid))) JOIN pg_attribute a ON (((c.oid = a.attrelid) AND (a.attnum = s.staattnum)))) LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace))) WHERE has_table_privilege(c.oid, 'select'::text);
  pg_tables                | SELECT n.nspname AS schemaname, c.relname AS tablename, pg_get_userbyid(c.relowner) AS tableowner, c.relhasindex AS hasindexes, c.relhasrules AS hasrules, (c.reltriggers > 0) AS hastriggers FROM (pg_class c LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace))) WHERE ((c.relkind = 'r'::"char") OR (c.relkind = 's'::"char"));
  pg_user                  | SELECT pg_shadow.usename, pg_shadow.usesysid, pg_shadow.usecreatedb, pg_shadow.usesuper, pg_shadow.usecatupd, '********'::text AS passwd, pg_shadow.valuntil, pg_shadow.useconfig FROM pg_shadow;
  pg_views                 | SELECT n.nspname AS schemaname, c.relname AS viewname, pg_get_userbyid(c.relowner) AS viewowner, pg_get_viewdef(c.oid) AS definition FROM (pg_class c LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace))) WHERE (c.relkind = 'v'::"char");