diff --git a/doc/src/sgml/perform.sgml b/doc/src/sgml/perform.sgml index b10b734b90..3406b7a1cd 100644 --- a/doc/src/sgml/perform.sgml +++ b/doc/src/sgml/perform.sgml @@ -1132,7 +1132,7 @@ WHERE tablename = 'road'; To inspect functional dependencies on a statistics stts, you may do this: -CREATE STATISTICS stts WITH (dependencies) +CREATE STATISTICS stts USING (dependencies) ON (zip, city) FROM zipcodes; ANALYZE zipcodes; SELECT stxname, stxkeys, stxdependencies @@ -1219,7 +1219,7 @@ 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: -CREATE STATISTICS stts2 WITH (ndistinct) +CREATE STATISTICS stts2 USING (ndistinct) ON (zip, state, city) FROM zipcodes; ANALYZE zipcodes; SELECT stxkeys AS k, stxndistinct AS nd diff --git a/doc/src/sgml/planstats.sgml b/doc/src/sgml/planstats.sgml index f4430eb23c..16c433c3a2 100644 --- a/doc/src/sgml/planstats.sgml +++ b/doc/src/sgml/planstats.sgml @@ -526,7 +526,7 @@ EXPLAIN (ANALYZE, TIMING OFF) SELECT * FROM t WHERE a = 1 AND b = 1; multivariate statistics on the two columns: -CREATE STATISTICS stts WITH (dependencies) ON (a, b) FROM t; +CREATE STATISTICS stts USING (dependencies) ON (a, b) FROM t; ANALYZE t; EXPLAIN (ANALYZE, TIMING OFF) SELECT * FROM t WHERE a = 1 AND b = 1; QUERY PLAN @@ -569,7 +569,7 @@ EXPLAIN (ANALYZE, TIMING OFF) SELECT COUNT(*) FROM t GROUP BY a, b; calculation, the estimate is much improved: DROP STATISTICS stts; -CREATE STATISTICS stts WITH (dependencies, ndistinct) ON (a, b) FROM t; +CREATE STATISTICS stts USING (dependencies, ndistinct) ON (a, b) FROM t; ANALYZE t; EXPLAIN (ANALYZE, TIMING OFF) SELECT COUNT(*) FROM t GROUP BY a, b; QUERY PLAN diff --git a/doc/src/sgml/ref/create_statistics.sgml b/doc/src/sgml/ref/create_statistics.sgml index edbcf5840b..ff6ed0668f 100644 --- a/doc/src/sgml/ref/create_statistics.sgml +++ b/doc/src/sgml/ref/create_statistics.sgml @@ -22,7 +22,7 @@ PostgreSQL documentation CREATE STATISTICS [ IF NOT EXISTS ] statistics_name - WITH ( option [= value] [, ... ] ) + USING ( statistic_type [, ... ] ) ON ( column_name, column_name [, ...]) FROM table_name @@ -103,14 +103,14 @@ CREATE STATISTICS [ IF NOT EXISTS ] statistics_na - The WITH clause can specify options - for the statistics. Available options are listed below. + The USING clause can specify types of statistics + to be enabled. Available types are listed below. - dependencies (boolean) + dependencies Enables functional dependencies for the statistics. @@ -119,7 +119,7 @@ CREATE STATISTICS [ IF NOT EXISTS ] statistics_na - ndistinct (boolean) + ndistinct Enables ndistinct coefficients for the statistics. diff --git a/src/backend/commands/statscmds.c b/src/backend/commands/statscmds.c index 0b9c33e30a..f4d1712091 100644 --- a/src/backend/commands/statscmds.c +++ b/src/backend/commands/statscmds.c @@ -194,23 +194,22 @@ CreateStatistics(CreateStatsStmt *stmt) stxkeys = buildint2vector(attnums, numcols); /* - * Parse the statistics options. Currently only statistics types are - * recognized. + * Parse the statistic type options. */ build_ndistinct = false; build_dependencies = false; - foreach(l, stmt->options) + foreach(l, stmt->stat_options) { DefElem *opt = (DefElem *) lfirst(l); if (strcmp(opt->defname, "ndistinct") == 0) { - build_ndistinct = defGetBoolean(opt); + build_ndistinct = true; requested_type = true; } else if (strcmp(opt->defname, "dependencies") == 0) { - build_dependencies = defGetBoolean(opt); + build_dependencies = true; requested_type = true; } else diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c index 35a237a000..01c57e4783 100644 --- a/src/backend/nodes/copyfuncs.c +++ b/src/backend/nodes/copyfuncs.c @@ -3391,7 +3391,7 @@ _copyCreateStatsStmt(const CreateStatsStmt *from) COPY_NODE_FIELD(defnames); COPY_NODE_FIELD(relation); COPY_NODE_FIELD(keys); - COPY_NODE_FIELD(options); + COPY_NODE_FIELD(stat_options); COPY_SCALAR_FIELD(if_not_exists); return newnode; diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c index 21dfbb0d75..01e2124883 100644 --- a/src/backend/nodes/equalfuncs.c +++ b/src/backend/nodes/equalfuncs.c @@ -1351,7 +1351,7 @@ _equalCreateStatsStmt(const CreateStatsStmt *a, const CreateStatsStmt *b) COMPARE_NODE_FIELD(defnames); COMPARE_NODE_FIELD(relation); COMPARE_NODE_FIELD(keys); - COMPARE_NODE_FIELD(options); + COMPARE_NODE_FIELD(stat_options); COMPARE_SCALAR_FIELD(if_not_exists); return true; diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c index 98f67681a7..015537a4c8 100644 --- a/src/backend/nodes/outfuncs.c +++ b/src/backend/nodes/outfuncs.c @@ -2641,7 +2641,7 @@ _outCreateStatsStmt(StringInfo str, const CreateStatsStmt *node) WRITE_NODE_FIELD(defnames); WRITE_NODE_FIELD(relation); WRITE_NODE_FIELD(keys); - WRITE_NODE_FIELD(options); + WRITE_NODE_FIELD(stat_options); WRITE_BOOL_FIELD(if_not_exists); } diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index 818d2c29d4..a3467f1c47 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -371,6 +371,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query); OptTableElementList TableElementList OptInherit definition OptTypedTableElementList TypedTableElementList reloptions opt_reloptions + stat_option_list opt_stat_option_list OptWith distinct_clause opt_all_clause opt_definition func_args func_args_list func_args_with_defaults func_args_with_defaults_list aggr_args aggr_args_list @@ -464,6 +465,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query); %type TableElement TypedTableElement ConstraintElem TableFuncElement %type columnDef columnOptions %type def_elem reloption_elem old_aggr_elem operator_def_elem + stat_option_elem %type def_arg columnElem where_clause where_or_current_clause a_expr b_expr c_expr AexprConst indirection_el opt_slice_bound columnref in_expr having_clause func_table xmltable array_expr @@ -3828,32 +3830,59 @@ ExistingIndex: USING INDEX index_name { $$ = $3; } /***************************************************************************** * * QUERY : - * CREATE STATISTICS stats_name WITH (options) ON (columns) FROM relname + * CREATE STATISTICS stats_name [USING (stat_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; - } - ; +opt_stat_option_list: + USING '(' stat_option_list ')' { $$ = $3; } + | /* EMPTY */ { $$ = NIL; } + ; + +stat_option_list: + stat_option_elem + { + $$ = list_make1($1); + } + | stat_option_list ',' stat_option_elem + { + $$ = lappend($1, $3); + } + ; + +stat_option_elem: + ColLabel + { + $$ = makeDefElem($1, NULL, @1); + } + ; + +CreateStatsStmt: + CREATE STATISTICS any_name opt_stat_option_list + ON '(' columnList ')' FROM qualified_name + { + CreateStatsStmt *n = makeNode(CreateStatsStmt); + n->defnames = $3; + n->relation = $10; + n->keys = $7; + n->stat_options = $4; + n->if_not_exists = false; + $$ = (Node *)n; + } + | CREATE STATISTICS IF_P NOT EXISTS any_name opt_stat_option_list + ON '(' columnList ')' FROM qualified_name + { + CreateStatsStmt *n = makeNode(CreateStatsStmt); + n->defnames = $6; + n->relation = $13; + n->keys = $10; + n->stat_options = $7; + n->if_not_exists = true; + $$ = (Node *)n; + } + ; /***************************************************************************** * diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c index cbde1fff01..cdc1712928 100644 --- a/src/backend/utils/adt/ruleutils.c +++ b/src/backend/utils/adt/ruleutils.c @@ -1479,7 +1479,7 @@ pg_get_statisticsext_worker(Oid statextid, bool missing_ok) NameStr(statextrec->stxname))); /* - * Lookup the stxkind column so that we know how to handle the WITH + * Lookup the stxkind column so that we know how to handle the USING * clause. */ datum = SysCacheGetAttr(STATEXTOID, statexttup, @@ -1504,15 +1504,15 @@ 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 + * If any option is disabled, then we'll need to append a USING clause to + * show which options are enabled. We omit the USING 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 ("); + appendStringInfoString(&buf, " USING ("); if (ndistinct_enabled) appendStringInfoString(&buf, "ndistinct"); else if (dependencies_enabled) diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c index dbfc7339e5..dbea7fa677 100644 --- a/src/bin/psql/describe.c +++ b/src/bin/psql/describe.c @@ -2385,7 +2385,7 @@ describeOneTableDetails(const char *schemaname, printfPQExpBuffer(&buf, " "); /* statistics name (qualified with namespace) */ - appendPQExpBuffer(&buf, "\"%s.%s\" WITH (", + appendPQExpBuffer(&buf, "\"%s.%s\" USING (", PQgetvalue(result, i, 1), PQgetvalue(result, i, 2)); diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h index e1d454a07d..0409f9d814 100644 --- a/src/include/nodes/parsenodes.h +++ b/src/include/nodes/parsenodes.h @@ -2691,7 +2691,7 @@ typedef struct CreateStatsStmt List *defnames; /* qualified name (list of Value strings) */ RangeVar *relation; /* relation to build statistics on */ List *keys; /* String nodes naming referenced columns */ - List *options; /* list of DefElem */ + List *stat_options; /* list of name-only DefElem for stat types */ bool if_not_exists; /* do nothing if statistics already exists */ } CreateStatsStmt; diff --git a/src/test/regress/expected/stats_ext.out b/src/test/regress/expected/stats_ext.out index 92ac84ac67..e756f58e2d 100644 --- a/src/test/regress/expected/stats_ext.out +++ b/src/test/regress/expected/stats_ext.out @@ -31,7 +31,7 @@ ALTER TABLE ab1 DROP COLUMN a; b | integer | | | c | integer | | | Statistics: - "public.ab1_b_c_stats" WITH (ndistinct, dependencies) ON (b, c) + "public.ab1_b_c_stats" USING (ndistinct, dependencies) ON (b, c) DROP TABLE ab1; -- Ensure things work sanely with SET STATISTICS 0 @@ -389,7 +389,7 @@ EXPLAIN (COSTS OFF) (2 rows) -- create statistics -CREATE STATISTICS func_deps_stat WITH (dependencies) ON (a, b, c) FROM functional_dependencies; +CREATE STATISTICS func_deps_stat USING (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,7 +432,7 @@ EXPLAIN (COSTS OFF) (2 rows) -- create statistics -CREATE STATISTICS func_deps_stat WITH (dependencies) ON (a, b, c) FROM functional_dependencies; +CREATE STATISTICS func_deps_stat USING (dependencies) ON (a, b, c) FROM functional_dependencies; ANALYZE functional_dependencies; EXPLAIN (COSTS OFF) SELECT * FROM functional_dependencies WHERE a = 1 AND b = '1'; diff --git a/src/test/regress/sql/stats_ext.sql b/src/test/regress/sql/stats_ext.sql index 72c7659c4b..15f863f3e0 100644 --- a/src/test/regress/sql/stats_ext.sql +++ b/src/test/regress/sql/stats_ext.sql @@ -233,7 +233,7 @@ 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; +CREATE STATISTICS func_deps_stat USING (dependencies) ON (a, b, c) FROM functional_dependencies; ANALYZE functional_dependencies; @@ -259,7 +259,7 @@ 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; +CREATE STATISTICS func_deps_stat USING (dependencies) ON (a, b, c) FROM functional_dependencies; ANALYZE functional_dependencies;