From ce7565ab91100747d250ef67d72af5c1b01150d4 Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Wed, 31 Jul 2002 17:19:54 +0000
Subject: [PATCH] Instead of having a configure-time DEFAULT_ATTSTATTARGET,
 store -1 in attstattarget to indicate 'use the default'.  The default is now
 a GUC variable default_statistics_target, and so may be changed on the fly. 
 Along the way we gain the ability to have pg_dump dump the per-column
 statistics target when it's not the default.  Patch by Neil Conway, with some
 kibitzing from Tom Lane.

---
 doc/src/sgml/catalogs.sgml                    |  7 ++--
 doc/src/sgml/ref/alter_table.sgml             |  4 ++-
 doc/src/sgml/ref/analyze.sgml                 | 10 +++---
 doc/src/sgml/runtime.sgml                     | 15 +++++++-
 src/backend/access/common/tupdesc.c           |  4 +--
 src/backend/catalog/genbki.sh                 |  6 ++--
 src/backend/catalog/heap.c                    |  4 +--
 src/backend/commands/analyze.c                | 17 ++++++---
 src/backend/commands/tablecmds.c              | 16 ++++++---
 src/backend/parser/gram.y                     |  8 ++---
 src/backend/utils/misc/guc.c                  |  7 +++-
 src/backend/utils/misc/postgresql.conf.sample |  1 +
 src/bin/pg_dump/pg_dump.c                     | 35 ++++++++++++++++---
 src/bin/pg_dump/pg_dump.h                     |  3 +-
 src/bin/psql/tab-complete.c                   |  3 +-
 src/include/catalog/pg_attribute.h            | 33 ++++++++---------
 src/include/commands/vacuum.h                 |  5 ++-
 src/include/pg_config.h.in                    |  7 +---
 18 files changed, 125 insertions(+), 60 deletions(-)

diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml
index 13f883a65de..8bf4bf816f0 100644
--- a/doc/src/sgml/catalogs.sgml
+++ b/doc/src/sgml/catalogs.sgml
@@ -1,6 +1,6 @@
 <!--
  Documentation of the system catalogs, directed toward PostgreSQL developers
- $Header: /cvsroot/pgsql/doc/src/sgml/catalogs.sgml,v 2.49 2002/07/30 05:24:56 tgl Exp $
+ $Header: /cvsroot/pgsql/doc/src/sgml/catalogs.sgml,v 2.50 2002/07/31 17:19:49 tgl Exp $
  -->
 
 <chapter id="catalogs">
@@ -672,8 +672,9 @@
        of statistics accumulated for this column by
        <command>ANALYZE</command>.
        A zero value indicates that no statistics should be collected.
-       The exact meaning of positive values is data type-dependent.
-       For scalar data types, <structfield>attstattarget</structfield>
+       A negative value says to use the system default statistics target.
+       The exact meaning of positive values is datatype-dependent.
+       For scalar datatypes, <structfield>attstattarget</structfield>
        is both the target number of <quote>most common values</quote>
        to collect, and the target number of histogram bins to create.
       </entry>
diff --git a/doc/src/sgml/ref/alter_table.sgml b/doc/src/sgml/ref/alter_table.sgml
index 9acd474203c..11da9fdf60c 100644
--- a/doc/src/sgml/ref/alter_table.sgml
+++ b/doc/src/sgml/ref/alter_table.sgml
@@ -1,5 +1,5 @@
 <!--
-$Header: /cvsroot/pgsql/doc/src/sgml/ref/alter_table.sgml,v 1.46 2002/07/12 18:43:12 tgl Exp $
+$Header: /cvsroot/pgsql/doc/src/sgml/ref/alter_table.sgml,v 1.47 2002/07/31 17:19:50 tgl Exp $
 PostgreSQL documentation
 -->
 
@@ -218,6 +218,8 @@ ALTER TABLE <replaceable class="PARAMETER">table</replaceable>
       This form
       sets the per-column statistics-gathering target for subsequent
       <xref linkend="sql-analyze" endterm="sql-analyze-title"> operations.
+      The target can be set in the range 0 to 1000; alternatively, set it
+      to -1 to revert to using the system default statistics target.
      </para>
     </listitem>
    </varlistentry>
diff --git a/doc/src/sgml/ref/analyze.sgml b/doc/src/sgml/ref/analyze.sgml
index 5fbef560dec..72dc5cdcdeb 100644
--- a/doc/src/sgml/ref/analyze.sgml
+++ b/doc/src/sgml/ref/analyze.sgml
@@ -1,5 +1,5 @@
 <!--
-$Header: /cvsroot/pgsql/doc/src/sgml/ref/analyze.sgml,v 1.8 2002/04/23 02:07:15 tgl Exp $
+$Header: /cvsroot/pgsql/doc/src/sgml/ref/analyze.sgml,v 1.9 2002/07/31 17:19:51 tgl Exp $
 PostgreSQL documentation
 -->
 
@@ -157,7 +157,9 @@ ANALYZE [ VERBOSE ] [ <replaceable class="PARAMETER">table</replaceable> [ (<rep
   </para>
 
   <para>
-   The extent of analysis can be controlled by adjusting the per-column
+   The extent of analysis can be controlled by adjusting the
+   <literal>default_statistics_target</> parameter variable, or on a
+   column-by-column basis by setting the per-column
    statistics target with <command>ALTER TABLE ALTER COLUMN SET
    STATISTICS</command> (see
    <xref linkend="sql-altertable" endterm="sql-altertable-title">).  The
@@ -165,8 +167,8 @@ ANALYZE [ VERBOSE ] [ <replaceable class="PARAMETER">table</replaceable> [ (<rep
    list and the maximum number of bins in the histogram.  The default
    target value is 10, but this can be adjusted up or down to trade off
    accuracy of planner estimates against the time taken for
-   <command>ANALYZE</command> and the
-   amount of space occupied in <literal>pg_statistic</literal>.
+   <command>ANALYZE</command> and the amount of space occupied
+   in <literal>pg_statistic</literal>.
    In particular, setting the statistics target to zero disables collection of
    statistics for that column.  It may be useful to do that for columns that
    are never used as part of the WHERE, GROUP BY, or ORDER BY clauses of
diff --git a/doc/src/sgml/runtime.sgml b/doc/src/sgml/runtime.sgml
index 15f2e6e56af..8733725c2e3 100644
--- a/doc/src/sgml/runtime.sgml
+++ b/doc/src/sgml/runtime.sgml
@@ -1,5 +1,5 @@
 <!--
-$Header: /cvsroot/pgsql/doc/src/sgml/runtime.sgml,v 1.121 2002/07/13 01:02:14 momjian Exp $
+$Header: /cvsroot/pgsql/doc/src/sgml/runtime.sgml,v 1.122 2002/07/31 17:19:50 tgl Exp $
 -->
 
 <Chapter Id="runtime">
@@ -592,6 +592,19 @@ env PGOPTIONS='-c geqo=off' psql
       </listitem>
      </varlistentry>
     
+     <varlistentry>
+      <term><varname>DEFAULT_STATISTICS_TARGET</varname> (<type>integer</type>)</term>
+      <listitem>
+       <para>
+        Sets the default statistics target for table columns that have not
+	had a column-specific target set via <command>ALTER TABLE SET
+	STATISTICS</>.  Larger values increase the time needed to do
+	<command>ANALYZE</>, but may improve the quality of the planner's
+	estimates.
+       </para>
+      </listitem>
+     </varlistentry>
+    
      <varlistentry>
       <term><varname>EFFECTIVE_CACHE_SIZE</varname> (<type>floating point</type>)</term>
       <listitem>
diff --git a/src/backend/access/common/tupdesc.c b/src/backend/access/common/tupdesc.c
index 24f33fac4be..1eb62dea91a 100644
--- a/src/backend/access/common/tupdesc.c
+++ b/src/backend/access/common/tupdesc.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/access/common/tupdesc.c,v 1.81 2002/07/20 05:16:56 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/access/common/tupdesc.c,v 1.82 2002/07/31 17:19:51 tgl Exp $
  *
  * NOTES
  *	  some of the executor utility code such as "ExecTypeFromTL" should be
@@ -375,7 +375,7 @@ TupleDescInitEntry(TupleDesc desc,
 	else
 		MemSet(NameStr(att->attname), 0, NAMEDATALEN);
 
-	att->attstattarget = 0;
+	att->attstattarget = -1;
 	att->attcacheoff = -1;
 	att->atttypmod = typmod;
 
diff --git a/src/backend/catalog/genbki.sh b/src/backend/catalog/genbki.sh
index 94db1c65189..2fbb84494ca 100644
--- a/src/backend/catalog/genbki.sh
+++ b/src/backend/catalog/genbki.sh
@@ -10,7 +10,7 @@
 #
 #
 # IDENTIFICATION
-#    $Header: /cvsroot/pgsql/src/backend/catalog/Attic/genbki.sh,v 1.27 2002/04/27 21:24:33 tgl Exp $
+#    $Header: /cvsroot/pgsql/src/backend/catalog/Attic/genbki.sh,v 1.28 2002/07/31 17:19:51 tgl Exp $
 #
 # NOTES
 #    non-essential whitespace is removed from the generated file.
@@ -126,12 +126,11 @@ for dir in $INCLUDE_DIRS; do
     fi
 done
 
-# Get INDEX_MAX_KEYS and DEFAULT_ATTSTATTARGET from pg_config.h
+# Get INDEX_MAX_KEYS from pg_config.h
 # (who needs consistency?)
 for dir in $INCLUDE_DIRS; do
     if [ -f "$dir/pg_config.h" ]; then
         INDEXMAXKEYS=`grep '^#define[ 	]*INDEX_MAX_KEYS' $dir/pg_config.h | $AWK '{ print $3 }'`
-        DEFAULTATTSTATTARGET=`grep '^#define[ 	]*DEFAULT_ATTSTATTARGET' $dir/pg_config.h | $AWK '{ print $3 }'`
         break
     fi
 done
@@ -194,7 +193,6 @@ sed -e "s/;[ 	]*$//g" \
     -e "s/PGUID/1/g" \
     -e "s/NAMEDATALEN/$NAMEDATALEN/g" \
     -e "s/PGNSP/$PG_CATALOG_NAMESPACE/g" \
-    -e "s/DEFAULT_ATTSTATTARGET/$DEFAULTATTSTATTARGET/g" \
     -e "s/INDEX_MAX_KEYS\*2/$INDEXMAXKEYS2/g" \
     -e "s/INDEX_MAX_KEYS\*4/$INDEXMAXKEYS4/g" \
     -e "s/INDEX_MAX_KEYS/$INDEXMAXKEYS/g" \
diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c
index 07373663aeb..6045c17bb6a 100644
--- a/src/backend/catalog/heap.c
+++ b/src/backend/catalog/heap.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.213 2002/07/24 19:11:07 petere Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.214 2002/07/31 17:19:51 tgl Exp $
  *
  *
  * INTERFACE ROUTINES
@@ -441,7 +441,7 @@ AddNewAttributeTuples(Oid new_rel_oid,
 		/* Fill in the correct relation OID */
 		(*dpp)->attrelid = new_rel_oid;
 		/* Make sure these are OK, too */
-		(*dpp)->attstattarget = DEFAULT_ATTSTATTARGET;
+		(*dpp)->attstattarget = -1;
 		(*dpp)->attcacheoff = -1;
 
 		tup = heap_addheader(Natts_pg_attribute,
diff --git a/src/backend/commands/analyze.c b/src/backend/commands/analyze.c
index 6caa968b5d2..55069aa6feb 100644
--- a/src/backend/commands/analyze.c
+++ b/src/backend/commands/analyze.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/commands/analyze.c,v 1.38 2002/06/20 20:29:26 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/analyze.c,v 1.39 2002/07/31 17:19:51 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -107,6 +107,11 @@ typedef struct
 #define swapInt(a,b)	do {int _tmp; _tmp=a; a=b; b=_tmp;} while(0)
 #define swapDatum(a,b)	do {Datum _tmp; _tmp=a; a=b; b=_tmp;} while(0)
 
+
+/* Default statistics target (GUC parameter) */
+int		default_statistics_target = 10;
+
+
 static int elevel = -1;
 
 static MemoryContext anl_context = NULL;
@@ -384,7 +389,7 @@ examine_attribute(Relation onerel, int attnum)
 	VacAttrStats *stats;
 
 	/* Don't analyze column if user has specified not to */
-	if (attr->attstattarget <= 0)
+	if (attr->attstattarget == 0)
 		return NULL;
 
 	/* If column has no "=" operator, we can't do much of anything */
@@ -425,6 +430,10 @@ examine_attribute(Relation onerel, int attnum)
 	stats->eqopr = eqopr;
 	stats->eqfunc = eqfunc;
 
+	/* If the attstattarget column is negative, use the default value */
+	if (stats->attr->attstattarget < 0)
+		stats->attr->attstattarget = default_statistics_target;
+
 	/* Is there a "<" operator with suitable semantics? */
 	func_operator = compatible_oper(makeList1(makeString("<")),
 									attr->atttypid,
@@ -466,14 +475,14 @@ examine_attribute(Relation onerel, int attnum)
 		 * know it at this point.
 		 *--------------------
 		 */
-		stats->minrows = 300 * attr->attstattarget;
+		stats->minrows = 300 * stats->attr->attstattarget;
 	}
 	else
 	{
 		/* Can't do much but the minimal stuff */
 		stats->algcode = ALG_MINIMAL;
 		/* Might as well use the same minrows as above */
-		stats->minrows = 300 * attr->attstattarget;
+		stats->minrows = 300 * stats->attr->attstattarget;
 	}
 
 	return stats;
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 6b943723bb8..cfcf5d5ddfd 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v 1.24 2002/07/20 05:16:57 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v 1.25 2002/07/31 17:19:51 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1668,7 +1668,7 @@ AlterTableAddColumn(Oid myrelid,
 	attribute->attrelid = myrelid;
 	namestrcpy(&(attribute->attname), colDef->colname);
 	attribute->atttypid = HeapTupleGetOid(typeTuple);
-	attribute->attstattarget = DEFAULT_ATTSTATTARGET;
+	attribute->attstattarget = -1;
 	attribute->attlen = tform->typlen;
 	attribute->attcacheoff = -1;
 	attribute->atttypmod = colDef->typename->typmod;
@@ -2184,12 +2184,18 @@ AlterTableAlterColumnFlags(Oid myrelid,
 		newtarget = intVal(flagValue);
 
 		/*
-		 * Limit target to sane range (should we raise an error instead?)
+		 * Limit target to a sane range
 		 */
-		if (newtarget < 0)
-			newtarget = 0;
+		if (newtarget < -1)
+		{
+			elog(ERROR, "ALTER TABLE: statistics target %d is too low",
+				 newtarget);
+		}
 		else if (newtarget > 1000)
+		{
+			elog(WARNING, "ALTER TABLE: lowering statistics target to 1000");
 			newtarget = 1000;
+		}
 	}
 	else if (*flagType == 'M')
 	{
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index 685919a3ff5..73c2875d1b7 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.351 2002/07/30 16:55:44 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.352 2002/07/31 17:19:51 tgl Exp $
  *
  * HISTORY
  *	  AUTHOR			DATE			MAJOR EVENT
@@ -1134,14 +1134,14 @@ AlterTableStmt:
 					n->name = $6;
 					$$ = (Node *)n;
 				}
-			/* ALTER TABLE <relation> ALTER [COLUMN] <colname> SET STATISTICS <Iconst> */
-			| ALTER TABLE relation_expr ALTER opt_column ColId SET STATISTICS Iconst
+			/* ALTER TABLE <relation> ALTER [COLUMN] <colname> SET STATISTICS <IntegerOnly> */
+			| ALTER TABLE relation_expr ALTER opt_column ColId SET STATISTICS IntegerOnly
 				{
 					AlterTableStmt *n = makeNode(AlterTableStmt);
 					n->subtype = 'S';
 					n->relation = $3;
 					n->name = $6;
-					n->def = (Node *) makeInteger($9);
+					n->def = (Node *) $9;
 					$$ = (Node *)n;
 				}
 			/* ALTER TABLE <relation> ALTER [COLUMN] <colname> SET STORAGE <storagemode> */
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 4a03c95277b..dd22003bac7 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -5,7 +5,7 @@
  * command, configuration file, and command line options.
  * See src/backend/utils/misc/README for more information.
  *
- * $Header: /cvsroot/pgsql/src/backend/utils/misc/guc.c,v 1.76 2002/07/30 16:20:03 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/misc/guc.c,v 1.77 2002/07/31 17:19:52 tgl Exp $
  *
  * Copyright 2000 by PostgreSQL Global Development Group
  * Written by Peter Eisentraut <peter_e@gmx.net>.
@@ -26,6 +26,7 @@
 #include "catalog/pg_type.h"
 #include "commands/async.h"
 #include "commands/variable.h"
+#include "commands/vacuum.h"
 #include "executor/executor.h"
 #include "fmgr.h"
 #include "libpq/auth.h"
@@ -491,6 +492,10 @@ static struct config_bool
 static struct config_int
 			ConfigureNamesInt[] =
 {
+	{
+		{ "default_statistics_target", PGC_USERSET }, &default_statistics_target,
+		10, 1, 1000, NULL, NULL
+	},
 	{
 		{ "geqo_threshold", PGC_USERSET }, &geqo_rels,
 		DEFAULT_GEQO_RELS, 2, INT_MAX, NULL, NULL
diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample
index 1830ab166c0..be097186cac 100644
--- a/src/backend/utils/misc/postgresql.conf.sample
+++ b/src/backend/utils/misc/postgresql.conf.sample
@@ -95,6 +95,7 @@
 #cpu_index_tuple_cost = 0.001
 #cpu_operator_cost = 0.0025
 
+#default_statistics_target = 10	# range 1-1000
 
 #
 #	GEQO Optimizer Parameters
diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c
index 76623f61835..7ca027e0105 100644
--- a/src/bin/pg_dump/pg_dump.c
+++ b/src/bin/pg_dump/pg_dump.c
@@ -22,7 +22,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dump.c,v 1.277 2002/07/30 21:56:04 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dump.c,v 1.278 2002/07/31 17:19:52 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -2344,6 +2344,7 @@ getTableAttrs(TableInfo *tblinfo, int numTables)
 	int			i_attname;
 	int			i_atttypname;
 	int			i_atttypmod;
+	int			i_attstattarget;
 	int			i_attnotnull;
 	int			i_atthasdef;
 	PGresult   *res;
@@ -2384,7 +2385,7 @@ getTableAttrs(TableInfo *tblinfo, int numTables)
 
 		if (g_fout->remoteVersion >= 70300)
 		{
-			appendPQExpBuffer(q, "SELECT attnum, attname, atttypmod, "
+			appendPQExpBuffer(q, "SELECT attnum, attname, atttypmod, attstattarget, "
 							  "attnotnull, atthasdef, "
 							  "pg_catalog.format_type(atttypid,atttypmod) as atttypname "
 							  "from pg_catalog.pg_attribute a "
@@ -2395,7 +2396,12 @@ getTableAttrs(TableInfo *tblinfo, int numTables)
 		}
 		else if (g_fout->remoteVersion >= 70100)
 		{
-			appendPQExpBuffer(q, "SELECT attnum, attname, atttypmod, "
+			/*
+			 * attstattarget doesn't exist in 7.1.  It does exist in 7.2,
+			 * but we don't dump it because we can't tell whether it's been
+			 * explicitly set or was just a default.
+			 */
+			appendPQExpBuffer(q, "SELECT attnum, attname, atttypmod, -1 as attstattarget, "
 							  "attnotnull, atthasdef, "
 							  "format_type(atttypid,atttypmod) as atttypname "
 							  "from pg_attribute a "
@@ -2407,7 +2413,7 @@ getTableAttrs(TableInfo *tblinfo, int numTables)
 		else
 		{
 			/* format_type not available before 7.1 */
-			appendPQExpBuffer(q, "SELECT attnum, attname, atttypmod, "
+			appendPQExpBuffer(q, "SELECT attnum, attname, atttypmod, -1 as attstattarget, "
 							  "attnotnull, atthasdef, "
 							  "(select typname from pg_type where oid = atttypid) as atttypname "
 							  "from pg_attribute a "
@@ -2430,6 +2436,7 @@ getTableAttrs(TableInfo *tblinfo, int numTables)
 		i_attname = PQfnumber(res, "attname");
 		i_atttypname = PQfnumber(res, "atttypname");
 		i_atttypmod = PQfnumber(res, "atttypmod");
+		i_attstattarget = PQfnumber(res, "attstattarget");
 		i_attnotnull = PQfnumber(res, "attnotnull");
 		i_atthasdef = PQfnumber(res, "atthasdef");
 
@@ -2437,6 +2444,7 @@ getTableAttrs(TableInfo *tblinfo, int numTables)
 		tblinfo[i].attnames = (char **) malloc(ntups * sizeof(char *));
 		tblinfo[i].atttypnames = (char **) malloc(ntups * sizeof(char *));
 		tblinfo[i].atttypmod = (int *) malloc(ntups * sizeof(int));
+		tblinfo[i].attstattarget = (int *) malloc(ntups * sizeof(int));
 		tblinfo[i].notnull = (bool *) malloc(ntups * sizeof(bool));
 		tblinfo[i].adef_expr = (char **) malloc(ntups * sizeof(char *));
 		tblinfo[i].inhAttrs = (bool *) malloc(ntups * sizeof(bool));
@@ -2449,6 +2457,7 @@ getTableAttrs(TableInfo *tblinfo, int numTables)
 			tblinfo[i].attnames[j] = strdup(PQgetvalue(res, j, i_attname));
 			tblinfo[i].atttypnames[j] = strdup(PQgetvalue(res, j, i_atttypname));
 			tblinfo[i].atttypmod[j] = atoi(PQgetvalue(res, j, i_atttypmod));
+			tblinfo[i].attstattarget[j] = atoi(PQgetvalue(res, j, i_attstattarget));
 			tblinfo[i].notnull[j] = (PQgetvalue(res, j, i_attnotnull)[0] == 't');
 			tblinfo[i].adef_expr[j] = NULL;	/* fix below */
 			if (PQgetvalue(res, j, i_atthasdef)[0] == 't')
@@ -5144,6 +5153,24 @@ dumpOneTable(Archive *fout, TableInfo *tbinfo, TableInfo *g_tblinfo)
 			appendPQExpBuffer(q, " WITHOUT OIDS");
 
 		appendPQExpBuffer(q, ";\n");
+
+		/*
+		 * Dump per-column statistics information. We only issue an ALTER TABLE
+		 * statement if the attstattarget entry for this column is non-negative
+		 * (i.e. it's not the default value)
+		 */
+		for (j = 0; j  < tbinfo->numatts; j++)
+		{
+			if (tbinfo->attstattarget[j] >= 0)
+			{
+				appendPQExpBuffer(q, "ALTER TABLE %s ",
+								  fmtId(tbinfo->relname, force_quotes));
+				appendPQExpBuffer(q, "ALTER COLUMN %s ",
+								  fmtId(tbinfo->attnames[j], force_quotes));
+				appendPQExpBuffer(q, "SET STATISTICS %d;\n",
+								  tbinfo->attstattarget[j]);
+			}
+		}
 	}
 
 	ArchiveEntry(fout, objoid, tbinfo->relname,
diff --git a/src/bin/pg_dump/pg_dump.h b/src/bin/pg_dump/pg_dump.h
index b3b943dde08..6a6322c9ca2 100644
--- a/src/bin/pg_dump/pg_dump.h
+++ b/src/bin/pg_dump/pg_dump.h
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: pg_dump.h,v 1.92 2002/07/30 21:56:04 tgl Exp $
+ * $Id: pg_dump.h,v 1.93 2002/07/31 17:19:53 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -122,6 +122,7 @@ typedef struct _tableInfo
 	char	  **attnames;		/* the attribute names */
 	char	  **atttypnames;	/* attribute type names */
 	int		   *atttypmod;		/* type-specific type modifiers */
+	int		   *attstattarget;	/* attribute statistics targets */
 	/*
 	 * Note: we need to store per-attribute notnull and default stuff for
 	 * all interesting tables so that we can tell which constraints were
diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c
index 8e37306f380..f60ccae324a 100644
--- a/src/bin/psql/tab-complete.c
+++ b/src/bin/psql/tab-complete.c
@@ -3,7 +3,7 @@
  *
  * Copyright 2000 by PostgreSQL Global Development Group
  *
- * $Header: /cvsroot/pgsql/src/bin/psql/tab-complete.c,v 1.52 2002/07/30 16:35:05 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/bin/psql/tab-complete.c,v 1.53 2002/07/31 17:19:53 tgl Exp $
  */
 
 /*----------------------------------------------------------------------
@@ -246,6 +246,7 @@ psql_completion(char *text, int start, int end)
 		"password_encryption",
 		"transform_null_equals",
 
+		"default_statistics_target",
 		"geqo_threshold",
 		"geqo_pool_size",
 		"geqo_effort",
diff --git a/src/include/catalog/pg_attribute.h b/src/include/catalog/pg_attribute.h
index 462df4cc17e..15945192a00 100644
--- a/src/include/catalog/pg_attribute.h
+++ b/src/include/catalog/pg_attribute.h
@@ -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_attribute.h,v 1.94 2002/07/24 19:11:12 petere Exp $
+ * $Id: pg_attribute.h,v 1.95 2002/07/31 17:19:54 tgl Exp $
  *
  * NOTES
  *	  the genbki.sh script reads this file and generates .bki
@@ -58,7 +58,8 @@ CATALOG(pg_attribute) BOOTSTRAP BKI_WITHOUT_OIDS
 	 * attstattarget is the target number of statistics datapoints to
 	 * collect during VACUUM ANALYZE of this column.  A zero here
 	 * indicates that we do not wish to collect any stats about this
-	 * column.
+	 * column. A "-1" here indicates that no value has been explicitly
+	 * set for this column, so ANALYZE should use the default setting.
 	 */
 	int4		attstattarget;
 
@@ -210,7 +211,7 @@ typedef FormData_pg_attribute *Form_pg_attribute;
  * ----------------
  */
 #define Schema_pg_type \
-{ 1247, {"typname"},	   19, DEFAULT_ATTSTATTARGET, NAMEDATALEN,	1, 0, -1, -1, false, 'p', false, 'i', false, false }, \
+{ 1247, {"typname"},	   19, -1, NAMEDATALEN,	1, 0, -1, -1, false, 'p', false, 'i', false, false }, \
 { 1247, {"typnamespace"},  26, 0,	4,	2, 0, -1, -1, true, 'p', false, 'i', false, false }, \
 { 1247, {"typowner"},	   23, 0,	4,	3, 0, -1, -1, true, 'p', false, 'i', false, false }, \
 { 1247, {"typlen"},		   21, 0,	2,	4, 0, -1, -1, true, 'p', false, 's', false, false }, \
@@ -232,7 +233,7 @@ typedef FormData_pg_attribute *Form_pg_attribute;
 { 1247, {"typdefault"},    25, 0,  -1, 20, 0, -1, -1, false, 'x', false, 'i', false, false }
 
 
-DATA(insert ( 1247 typname			19 DEFAULT_ATTSTATTARGET NAMEDATALEN   1 0 -1 -1 f p f i f f));
+DATA(insert ( 1247 typname			19 -1 NAMEDATALEN   1 0 -1 -1 f p f i f f));
 DATA(insert ( 1247 typnamespace		26 0  4   2 0 -1 -1 t p f i f f));
 DATA(insert ( 1247 typowner			23 0  4   3 0 -1 -1 t p f i f f));
 DATA(insert ( 1247 typlen			21 0  2   4 0 -1 -1 t p f s f f));
@@ -289,7 +290,7 @@ DATA(insert ( 1262 tableoid			26 0  4  -7 0 -1 -1 t p f i f f));
  * ----------------
  */
 #define Schema_pg_proc \
-{ 1255, {"proname"},			19, DEFAULT_ATTSTATTARGET, NAMEDATALEN,  1, 0, -1, -1, false, 'p', false, 'i', false, false }, \
+{ 1255, {"proname"},			19, -1, NAMEDATALEN,  1, 0, -1, -1, false, 'p', false, 'i', false, false }, \
 { 1255, {"pronamespace"},		26, 0,	4,	2, 0, -1, -1, true, 'p', false, 'i', false, false }, \
 { 1255, {"proowner"},			23, 0,	4,	3, 0, -1, -1, true, 'p', false, 'i', false, false }, \
 { 1255, {"prolang"},			26, 0,	4,	4, 0, -1, -1, true, 'p', false, 'i', false, false }, \
@@ -305,7 +306,7 @@ DATA(insert ( 1262 tableoid			26 0  4  -7 0 -1 -1 t p f i f f));
 { 1255, {"probin"},				17, 0, -1, 14, 0, -1, -1, false, 'x', false, 'i', false, false }, \
 { 1255, {"proacl"},			  1034, 0, -1, 15, 0, -1, -1, false, 'x', false, 'i', false, false }
 
-DATA(insert ( 1255 proname			19 DEFAULT_ATTSTATTARGET NAMEDATALEN   1 0 -1 -1 f p f i f f));
+DATA(insert ( 1255 proname			19 -1 NAMEDATALEN   1 0 -1 -1 f p f i f f));
 DATA(insert ( 1255 pronamespace		26 0  4   2 0 -1 -1 t p f i f f));
 DATA(insert ( 1255 proowner			23 0  4   3 0 -1 -1 t p f i f f));
 DATA(insert ( 1255 prolang			26 0  4   4 0 -1 -1 t p f i f f));
@@ -332,8 +333,8 @@ DATA(insert ( 1255 tableoid			26 0  4  -7 0 -1 -1 t p f i f f));
  *		pg_shadow
  * ----------------
  */
-DATA(insert ( 1260 usename			19	DEFAULT_ATTSTATTARGET NAMEDATALEN	1 0 -1 -1 f p f i f f));
-DATA(insert ( 1260 usesysid			23	DEFAULT_ATTSTATTARGET	4	2 0 -1 -1 t p f i f f));
+DATA(insert ( 1260 usename			19	-1 NAMEDATALEN	1 0 -1 -1 f p f i f f));
+DATA(insert ( 1260 usesysid			23	-1	4	2 0 -1 -1 t p f i f f));
 DATA(insert ( 1260 usecreatedb		16	0	1	3 0 -1 -1 t p f c f f));
 DATA(insert ( 1260 usesuper			16	0	1	4 0 -1 -1 t p f c f f));
 DATA(insert ( 1260 usecatupd		16	0	1	5 0 -1 -1 t p f c f f));
@@ -352,8 +353,8 @@ DATA(insert ( 1260 tableoid			26 0  4  -7 0 -1 -1 t p f i f f));
  *		pg_group
  * ----------------
  */
-DATA(insert ( 1261 groname			19 DEFAULT_ATTSTATTARGET NAMEDATALEN  1 0 -1 -1 f p f i f f));
-DATA(insert ( 1261 grosysid			23 DEFAULT_ATTSTATTARGET  4   2 0 -1 -1 t p f i f f));
+DATA(insert ( 1261 groname			19 -1 NAMEDATALEN  1 0 -1 -1 f p f i f f));
+DATA(insert ( 1261 grosysid			23 -1  4   2 0 -1 -1 t p f i f f));
 DATA(insert ( 1261 grolist		  1007 0 -1   3 0 -1 -1 f x f i f f));
 DATA(insert ( 1261 ctid				27 0  6  -1 0 -1 -1 f p f i f f));
 /* no OIDs in pg_group */
@@ -368,8 +369,8 @@ DATA(insert ( 1261 tableoid			26 0  4  -7 0 -1 -1 t p f i f f));
  * ----------------
  */
 #define Schema_pg_attribute \
-{ 1249, {"attrelid"},	  26, DEFAULT_ATTSTATTARGET,	4,	1, 0, -1, -1, true, 'p', false, 'i', false, false }, \
-{ 1249, {"attname"},	  19, DEFAULT_ATTSTATTARGET, NAMEDATALEN,	2, 0, -1, -1, false, 'p', false, 'i', false, false }, \
+{ 1249, {"attrelid"},	  26, -1,	4,	1, 0, -1, -1, true, 'p', false, 'i', false, false }, \
+{ 1249, {"attname"},	  19, -1, NAMEDATALEN,	2, 0, -1, -1, false, 'p', false, 'i', false, false }, \
 { 1249, {"atttypid"},	  26, 0,	4,	3, 0, -1, -1, true, 'p', false, 'i', false, false }, \
 { 1249, {"attstattarget"}, 23, 0,	4,	4, 0, -1, -1, true, 'p', false, 'i', false, false }, \
 { 1249, {"attlen"},		  21, 0,	2,	5, 0, -1, -1, true, 'p', false, 's', false, false }, \
@@ -384,8 +385,8 @@ DATA(insert ( 1261 tableoid			26 0  4  -7 0 -1 -1 t p f i f f));
 { 1249, {"attnotnull"},  16, 0, 1, 14, 0, -1, -1, true, 'p', false, 'c', false, false }, \
 { 1249, {"atthasdef"},	 16, 0, 1, 15, 0, -1, -1, true, 'p', false, 'c', false, false }
 
-DATA(insert ( 1249 attrelid			26 DEFAULT_ATTSTATTARGET  4   1 0 -1 -1 t p f i f f));
-DATA(insert ( 1249 attname			19 DEFAULT_ATTSTATTARGET NAMEDATALEN  2 0 -1 -1 f p f i f f));
+DATA(insert ( 1249 attrelid			26 -1  4   1 0 -1 -1 t p f i f f));
+DATA(insert ( 1249 attname			19 -1 NAMEDATALEN  2 0 -1 -1 f p f i f f));
 DATA(insert ( 1249 atttypid			26 0  4   3 0 -1 -1 t p f i f f));
 DATA(insert ( 1249 attstattarget	23 0  4   4 0 -1 -1 t p f i f f));
 DATA(insert ( 1249 attlen			21 0  2   5 0 -1 -1 t p f s f f));
@@ -412,7 +413,7 @@ DATA(insert ( 1249 tableoid			26 0  4  -7 0 -1 -1 t p f i f f));
  * ----------------
  */
 #define Schema_pg_class \
-{ 1259, {"relname"},	   19, DEFAULT_ATTSTATTARGET, NAMEDATALEN,	1, 0, -1, -1, false, 'p', false, 'i', false, false }, \
+{ 1259, {"relname"},	   19, -1, NAMEDATALEN,	1, 0, -1, -1, false, 'p', false, 'i', false, false }, \
 { 1259, {"relnamespace"},  26, 0,	4,	2, 0, -1, -1, true, 'p', false, 'i', false, false }, \
 { 1259, {"reltype"},	   26, 0,	4,	3, 0, -1, -1, true, 'p', false, 'i', false, false }, \
 { 1259, {"relowner"},	   23, 0,	4,	4, 0, -1, -1, true, 'p', false, 'i', false, false }, \
@@ -437,7 +438,7 @@ DATA(insert ( 1249 tableoid			26 0  4  -7 0 -1 -1 t p f i f f));
 { 1259, {"relhassubclass"},16, 0,	1, 23, 0, -1, -1, true, 'p', false, 'c', false, false }, \
 { 1259, {"relacl"},		 1034, 0,  -1, 24, 0, -1, -1, false, 'x', false, 'i', false, false }
 
-DATA(insert ( 1259 relname			19 DEFAULT_ATTSTATTARGET NAMEDATALEN   1 0 -1 -1 f p f i f f));
+DATA(insert ( 1259 relname			19 -1 NAMEDATALEN   1 0 -1 -1 f p f i f f));
 DATA(insert ( 1259 relnamespace		26 0  4   2 0 -1 -1 t p f i f f));
 DATA(insert ( 1259 reltype			26 0  4   3 0 -1 -1 t p f i f f));
 DATA(insert ( 1259 relowner			23 0  4   4 0 -1 -1 t p f i f f));
diff --git a/src/include/commands/vacuum.h b/src/include/commands/vacuum.h
index 42986f4ed4d..9d6565659b8 100644
--- a/src/include/commands/vacuum.h
+++ b/src/include/commands/vacuum.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: vacuum.h,v 1.44 2002/06/20 20:29:49 momjian Exp $
+ * $Id: vacuum.h,v 1.45 2002/07/31 17:19:54 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -34,6 +34,9 @@ typedef struct VacRUsage
 	struct rusage ru;
 } VacRUsage;
 
+/* Default statistics target (GUC parameter) */
+extern int	default_statistics_target;
+
 
 /* in commands/vacuum.c */
 extern void vacuum(VacuumStmt *vacstmt);
diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in
index 7a616440cf4..01d5465ad84 100644
--- a/src/include/pg_config.h.in
+++ b/src/include/pg_config.h.in
@@ -8,7 +8,7 @@
  * or in pg_config.h afterwards.  Of course, if you edit pg_config.h, then your
  * changes will be overwritten the next time you run configure.
  *
- * $Id: pg_config.h.in,v 1.25 2002/07/20 05:16:59 momjian Exp $
+ * $Id: pg_config.h.in,v 1.26 2002/07/31 17:19:54 tgl Exp $
  */
 
 #ifndef PG_CONFIG_H
@@ -165,11 +165,6 @@
 #define INDEX_MAX_KEYS		16
 #define FUNC_MAX_ARGS		INDEX_MAX_KEYS
 
-/*
- * System default value for pg_attribute.attstattarget
- */
-#define DEFAULT_ATTSTATTARGET	10
-
 /*
  * Define this to make libpgtcl's "pg_result -assign" command process C-style
  * backslash sequences in returned tuple data and convert Postgres array
-- 
GitLab