Here's a patch implementing this idea.  From gram.y's comment, the
support syntax is now:

  /*****************************************************************************
   *
   *        QUERY :
!  *                CREATE STATISTICS stats_name [(stat types)] arguments
! 
!  *            where 'arguments' can be one or more of:
!  *                    { ON (columns)
!  *                      | FROM relations
!  *                      | WITH (options)
!  *                      | WHERE expression }

Note that I removed the USING keyword in the stat types list, and also
made it mandatory that that list appears immediately after the new stats
name.  This should make it possible to have USING in the relation list
(the FROM clause), if we allow explicit multiple relations with join
syntax there.  The other options can appear in any order.

Also, both WITH and WHERE are accepted by the grammar, but immediately
throw "feature not implemented" error at parse time.

I was on the fence about adding copy/equal/out support for the new
StatisticArgument node; it seems pointless because that node does not
leave gram.y anyway.

Unless there are objections, I'll push this tomorrow.

-- 
Álvaro Herrera                https://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services
*** a/doc/src/sgml/perform.sgml
--- b/doc/src/sgml/perform.sgml
***************
*** 1132,1138 **** WHERE tablename = 'road';
       To inspect functional dependencies on a statistics
       <literal>stts</literal>, you may do this:
  <programlisting>
! CREATE STATISTICS stts WITH (dependencies)
                 ON (zip, city) FROM zipcodes;
  ANALYZE zipcodes;
  SELECT stxname, stxkeys, stxdependencies
--- 1132,1138 ----
       To inspect functional dependencies on a statistics
       <literal>stts</literal>, you may do this:
  <programlisting>
! CREATE STATISTICS stts (dependencies)
                 ON (zip, city) FROM zipcodes;
  ANALYZE zipcodes;
  SELECT stxname, stxkeys, stxdependencies
***************
*** 1219,1225 **** EXPLAIN (ANALYZE, TIMING OFF) SELECT * FROM t WHERE a = 1 
AND b = 10;
       Continuing the above example, the n-distinct coefficients in a ZIP
       code table may look like the following:
  <programlisting>
! CREATE STATISTICS stts2 WITH (ndistinct)
                 ON (zip, state, city) FROM zipcodes;
  ANALYZE zipcodes;
  SELECT stxkeys AS k, stxndistinct AS nd
--- 1219,1225 ----
       Continuing the above example, the n-distinct coefficients in a ZIP
       code table may look like the following:
  <programlisting>
! CREATE STATISTICS stts2 (ndistinct)
                 ON (zip, state, city) FROM zipcodes;
  ANALYZE zipcodes;
  SELECT stxkeys AS k, stxndistinct AS nd
*** a/doc/src/sgml/planstats.sgml
--- b/doc/src/sgml/planstats.sgml
***************
*** 526,532 **** EXPLAIN (ANALYZE, TIMING OFF) SELECT * FROM t WHERE a = 1 AND 
b = 1;
      multivariate statistics on the two columns:
  
  <programlisting>
! CREATE STATISTICS stts WITH (dependencies) ON (a, b) FROM t;
  ANALYZE t;
  EXPLAIN (ANALYZE, TIMING OFF) SELECT * FROM t WHERE a = 1 AND b = 1;
                                    QUERY PLAN                                  
 
--- 526,532 ----
      multivariate statistics on the two columns:
  
  <programlisting>
! CREATE STATISTICS stts (dependencies) ON (a, b) FROM t;
  ANALYZE t;
  EXPLAIN (ANALYZE, TIMING OFF) SELECT * FROM t WHERE a = 1 AND b = 1;
                                    QUERY PLAN                                  
 
***************
*** 569,575 **** EXPLAIN (ANALYZE, TIMING OFF) SELECT COUNT(*) FROM t GROUP BY 
a, b;
      calculation, the estimate is much improved:
  <programlisting>
  DROP STATISTICS stts;
! CREATE STATISTICS stts WITH (dependencies, ndistinct) ON (a, b) FROM t;
  ANALYZE t;
  EXPLAIN (ANALYZE, TIMING OFF) SELECT COUNT(*) FROM t GROUP BY a, b;
                                         QUERY PLAN                             
           
--- 569,575 ----
      calculation, the estimate is much improved:
  <programlisting>
  DROP STATISTICS stts;
! CREATE STATISTICS stts (dependencies, ndistinct) ON (a, b) FROM t;
  ANALYZE t;
  EXPLAIN (ANALYZE, TIMING OFF) SELECT COUNT(*) FROM t GROUP BY a, b;
                                         QUERY PLAN                             
           
*** a/doc/src/sgml/ref/create_statistics.sgml
--- b/doc/src/sgml/ref/create_statistics.sgml
***************
*** 22,28 **** PostgreSQL documentation
   <refsynopsisdiv>
  <synopsis>
  CREATE STATISTICS [ IF NOT EXISTS ] <replaceable 
class="PARAMETER">statistics_name</replaceable>
!     WITH ( <replaceable class="PARAMETER">option</replaceable> [= 
<replaceable class="PARAMETER">value</replaceable>] [, ... ] )
      ON ( <replaceable class="PARAMETER">column_name</replaceable>, 
<replaceable class="PARAMETER">column_name</replaceable> [, ...])
      FROM <replaceable class="PARAMETER">table_name</replaceable>
  </synopsis>
--- 22,28 ----
   <refsynopsisdiv>
  <synopsis>
  CREATE STATISTICS [ IF NOT EXISTS ] <replaceable 
class="PARAMETER">statistics_name</replaceable>
!     [ ( <replaceable class="PARAMETER">statistic_type</replaceable> [, ... ] 
) ]
      ON ( <replaceable class="PARAMETER">column_name</replaceable>, 
<replaceable class="PARAMETER">column_name</replaceable> [, ...])
      FROM <replaceable class="PARAMETER">table_name</replaceable>
  </synopsis>
***************
*** 75,80 **** CREATE STATISTICS [ IF NOT EXISTS ] <replaceable 
class="PARAMETER">statistics_na
--- 75,93 ----
     </varlistentry>
  
     <varlistentry>
+     <term><replaceable class="PARAMETER">statistic_type</replaceable></term>
+     <listitem>
+      <para>
+       A statistic type to be enabled for this statistics.  Currently
+       supported types are <literal>ndistinct</literal>, which enables
+       n-distinct coefficient tracking,
+       and <literal>dependencies</literal>, which enables functional
+       dependencies.
+      </para>
+     </listitem>
+    </varlistentry>
+ 
+    <varlistentry>
      <term><replaceable class="PARAMETER">column_name</replaceable></term>
      <listitem>
       <para>
***************
*** 94,135 **** CREATE STATISTICS [ IF NOT EXISTS ] <replaceable 
class="PARAMETER">statistics_na
     </varlistentry>
  
    </variablelist>
- 
-   <refsect2 id="SQL-CREATESTATISTICS-parameters">
-    <title id="SQL-CREATESTATISTICS-parameters-title">Parameters</title>
- 
-  <indexterm zone="sql-createstatistics-parameters">
-   <primary>statistics parameters</primary>
-  </indexterm>
- 
-    <para>
-     The <literal>WITH</> clause can specify <firstterm>options</>
-     for the statistics. Available options are listed below.
-    </para>
- 
-    <variablelist>
- 
-    <varlistentry>
-     <term><literal>dependencies</> (<type>boolean</>)</term>
-     <listitem>
-      <para>
-       Enables functional dependencies for the statistics.
-      </para>
-     </listitem>
-    </varlistentry>
- 
-    <varlistentry>
-     <term><literal>ndistinct</> (<type>boolean</>)</term>
-     <listitem>
-      <para>
-       Enables ndistinct coefficients for the statistics.
-      </para>
-     </listitem>
-    </varlistentry>
- 
-    </variablelist>
- 
-   </refsect2>
   </refsect1>
  
   <refsect1>
--- 107,112 ----
*** a/src/backend/commands/statscmds.c
--- b/src/backend/commands/statscmds.c
***************
*** 199,223 **** CreateStatistics(CreateStatsStmt *stmt)
         */
        build_ndistinct = false;
        build_dependencies = false;
!       foreach(l, stmt->options)
        {
!               DefElem    *opt = (DefElem *) lfirst(l);
  
!               if (strcmp(opt->defname, "ndistinct") == 0)
                {
!                       build_ndistinct = defGetBoolean(opt);
                        requested_type = true;
                }
!               else if (strcmp(opt->defname, "dependencies") == 0)
                {
!                       build_dependencies = defGetBoolean(opt);
                        requested_type = true;
                }
                else
                        ereport(ERROR,
                                        (errcode(ERRCODE_SYNTAX_ERROR),
!                                        errmsg("unrecognized STATISTICS option 
\"%s\"",
!                                                       opt->defname)));
        }
        /* If no statistic type was specified, build them all. */
        if (!requested_type)
--- 199,223 ----
         */
        build_ndistinct = false;
        build_dependencies = false;
!       foreach(l, stmt->stat_types)
        {
!               char    *type = strVal((Value *) lfirst(l));
  
!               if (strcmp(type, "ndistinct") == 0)
                {
!                       build_ndistinct = true;
                        requested_type = true;
                }
!               else if (strcmp(type, "dependencies") == 0)
                {
!                       build_dependencies = true;
                        requested_type = true;
                }
                else
                        ereport(ERROR,
                                        (errcode(ERRCODE_SYNTAX_ERROR),
!                                        errmsg("unrecognized statistics type 
\"%s\"",
!                                                       type)));
        }
        /* If no statistic type was specified, build them all. */
        if (!requested_type)
*** a/src/backend/nodes/copyfuncs.c
--- b/src/backend/nodes/copyfuncs.c
***************
*** 3397,3402 **** _copyCreateStatsStmt(const CreateStatsStmt *from)
--- 3397,3413 ----
        return newnode;
  }
  
+ static CreateStatsArgument *
+ _copyCreateStatsArgument(const CreateStatsArgument *from)
+ {
+       CreateStatsArgument *newnode = makeNode(CreateStatsArgument);
+ 
+       COPY_SCALAR_FIELD(subtype);
+       COPY_NODE_FIELD(elements);
+ 
+       return newnode;
+ }
+ 
  static CreateFunctionStmt *
  _copyCreateFunctionStmt(const CreateFunctionStmt *from)
  {
***************
*** 5121,5126 **** copyObjectImpl(const void *from)
--- 5132,5140 ----
                case T_CreateStatsStmt:
                        retval = _copyCreateStatsStmt(from);
                        break;
+               case T_CreateStatsArgument:
+                       retval = _copyCreateStatsArgument(from);
+                       break;
                case T_CreateFunctionStmt:
                        retval = _copyCreateFunctionStmt(from);
                        break;
*** a/src/backend/nodes/equalfuncs.c
--- b/src/backend/nodes/equalfuncs.c
***************
*** 1358,1363 **** _equalCreateStatsStmt(const CreateStatsStmt *a, const 
CreateStatsStmt *b)
--- 1358,1372 ----
  }
  
  static bool
+ _equalCreateStatsArgument(const CreateStatsArgument *a, const 
CreateStatsArgument *b)
+ {
+       COMPARE_SCALAR_FIELD(subtype);
+       COMPARE_NODE_FIELD(elements);
+ 
+       return true;
+ }
+ 
+ static bool
  _equalCreateFunctionStmt(const CreateFunctionStmt *a, const 
CreateFunctionStmt *b)
  {
        COMPARE_SCALAR_FIELD(replace);
***************
*** 3270,3275 **** equal(const void *a, const void *b)
--- 3279,3287 ----
                case T_CreateStatsStmt:
                        retval = _equalCreateStatsStmt(a, b);
                        break;
+               case T_CreateStatsArgument:
+                       retval = _equalCreateStatsArgument(a, b);
+                       break;
                case T_CreateFunctionStmt:
                        retval = _equalCreateFunctionStmt(a, b);
                        break;
*** a/src/backend/nodes/outfuncs.c
--- b/src/backend/nodes/outfuncs.c
***************
*** 2646,2651 **** _outCreateStatsStmt(StringInfo str, const CreateStatsStmt 
*node)
--- 2646,2660 ----
  }
  
  static void
+ _outCreateStatsArgument(StringInfo str, const CreateStatsArgument *node)
+ {
+       WRITE_NODE_TYPE("CREATESTATSARG");
+ 
+       WRITE_INT_FIELD(subtype);
+       WRITE_NODE_FIELD(elements);
+ }
+ 
+ static void
  _outNotifyStmt(StringInfo str, const NotifyStmt *node)
  {
        WRITE_NODE_TYPE("NOTIFY");
***************
*** 4051,4056 **** outNode(StringInfo str, const void *obj)
--- 4060,4068 ----
                        case T_CreateStatsStmt:
                                _outCreateStatsStmt(str, obj);
                                break;
+                       case T_CreateStatsArgument:
+                               _outCreateStatsArgument(str, obj);
+                               break;
                        case T_NotifyStmt:
                                _outNotifyStmt(str, obj);
                                break;
*** a/src/backend/parser/gram.y
--- b/src/backend/parser/gram.y
***************
*** 183,188 **** static RangeVar *makeRangeVarFromAnyName(List *names, int 
position, core_yyscan_
--- 183,189 ----
  static void SplitColQualList(List *qualList,
                                                         List **constraintList, 
CollateClause **collClause,
                                                         core_yyscan_t 
yyscanner);
+ static void SplitStatsArgList(CreateStatsStmt *stmt, List *arguments);
  static void processCASbits(int cas_bits, int location, const char *constrType,
                           bool *deferrable, bool *initdeferred, bool 
*not_valid,
                           bool *no_inherit, core_yyscan_t yyscanner);
***************
*** 236,241 **** static Node *makeRecursiveViewSelect(char *relname, List 
*aliases, Node *query);
--- 237,243 ----
        AccessPriv                      *accesspriv;
        struct ImportQual       *importqual;
        InsertStmt                      *istmt;
+       CreateStatsArgument *cstatarg;
        VariableSetStmt         *vsetstmt;
        PartitionElem           *partelem;
        PartitionSpec           *partspec;
***************
*** 397,402 **** static Node *makeRecursiveViewSelect(char *relname, List 
*aliases, Node *query);
--- 399,406 ----
                                transform_element_list transform_type_list
                                TriggerTransitions TriggerReferencing
                                publication_name_list
+                               opt_stats_type_list stats_type_list 
StatisticArgList
+ %type <cstatarg> StatisticArgument
  
  %type <list>  group_by_list
  %type <node>  group_by_item empty_grouping_set rollup_clause cube_clause
***************
*** 3828,3860 **** ExistingIndex:   USING INDEX index_name                      
        { $$ = $3; }
  /*****************************************************************************
   *
   *            QUERY :
!  *                            CREATE STATISTICS stats_name WITH (options) ON 
(columns) FROM relname
   *
   
*****************************************************************************/
  
  
! CreateStatsStmt:      CREATE STATISTICS any_name opt_reloptions ON '(' 
columnList ')' FROM qualified_name
!                                               {
!                                                       CreateStatsStmt *n = 
makeNode(CreateStatsStmt);
!                                                       n->defnames = $3;
!                                                       n->relation = $10;
!                                                       n->keys = $7;
!                                                       n->options = $4;
!                                                       n->if_not_exists = 
false;
!                                                       $$ = (Node *)n;
!                                               }
!                                       | CREATE STATISTICS IF_P NOT EXISTS 
any_name opt_reloptions ON '(' columnList ')' FROM qualified_name
!                                               {
!                                                       CreateStatsStmt *n = 
makeNode(CreateStatsStmt);
!                                                       n->defnames = $6;
!                                                       n->relation = $13;
!                                                       n->keys = $10;
!                                                       n->options = $7;
!                                                       n->if_not_exists = true;
!                                                       $$ = (Node *)n;
!                                               }
                        ;
  
  /*****************************************************************************
   *
   *            QUERY :
--- 3832,3905 ----
  /*****************************************************************************
   *
   *            QUERY :
!  *                            CREATE STATISTICS stats_name [(stat types)] 
arguments
! 
!  *                    where 'arguments' can be one or more of:
!  *                                    { ON (columns)
!  *                                      | FROM relations
!  *                                      | WITH (options)
!  *                                      | WHERE expression }
   *
   
*****************************************************************************/
  
+ CreateStatsStmt:
+                       CREATE opt_if_not_exists STATISTICS any_name
+                       opt_stats_type_list StatisticArgList
+                               {
+                                       CreateStatsStmt *n = 
makeNode(CreateStatsStmt);
+                                       n->defnames = $4;
+                                       n->stat_types = $5;
+                                       n->if_not_exists = $2;
  
!                                       SplitStatsArgList(n, $6);
!                                       $$ = (Node *)n;
!                               }
                        ;
  
+ opt_stats_type_list:
+                       '(' stats_type_list ')'                 { $$ = $2; }
+                       | /* EMPTY */                                   { $$ = 
NULL; }
+               ;
+ 
+ stats_type_list:
+                       ColId                                                   
{ $$ = list_make1(makeString($1)); }
+                       | stats_type_list ',' ColId             { $$ = 
lappend($1, makeString($3)); }
+               ;
+ 
+ StatisticArgList:
+                       StatisticArgument                                       
        { $$ = list_make1($1); }
+                       | StatisticArgList StatisticArgument    { $$ = 
lappend($1, $2); }
+               ;
+ 
+ StatisticArgument:
+                       ON '(' name_list ')'
+                               {
+                                       CreateStatsArgument *n = 
makeNode(CreateStatsArgument);
+                                       n->subtype = CSA_Expressions;
+                                       n->elements = $3;
+                                       $$ = n;
+                               }
+                       | FROM qualified_name_list
+                               {
+                                       CreateStatsArgument *n = 
makeNode(CreateStatsArgument);
+                                       n->subtype = CSA_Relations;
+                                       n->elements = $2;
+                                       $$ = n;
+                               }
+                       | WITH reloptions
+                               {
+                                       ereport(ERROR,
+                                                       
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+                                                        errmsg("WITH clause is 
not yet implemented")));
+                               }
+                       | WHERE a_expr
+                               {
+                                       ereport(ERROR,
+                                                       
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+                                                        errmsg("WHERE clause 
is not yet implemented")));
+                               }
+               ;
+ 
  /*****************************************************************************
   *
   *            QUERY :
***************
*** 15872,15877 **** processCASbits(int cas_bits, int location, const char 
*constrType,
--- 15917,15969 ----
        }
  }
  
+ /*
+  * Split out CREATE STATISTICS arguments.
+  */
+ static void
+ SplitStatsArgList(CreateStatsStmt *stmt, List *arguments)
+ {
+       ListCell   *cell;
+ 
+       foreach(cell, arguments)
+       {
+               CreateStatsArgument *n = lfirst_node(CreateStatsArgument, cell);
+ 
+               switch (n->subtype)
+               {
+                       case CSA_Relations:
+                               if (stmt->relation)
+                                       ereport(ERROR,
+                                               
(errcode(ERRCODE_DUPLICATE_OBJECT),
+                                                errmsg("redundant or 
conflicting FROM clauses")));
+                               if (list_length(n->elements) > 1)
+                                       ereport(ERROR,
+                                                       
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+                                                        errmsg("statistics 
across multiple relations are not supported yet")));
+                               stmt->relation = linitial_node(RangeVar, 
n->elements);
+                               break;
+                       case CSA_Expressions:
+                               if (stmt->keys)
+                                       ereport(ERROR,
+                                                       
(errcode(ERRCODE_DUPLICATE_OBJECT),
+                                                        errmsg("redundant or 
conflicting ON clauses")));
+                               stmt->keys = n->elements;
+                               break;
+                       default:
+                               elog(ERROR, "unsupported node type %d", 
n->subtype);
+               }
+       }
+ 
+       if (!stmt->relation)
+               ereport(ERROR,
+                               (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
+                                errmsg("missing FROM clause")));
+       if (!stmt->keys)
+               ereport(ERROR,
+                               (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
+                                errmsg("missing ON clause")));
+ }
+ 
  /*----------
   * Recursive view transformation
   *
*** a/src/backend/utils/adt/ruleutils.c
--- b/src/backend/utils/adt/ruleutils.c
***************
*** 1504,1518 **** pg_get_statisticsext_worker(Oid statextid, bool missing_ok)
        }
  
        /*
!        * If any option is disabled, then we'll need to append a WITH clause to
!        * show which options are enabled.  We omit the WITH clause on purpose
         * when all options are enabled, so a pg_dump/pg_restore will create all
         * statistics types on a newer postgres version, if the statistics had 
all
         * options enabled on the original version.
         */
        if (!ndistinct_enabled || !dependencies_enabled)
        {
!               appendStringInfoString(&buf, " WITH (");
                if (ndistinct_enabled)
                        appendStringInfoString(&buf, "ndistinct");
                else if (dependencies_enabled)
--- 1504,1518 ----
        }
  
        /*
!        * If any option is disabled, then we'll need to append the types clause
!        * to show which options are enabled.  We omit the WITH clause on 
purpose
         * when all options are enabled, so a pg_dump/pg_restore will create all
         * statistics types on a newer postgres version, if the statistics had 
all
         * options enabled on the original version.
         */
        if (!ndistinct_enabled || !dependencies_enabled)
        {
!               appendStringInfoString(&buf, " (");
                if (ndistinct_enabled)
                        appendStringInfoString(&buf, "ndistinct");
                else if (dependencies_enabled)
*** a/src/bin/pg_dump/t/002_pg_dump.pl
--- b/src/bin/pg_dump/t/002_pg_dump.pl
***************
*** 4958,4967 **** qr/CREATE TRANSFORM FOR integer LANGUAGE sql \(FROM SQL WITH 
FUNCTION pg_catalog
                all_runs     => 1,
                catch_all    => 'CREATE ... commands',
                create_order => 97,
!               create_sql   => 'CREATE STATISTICS 
dump_test.test_ext_stats_using
!                                                       WITH (ndistinct) ON 
(col1, col2) FROM dump_test.test_fifth_table',
                regexp => qr/^
!                       \QCREATE STATISTICS dump_test.test_ext_stats_using WITH 
(ndistinct) ON (col1, col2) FROM test_fifth_table;\E
                    /xms,
                like => {
                        binary_upgrade          => 1,
--- 4958,4967 ----
                all_runs     => 1,
                catch_all    => 'CREATE ... commands',
                create_order => 97,
!               create_sql   => 'CREATE STATISTICS dump_test.test_ext_stats_opts
!                                                       (ndistinct) ON (col1, 
col2) FROM dump_test.test_fifth_table',
                regexp => qr/^
!                       \QCREATE STATISTICS dump_test.test_ext_stats_opts 
(ndistinct) ON (col1, col2) FROM test_fifth_table;\E
                    /xms,
                like => {
                        binary_upgrade          => 1,
*** a/src/bin/psql/describe.c
--- b/src/bin/psql/describe.c
***************
*** 2385,2391 **** describeOneTableDetails(const char *schemaname,
                                        printfPQExpBuffer(&buf, "    ");
  
                                        /* statistics name (qualified with 
namespace) */
!                                       appendPQExpBuffer(&buf, "\"%s.%s\" WITH 
(",
                                                                          
PQgetvalue(result, i, 1),
                                                                          
PQgetvalue(result, i, 2));
  
--- 2385,2391 ----
                                        printfPQExpBuffer(&buf, "    ");
  
                                        /* statistics name (qualified with 
namespace) */
!                                       appendPQExpBuffer(&buf, "\"%s.%s\" (",
                                                                          
PQgetvalue(result, i, 1),
                                                                          
PQgetvalue(result, i, 2));
  
*** a/src/include/nodes/nodes.h
--- b/src/include/nodes/nodes.h
***************
*** 462,467 **** typedef enum NodeTag
--- 462,468 ----
        T_InferClause,
        T_OnConflictClause,
        T_CommonTableExpr,
+       T_CreateStatsArgument,
        T_RoleSpec,
        T_TriggerTransition,
        T_PartitionElem,
*** a/src/include/nodes/parsenodes.h
--- b/src/include/nodes/parsenodes.h
***************
*** 2689,2700 **** typedef struct CreateStatsStmt
--- 2689,2714 ----
  {
        NodeTag         type;
        List       *defnames;           /* qualified name (list of Value 
strings) */
+       List       *stat_types;         /* stat types (list of Value strings) */
        RangeVar   *relation;           /* relation to build statistics on */
        List       *keys;                       /* String nodes naming 
referenced columns */
        List       *options;            /* list of DefElem */
        bool            if_not_exists;  /* do nothing if statistics already 
exists */
  } CreateStatsStmt;
  
+ typedef enum CSA_Type
+ {
+       CSA_Relations,
+       CSA_Expressions
+ } CSA_Type;
+ 
+ typedef struct CreateStatsArgument
+ {
+       NodeTag         type;
+       CSA_Type        subtype;
+       List       *elements;                   /* elements (list of Node) */
+ } CreateStatsArgument;
+ 
  /* ----------------------
   *            Create Function Statement
   * ----------------------
*** a/src/test/regress/expected/stats_ext.out
--- b/src/test/regress/expected/stats_ext.out
***************
*** 5,10 ****
--- 5,35 ----
  SET max_parallel_workers = 0;
  SET max_parallel_workers_per_gather = 0;
  SET work_mem = '128kB';
+ -- Verify failures
+ CREATE STATISTICS tst;
+ ERROR:  syntax error at or near ";"
+ LINE 1: CREATE STATISTICS tst;
+                              ^
+ CREATE STATISTICS tst ON (a, b);
+ ERROR:  missing FROM clause
+ CREATE STATISTICS tst ON (a + b);
+ ERROR:  syntax error at or near "+"
+ LINE 1: CREATE STATISTICS tst ON (a + b);
+                                     ^
+ CREATE STATISTICS tst FROM sometab;
+ ERROR:  missing ON clause
+ CREATE STATISTICS tst FROM sometab, othertab;
+ ERROR:  statistics across multiple relations are not supported yet
+ CREATE STATISTICS tst WITH (fillfactor = 80);
+ ERROR:  WITH clause is not yet implemented
+ CREATE STATISTICS tst WHERE mars > earth;
+ ERROR:  WHERE clause is not yet implemented
+ CREATE STATISTICS tst ON (a, b) FROM nonexistant;
+ ERROR:  relation "nonexistant" does not exist
+ CREATE STATISTICS tst ON (a, b) FROM pg_class;
+ ERROR:  column "a" referenced in statistics does not exist
+ CREATE STATISTICS tst (unrecognized) ON (relname, relnatts) FROM pg_class;
+ ERROR:  unrecognized statistics type "unrecognized"
  -- Ensure stats are dropped sanely
  CREATE TABLE ab1 (a INTEGER, b INTEGER, c INTEGER);
  CREATE STATISTICS ab1_a_b_stats ON (a, b) FROM ab1;
***************
*** 31,37 **** ALTER TABLE ab1 DROP COLUMN a;
   b      | integer |           |          | 
   c      | integer |           |          | 
  Statistics:
!     "public.ab1_b_c_stats" WITH (ndistinct, dependencies) ON (b, c)
  
  DROP TABLE ab1;
  -- Ensure things work sanely with SET STATISTICS 0
--- 56,62 ----
   b      | integer |           |          | 
   c      | integer |           |          | 
  Statistics:
!     "public.ab1_b_c_stats" (ndistinct, dependencies) ON (b, c)
  
  DROP TABLE ab1;
  -- Ensure things work sanely with SET STATISTICS 0
***************
*** 389,395 **** EXPLAIN (COSTS OFF)
  (2 rows)
  
  -- create statistics
! CREATE STATISTICS func_deps_stat WITH (dependencies) ON (a, b, c) FROM 
functional_dependencies;
  ANALYZE functional_dependencies;
  EXPLAIN (COSTS OFF)
   SELECT * FROM functional_dependencies WHERE a = 1 AND b = '1';
--- 414,420 ----
  (2 rows)
  
  -- create statistics
! CREATE STATISTICS func_deps_stat (dependencies) ON (a, b, c) FROM 
functional_dependencies;
  ANALYZE functional_dependencies;
  EXPLAIN (COSTS OFF)
   SELECT * FROM functional_dependencies WHERE a = 1 AND b = '1';
***************
*** 432,438 **** EXPLAIN (COSTS OFF)
  (2 rows)
  
  -- create statistics
! CREATE STATISTICS func_deps_stat WITH (dependencies) ON (a, b, c) FROM 
functional_dependencies;
  ANALYZE functional_dependencies;
  EXPLAIN (COSTS OFF)
   SELECT * FROM functional_dependencies WHERE a = 1 AND b = '1';
--- 457,463 ----
  (2 rows)
  
  -- create statistics
! CREATE STATISTICS func_deps_stat (dependencies) ON (a, b, c) FROM 
functional_dependencies;
  ANALYZE functional_dependencies;
  EXPLAIN (COSTS OFF)
   SELECT * FROM functional_dependencies WHERE a = 1 AND b = '1';
*** a/src/test/regress/sql/stats_ext.sql
--- b/src/test/regress/sql/stats_ext.sql
***************
*** 7,12 **** SET max_parallel_workers = 0;
--- 7,24 ----
  SET max_parallel_workers_per_gather = 0;
  SET work_mem = '128kB';
  
+ -- Verify failures
+ CREATE STATISTICS tst;
+ CREATE STATISTICS tst ON (a, b);
+ CREATE STATISTICS tst ON (a + b);
+ CREATE STATISTICS tst FROM sometab;
+ CREATE STATISTICS tst FROM sometab, othertab;
+ CREATE STATISTICS tst WITH (fillfactor = 80);
+ CREATE STATISTICS tst WHERE mars > earth;
+ CREATE STATISTICS tst ON (a, b) FROM nonexistant;
+ CREATE STATISTICS tst ON (a, b) FROM pg_class;
+ CREATE STATISTICS tst (unrecognized) ON (relname, relnatts) FROM pg_class;
+ 
  -- Ensure stats are dropped sanely
  CREATE TABLE ab1 (a INTEGER, b INTEGER, c INTEGER);
  CREATE STATISTICS ab1_a_b_stats ON (a, b) FROM ab1;
***************
*** 233,239 **** EXPLAIN (COSTS OFF)
   SELECT * FROM functional_dependencies WHERE a = 1 AND b = '1' AND c = 1;
  
  -- create statistics
! CREATE STATISTICS func_deps_stat WITH (dependencies) ON (a, b, c) FROM 
functional_dependencies;
  
  ANALYZE functional_dependencies;
  
--- 245,251 ----
   SELECT * FROM functional_dependencies WHERE a = 1 AND b = '1' AND c = 1;
  
  -- create statistics
! CREATE STATISTICS func_deps_stat (dependencies) ON (a, b, c) FROM 
functional_dependencies;
  
  ANALYZE functional_dependencies;
  
***************
*** 259,265 **** EXPLAIN (COSTS OFF)
   SELECT * FROM functional_dependencies WHERE a = 1 AND b = '1' AND c = 1;
  
  -- create statistics
! CREATE STATISTICS func_deps_stat WITH (dependencies) ON (a, b, c) FROM 
functional_dependencies;
  
  ANALYZE functional_dependencies;
  
--- 271,277 ----
   SELECT * FROM functional_dependencies WHERE a = 1 AND b = '1' AND c = 1;
  
  -- create statistics
! CREATE STATISTICS func_deps_stat (dependencies) ON (a, b, c) FROM 
functional_dependencies;
  
  ANALYZE functional_dependencies;
  
-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to