*** a/doc/src/sgml/perform.sgml
--- b/doc/src/sgml/perform.sgml
***************
*** 1132,1138 **** WHERE tablename = 'road';
To inspect functional dependencies on a statistics
stts, you may do this:
! 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
stts, you may do this:
! 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:
! 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:
! 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:
! 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:
! 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:
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:
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
CREATE STATISTICS [ IF NOT EXISTS ] statistics_name
! WITH ( option [= value] [, ... ] )
ON ( column_name, column_name [, ...])
FROM table_name
--- 22,28 ----
CREATE STATISTICS [ IF NOT EXISTS ] statistics_name
! [ ( statistic_type [, ... ] ) ]
ON ( column_name, column_name [, ...])
FROM table_name
***************
*** 75,80 **** CREATE STATISTICS [ IF NOT EXISTS ] statistics_na
--- 75,93 ----
+ statistic_type
+
+
+ A statistic type to be enabled for this statistics. Currently
+ supported types are ndistinct, which enables
+ n-distinct coefficient tracking,
+ and dependencies, which enables functional
+ dependencies.
+
+
+
+
+
column_name
***************
*** 94,135 **** CREATE STATISTICS [ IF NOT EXISTS ] statistics_na
-
-
- Parameters
-
-
- statistics parameters
-
-
-
- The WITH> clause can specify options>
- for the statistics. Available options are listed below.
-
-
-
-
-
- dependencies> (boolean>)
-
-
- Enables functional dependencies for the statistics.
-
-
-
-
-
- ndistinct> (boolean>)
-
-
- Enables ndistinct coefficients for the statistics.
-
-
-
-
-
-
-
--- 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 StatisticArgument
%type group_by_list
%type 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;