mirror of
https://github.com/postgres/postgres.git
synced 2026-04-04 08:45:52 -04:00
Add support for extended statistics on virtual generated columns.
This allows both univariate and multivariate statistics to be built on virtual generated columns and expressions that refer to virtual generated columns. The restriction disallowing extended statistics on a single column is lifted in the case of a single virtual generated column, since it is treated as a single expression. In the catalogs, references to virtual generated columns are stored as-is. They are expanded at ANALYZE time to build the statistics, and at planning time to allow the optimizer to make use of the statistics. This allows the statistics to be correctly rebuilt using ANALYZE, if a column's generation expression is altered (which causes any existing statistics data to be deleted). Author: Yugo Nagata <nagata@sraoss.co.jp> Reviewed-by: Dean Rasheed <dean.a.rasheed@gmail.com> Discussion: https://postgr.es/m/20250422181006.dd6f9d1d81299f5b2ad55e1a@sraoss.co.jp
This commit is contained in:
parent
196bf448e0
commit
f7f4052a4e
7 changed files with 232 additions and 116 deletions
|
|
@ -217,7 +217,8 @@ WITH ( MODULUS <replaceable class="parameter">numeric_literal</replaceable>, REM
|
|||
so running <link linkend="sql-analyze"><command>ANALYZE</command></link>
|
||||
on the table afterwards is recommended.
|
||||
For a virtual generated column, <command>ANALYZE</command>
|
||||
is not necessary because such columns never have statistics.
|
||||
is not necessary unless extended statistics are defined on it,
|
||||
since such columns do not have statistics by default.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
|
@ -289,7 +290,8 @@ WITH ( MODULUS <replaceable class="parameter">numeric_literal</replaceable>, REM
|
|||
<link linkend="sql-analyze"><command>ANALYZE</command></link>
|
||||
on the table afterwards is recommended.
|
||||
For a virtual generated column, <command>ANALYZE</command>
|
||||
is not necessary because such columns never have statistics.
|
||||
is not necessary unless extended statistics are defined on it,
|
||||
since such columns do not have statistics by default.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
|
@ -368,6 +370,12 @@ WITH ( MODULUS <replaceable class="parameter">numeric_literal</replaceable>, REM
|
|||
<productname>PostgreSQL</productname> query planner, refer to
|
||||
<xref linkend="planner-stats"/>.
|
||||
</para>
|
||||
<para>
|
||||
This form is not supported on virtual generated columns, since such
|
||||
columns do not have statistics by default. If extended statistics are
|
||||
defined on such columns, the statistics-gathering target may be set on
|
||||
the extended statistics object using <xref linkend="sql-alterstatistics"/>.
|
||||
</para>
|
||||
<para>
|
||||
<literal>SET STATISTICS</literal> acquires a
|
||||
<literal>SHARE UPDATE EXCLUSIVE</literal> lock.
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ PostgreSQL documentation
|
|||
<refsynopsisdiv>
|
||||
<synopsis>
|
||||
CREATE STATISTICS [ [ IF NOT EXISTS ] <replaceable class="parameter">statistics_name</replaceable> ]
|
||||
ON ( <replaceable class="parameter">expression</replaceable> )
|
||||
ON { <replaceable class="parameter">column_name</replaceable> | ( <replaceable class="parameter">expression</replaceable> ) }
|
||||
FROM <replaceable class="parameter">table_name</replaceable>
|
||||
|
||||
CREATE STATISTICS [ [ IF NOT EXISTS ] <replaceable class="parameter">statistics_name</replaceable> ]
|
||||
|
|
@ -45,7 +45,8 @@ CREATE STATISTICS [ [ IF NOT EXISTS ] <replaceable class="parameter">statistics_
|
|||
|
||||
<para>
|
||||
The <command>CREATE STATISTICS</command> command has two basic forms. The
|
||||
first form allows univariate statistics for a single expression to be
|
||||
first form allows univariate statistics for a single expression
|
||||
or virtual generated column to be
|
||||
collected, providing benefits similar to an expression index without the
|
||||
overhead of index maintenance. This form does not allow the statistics
|
||||
kind to be specified, since the various statistics kinds refer only to
|
||||
|
|
@ -53,7 +54,7 @@ CREATE STATISTICS [ [ IF NOT EXISTS ] <replaceable class="parameter">statistics_
|
|||
multivariate statistics on multiple columns and/or expressions to be
|
||||
collected, optionally specifying which statistics kinds to include. This
|
||||
form will also automatically cause univariate statistics to be collected on
|
||||
any expressions included in the list.
|
||||
any expressions and virtual generated columns included in the list.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
|
|
@ -109,7 +110,8 @@ CREATE STATISTICS [ [ IF NOT EXISTS ] <replaceable class="parameter">statistics_
|
|||
If this clause is omitted, all supported statistics kinds are
|
||||
included in the statistics object. Univariate expression statistics are
|
||||
built automatically if the statistics definition includes any complex
|
||||
expressions rather than just simple column references.
|
||||
expressions or references to virtual generated columns
|
||||
rather than just simple column references.
|
||||
For more information, see <xref linkend="planner-stats-extended"/>
|
||||
and <xref linkend="multivariate-statistics-examples"/>.
|
||||
</para>
|
||||
|
|
@ -121,9 +123,16 @@ CREATE STATISTICS [ [ IF NOT EXISTS ] <replaceable class="parameter">statistics_
|
|||
<listitem>
|
||||
<para>
|
||||
The name of a table column to be covered by the computed statistics.
|
||||
This is only allowed when building multivariate statistics. At least
|
||||
two column names or expressions must be specified, and their order is
|
||||
not significant.
|
||||
This may be used to build univariate statistics on a single virtual
|
||||
generated column, or as part of a list of multiple columns (virtual or
|
||||
non-virtual) and/or expressions to build multivariate statistics. In
|
||||
the latter case, separate univariate statistics are built automatically
|
||||
for each expression and virtual generated column in the list.
|
||||
</para>
|
||||
<para>
|
||||
Defining extended statistics on a single <emphasis>non-virtual</emphasis>
|
||||
column is not supported or necessary, because statistics are built
|
||||
automatically on such columns without defining extended statistics.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
|
@ -136,7 +145,8 @@ CREATE STATISTICS [ [ IF NOT EXISTS ] <replaceable class="parameter">statistics_
|
|||
used to build univariate statistics on a single expression, or as part
|
||||
of a list of multiple column names and/or expressions to build
|
||||
multivariate statistics. In the latter case, separate univariate
|
||||
statistics are built automatically for each expression in the list.
|
||||
statistics are built automatically for each expression and virtual
|
||||
generated column in the list.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
|
@ -169,7 +179,9 @@ CREATE STATISTICS [ [ IF NOT EXISTS ] <replaceable class="parameter">statistics_
|
|||
Expression statistics are per-expression and are similar to creating an
|
||||
index on the expression, except that they avoid the overhead of index
|
||||
maintenance. Expression statistics are built automatically for each
|
||||
expression in the statistics object definition.
|
||||
expression in the statistics object definition. Extended statistics on
|
||||
a virtual generated column behave the same as expression statistics on the
|
||||
column's generation expression.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
#include "commands/comment.h"
|
||||
#include "commands/defrem.h"
|
||||
#include "miscadmin.h"
|
||||
#include "nodes/makefuncs.h"
|
||||
#include "nodes/nodeFuncs.h"
|
||||
#include "optimizer/optimizer.h"
|
||||
#include "statistics/statistics.h"
|
||||
|
|
@ -232,7 +233,8 @@ CreateStatistics(CreateStatsStmt *stmt, bool check_rights)
|
|||
* Convert the expression list to a simple array of attnums, but also keep
|
||||
* a list of more complex expressions. While at it, enforce some
|
||||
* constraints - we don't allow extended statistics on system attributes,
|
||||
* and we require the data type to have a less-than operator.
|
||||
* and we require the data type to have a less-than operator, if we're
|
||||
* building multivariate statistics.
|
||||
*
|
||||
* There are many ways to "mask" a simple attribute reference as an
|
||||
* expression, for example "(a+0)" etc. We can't possibly detect all of
|
||||
|
|
@ -268,22 +270,38 @@ CreateStatistics(CreateStatsStmt *stmt, bool check_rights)
|
|||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||
errmsg("statistics creation on system columns is not supported")));
|
||||
|
||||
/* Disallow use of virtual generated columns in extended stats */
|
||||
/*
|
||||
* Disallow data types without a less-than operator in
|
||||
* multivariate statistics.
|
||||
*/
|
||||
if (numcols > 1)
|
||||
{
|
||||
type = lookup_type_cache(attForm->atttypid, TYPECACHE_LT_OPR);
|
||||
if (type->lt_opr == InvalidOid)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||
errmsg("column \"%s\" cannot be used in multivariate statistics because its type %s has no default btree operator class",
|
||||
attname, format_type_be(attForm->atttypid))));
|
||||
}
|
||||
|
||||
/* Treat virtual generated columns as expressions */
|
||||
if (attForm->attgenerated == ATTRIBUTE_GENERATED_VIRTUAL)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||
errmsg("statistics creation on virtual generated columns is not supported")));
|
||||
{
|
||||
Node *expr;
|
||||
|
||||
/* Disallow data types without a less-than operator */
|
||||
type = lookup_type_cache(attForm->atttypid, TYPECACHE_LT_OPR);
|
||||
if (type->lt_opr == InvalidOid)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||
errmsg("column \"%s\" cannot be used in statistics because its type %s has no default btree operator class",
|
||||
attname, format_type_be(attForm->atttypid))));
|
||||
|
||||
attnums[nattnums] = attForm->attnum;
|
||||
nattnums++;
|
||||
expr = (Node *) makeVar(1,
|
||||
attForm->attnum,
|
||||
attForm->atttypid,
|
||||
attForm->atttypmod,
|
||||
attForm->attcollation,
|
||||
0);
|
||||
stxexprs = lappend(stxexprs, expr);
|
||||
}
|
||||
else
|
||||
{
|
||||
attnums[nattnums] = attForm->attnum;
|
||||
nattnums++;
|
||||
}
|
||||
ReleaseSysCache(atttuple);
|
||||
}
|
||||
else if (IsA(selem->expr, Var)) /* column reference in parens */
|
||||
|
|
@ -297,22 +315,30 @@ CreateStatistics(CreateStatsStmt *stmt, bool check_rights)
|
|||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||
errmsg("statistics creation on system columns is not supported")));
|
||||
|
||||
/* Disallow use of virtual generated columns in extended stats */
|
||||
/*
|
||||
* Disallow data types without a less-than operator in
|
||||
* multivariate statistics.
|
||||
*/
|
||||
if (numcols > 1)
|
||||
{
|
||||
type = lookup_type_cache(var->vartype, TYPECACHE_LT_OPR);
|
||||
if (type->lt_opr == InvalidOid)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||
errmsg("column \"%s\" cannot be used in multivariate statistics because its type %s has no default btree operator class",
|
||||
get_attname(relid, var->varattno, false), format_type_be(var->vartype))));
|
||||
}
|
||||
|
||||
/* Treat virtual generated columns as expressions */
|
||||
if (get_attgenerated(relid, var->varattno) == ATTRIBUTE_GENERATED_VIRTUAL)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||
errmsg("statistics creation on virtual generated columns is not supported")));
|
||||
|
||||
/* Disallow data types without a less-than operator */
|
||||
type = lookup_type_cache(var->vartype, TYPECACHE_LT_OPR);
|
||||
if (type->lt_opr == InvalidOid)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||
errmsg("column \"%s\" cannot be used in statistics because its type %s has no default btree operator class",
|
||||
get_attname(relid, var->varattno, false), format_type_be(var->vartype))));
|
||||
|
||||
attnums[nattnums] = var->varattno;
|
||||
nattnums++;
|
||||
{
|
||||
stxexprs = lappend(stxexprs, (Node *) var);
|
||||
}
|
||||
else
|
||||
{
|
||||
attnums[nattnums] = var->varattno;
|
||||
nattnums++;
|
||||
}
|
||||
}
|
||||
else /* expression */
|
||||
{
|
||||
|
|
@ -336,22 +362,13 @@ CreateStatistics(CreateStatsStmt *stmt, bool check_rights)
|
|||
ereport(ERROR,
|
||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||
errmsg("statistics creation on system columns is not supported")));
|
||||
|
||||
/* Disallow use of virtual generated columns in extended stats */
|
||||
if (get_attgenerated(relid, attnum) == ATTRIBUTE_GENERATED_VIRTUAL)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||
errmsg("statistics creation on virtual generated columns is not supported")));
|
||||
}
|
||||
|
||||
/*
|
||||
* Disallow data types without a less-than operator.
|
||||
*
|
||||
* We ignore this for statistics on a single expression, in which
|
||||
* case we'll build the regular statistics only (and that code can
|
||||
* deal with such data types).
|
||||
* Disallow data types without a less-than operator in
|
||||
* multivariate statistics.
|
||||
*/
|
||||
if (list_length(stmt->exprs) > 1)
|
||||
if (numcols > 1)
|
||||
{
|
||||
atttype = exprType(expr);
|
||||
type = lookup_type_cache(atttype, TYPECACHE_LT_OPR);
|
||||
|
|
@ -367,22 +384,25 @@ CreateStatistics(CreateStatsStmt *stmt, bool check_rights)
|
|||
}
|
||||
|
||||
/*
|
||||
* Parse the statistics kinds.
|
||||
*
|
||||
* First check that if this is the case with a single expression, there
|
||||
* are no statistics kinds specified (we don't allow that for the simple
|
||||
* CREATE STATISTICS form).
|
||||
* Check that at least two columns were specified in the statement, or
|
||||
* that we're building statistics on a single expression (or virtual
|
||||
* generated column).
|
||||
*/
|
||||
if ((list_length(stmt->exprs) == 1) && (list_length(stxexprs) == 1))
|
||||
{
|
||||
/* statistics kinds not specified */
|
||||
if (stmt->stat_types != NIL)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||
errmsg("when building statistics on a single expression, statistics kinds may not be specified")));
|
||||
}
|
||||
if (numcols < 2 && list_length(stxexprs) != 1)
|
||||
ereport(ERROR,
|
||||
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
|
||||
errmsg("cannot create extended statistics on a single non-virtual column"),
|
||||
errdetail("Univariate statistics are already built for each individual non-virtual table column."));
|
||||
|
||||
/*
|
||||
* Parse the statistics kinds (not allowed when building univariate
|
||||
* statistics).
|
||||
*/
|
||||
if (numcols == 1 && stmt->stat_types != NIL)
|
||||
ereport(ERROR,
|
||||
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||
errmsg("cannot specify statistics kinds when building univariate statistics"));
|
||||
|
||||
/* OK, let's check that we recognize the statistics kinds. */
|
||||
build_ndistinct = false;
|
||||
build_dependencies = false;
|
||||
build_mcv = false;
|
||||
|
|
@ -430,15 +450,6 @@ CreateStatistics(CreateStatsStmt *stmt, bool check_rights)
|
|||
*/
|
||||
build_expressions = (stxexprs != NIL);
|
||||
|
||||
/*
|
||||
* Check that at least two columns were specified in the statement, or
|
||||
* that we're building statistics on a single expression.
|
||||
*/
|
||||
if ((numcols < 2) && (list_length(stxexprs) != 1))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
|
||||
errmsg("extended statistics require at least 2 columns")));
|
||||
|
||||
/*
|
||||
* Sort the attnums, which makes detecting duplicates somewhat easier, and
|
||||
* it does not hurt (it does not matter for the contents, unlike for
|
||||
|
|
|
|||
|
|
@ -1792,6 +1792,9 @@ get_relation_statistics(PlannerInfo *root, RelOptInfo *rel,
|
|||
exprs = (List *) stringToNode(exprsString);
|
||||
pfree(exprsString);
|
||||
|
||||
/* Expand virtual generated columns in the expressions */
|
||||
exprs = (List *) expand_generated_columns_in_expr((Node *) exprs, relation, 1);
|
||||
|
||||
/*
|
||||
* Modify the copies we obtain from the relcache to have the
|
||||
* correct varno for the parent relation, so that they match
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@
|
|||
#include "parser/parsetree.h"
|
||||
#include "pgstat.h"
|
||||
#include "postmaster/autovacuum.h"
|
||||
#include "rewrite/rewriteHandler.h"
|
||||
#include "statistics/extended_stats_internal.h"
|
||||
#include "statistics/statistics.h"
|
||||
#include "utils/acl.h"
|
||||
|
|
@ -73,7 +74,7 @@ typedef struct StatExtEntry
|
|||
} StatExtEntry;
|
||||
|
||||
|
||||
static List *fetch_statentries_for_relation(Relation pg_statext, Oid relid);
|
||||
static List *fetch_statentries_for_relation(Relation pg_statext, Relation rel);
|
||||
static VacAttrStats **lookup_var_attr_stats(Bitmapset *attrs, List *exprs,
|
||||
int nvacatts, VacAttrStats **vacatts);
|
||||
static void statext_store(Oid statOid, bool inh,
|
||||
|
|
@ -125,7 +126,7 @@ BuildRelationExtStatistics(Relation onerel, bool inh, double totalrows,
|
|||
|
||||
/* the list of stats has to be allocated outside the memory context */
|
||||
pg_stext = table_open(StatisticExtRelationId, RowExclusiveLock);
|
||||
statslist = fetch_statentries_for_relation(pg_stext, RelationGetRelid(onerel));
|
||||
statslist = fetch_statentries_for_relation(pg_stext, onerel);
|
||||
|
||||
/* memory context for building each statistics object */
|
||||
cxt = AllocSetContextCreate(CurrentMemoryContext,
|
||||
|
|
@ -279,7 +280,7 @@ ComputeExtStatisticsRows(Relation onerel,
|
|||
oldcxt = MemoryContextSwitchTo(cxt);
|
||||
|
||||
pg_stext = table_open(StatisticExtRelationId, RowExclusiveLock);
|
||||
lstats = fetch_statentries_for_relation(pg_stext, RelationGetRelid(onerel));
|
||||
lstats = fetch_statentries_for_relation(pg_stext, onerel);
|
||||
|
||||
foreach(lc, lstats)
|
||||
{
|
||||
|
|
@ -416,12 +417,13 @@ statext_is_kind_built(HeapTuple htup, char type)
|
|||
* Return a list (of StatExtEntry) of statistics objects for the given relation.
|
||||
*/
|
||||
static List *
|
||||
fetch_statentries_for_relation(Relation pg_statext, Oid relid)
|
||||
fetch_statentries_for_relation(Relation pg_statext, Relation rel)
|
||||
{
|
||||
SysScanDesc scan;
|
||||
ScanKeyData skey;
|
||||
HeapTuple htup;
|
||||
List *result = NIL;
|
||||
Oid relid = RelationGetRelid(rel);
|
||||
|
||||
/*
|
||||
* Prepare to scan pg_statistic_ext for entries having stxrelid = this
|
||||
|
|
@ -491,6 +493,9 @@ fetch_statentries_for_relation(Relation pg_statext, Oid relid)
|
|||
|
||||
pfree(exprsString);
|
||||
|
||||
/* Expand virtual generated columns in the expressions */
|
||||
exprs = (List *) expand_generated_columns_in_expr((Node *) exprs, rel, 1);
|
||||
|
||||
/*
|
||||
* Run the expressions through eval_const_expressions. This is not
|
||||
* just an optimization, but is necessary, because the planner
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ begin
|
|||
end;
|
||||
$$;
|
||||
-- Verify failures
|
||||
CREATE TABLE ext_stats_test (x text, y int, z int);
|
||||
CREATE TABLE ext_stats_test (x text, y int, z int, w xid);
|
||||
CREATE STATISTICS tst;
|
||||
ERROR: syntax error at or near ";"
|
||||
LINE 1: CREATE STATISTICS tst;
|
||||
|
|
@ -75,7 +75,8 @@ ERROR: CREATE STATISTICS only supports relation names in the FROM clause
|
|||
DROP FUNCTION tftest;
|
||||
-- incorrect expressions
|
||||
CREATE STATISTICS tst ON (y) FROM ext_stats_test; -- single column reference
|
||||
ERROR: extended statistics require at least 2 columns
|
||||
ERROR: cannot create extended statistics on a single non-virtual column
|
||||
DETAIL: Univariate statistics are already built for each individual non-virtual table column.
|
||||
CREATE STATISTICS tst ON y + z FROM ext_stats_test; -- missing parentheses
|
||||
ERROR: syntax error at or near "+"
|
||||
LINE 1: CREATE STATISTICS tst ON y + z FROM ext_stats_test;
|
||||
|
|
@ -84,30 +85,22 @@ CREATE STATISTICS tst ON (x, y) FROM ext_stats_test; -- tuple expression
|
|||
ERROR: syntax error at or near ","
|
||||
LINE 1: CREATE STATISTICS tst ON (x, y) FROM ext_stats_test;
|
||||
^
|
||||
DROP TABLE ext_stats_test;
|
||||
-- statistics on virtual generated column not allowed
|
||||
CREATE TABLE ext_stats_test1 (x int, y int, z int GENERATED ALWAYS AS (x+y) VIRTUAL, w xid);
|
||||
CREATE STATISTICS tst on z from ext_stats_test1;
|
||||
ERROR: statistics creation on virtual generated columns is not supported
|
||||
CREATE STATISTICS tst on (z) from ext_stats_test1;
|
||||
ERROR: statistics creation on virtual generated columns is not supported
|
||||
CREATE STATISTICS tst on (z+1) from ext_stats_test1;
|
||||
ERROR: statistics creation on virtual generated columns is not supported
|
||||
CREATE STATISTICS tst (ndistinct) ON z from ext_stats_test1;
|
||||
ERROR: statistics creation on virtual generated columns is not supported
|
||||
-- statistics on system column not allowed
|
||||
CREATE STATISTICS tst on tableoid from ext_stats_test1;
|
||||
CREATE STATISTICS tst on tableoid from ext_stats_test;
|
||||
ERROR: statistics creation on system columns is not supported
|
||||
CREATE STATISTICS tst on (tableoid) from ext_stats_test1;
|
||||
CREATE STATISTICS tst on (tableoid) from ext_stats_test;
|
||||
ERROR: statistics creation on system columns is not supported
|
||||
CREATE STATISTICS tst on (tableoid::int+1) from ext_stats_test1;
|
||||
CREATE STATISTICS tst on (tableoid::int+1) from ext_stats_test;
|
||||
ERROR: statistics creation on system columns is not supported
|
||||
CREATE STATISTICS tst (ndistinct) ON xmin from ext_stats_test1;
|
||||
CREATE STATISTICS tst (ndistinct) ON xmin from ext_stats_test;
|
||||
ERROR: statistics creation on system columns is not supported
|
||||
-- statistics without a less-than operator not supported
|
||||
CREATE STATISTICS tst (ndistinct) ON w from ext_stats_test1;
|
||||
ERROR: column "w" cannot be used in statistics because its type xid has no default btree operator class
|
||||
DROP TABLE ext_stats_test1;
|
||||
-- statistics kinds are not allowed with univariate statistics
|
||||
CREATE STATISTICS tst (ndistinct) ON (y + z) FROM ext_stats_test;
|
||||
ERROR: cannot specify statistics kinds when building univariate statistics
|
||||
-- multivariate statistics without a less-than operator not supported
|
||||
CREATE STATISTICS tst (ndistinct) ON x, w from ext_stats_test;
|
||||
ERROR: column "w" cannot be used in multivariate statistics because its type xid has no default btree operator class
|
||||
DROP TABLE ext_stats_test;
|
||||
-- Ensure stats are dropped sanely, and test IF NOT EXISTS while at it
|
||||
CREATE TABLE ab1 (a INTEGER, b INTEGER, c INTEGER);
|
||||
CREATE STATISTICS IF NOT EXISTS ab1_a_b_stats ON a, b FROM ab1;
|
||||
|
|
@ -3153,6 +3146,66 @@ SELECT c0 FROM ONLY expr_stats_incompatible_test WHERE
|
|||
(0 rows)
|
||||
|
||||
DROP TABLE expr_stats_incompatible_test;
|
||||
-- multivariate statistics on virtual generated columns
|
||||
CREATE TABLE virtual_gen_stats (a int, b int, c int GENERATED ALWAYS AS (2*a), d int GENERATED ALWAYS AS (a+b), w xid GENERATED ALWAYS AS (a::text::xid));
|
||||
INSERT INTO virtual_gen_stats SELECT mod(i,10), mod(i,10) FROM generate_series(1,100) s(i);
|
||||
ANALYZE virtual_gen_stats;
|
||||
SELECT * FROM check_estimated_rows('SELECT * FROM virtual_gen_stats WHERE c = 0 AND (3*b) = 0');
|
||||
estimated | actual
|
||||
-----------+--------
|
||||
1 | 10
|
||||
(1 row)
|
||||
|
||||
SELECT * FROM check_estimated_rows('SELECT * FROM virtual_gen_stats WHERE d = 0 AND (d-2*a) = 0');
|
||||
estimated | actual
|
||||
-----------+--------
|
||||
1 | 10
|
||||
(1 row)
|
||||
|
||||
CREATE STATISTICS virtual_gen_stats_1 (mcv) ON c, (3*b), d, (d-2*a) FROM virtual_gen_stats;
|
||||
ANALYZE virtual_gen_stats;
|
||||
SELECT * FROM check_estimated_rows('SELECT * FROM virtual_gen_stats WHERE c = 0 AND (3*b) = 0');
|
||||
estimated | actual
|
||||
-----------+--------
|
||||
10 | 10
|
||||
(1 row)
|
||||
|
||||
SELECT * FROM check_estimated_rows('SELECT * FROM virtual_gen_stats WHERE d = 0 AND (d-2*a) = 0');
|
||||
estimated | actual
|
||||
-----------+--------
|
||||
10 | 10
|
||||
(1 row)
|
||||
|
||||
-- univariate statistics on individual virtual generated columns
|
||||
DROP STATISTICS virtual_gen_stats_1;
|
||||
SELECT * FROM check_estimated_rows('SELECT * FROM virtual_gen_stats WHERE c = 0');
|
||||
estimated | actual
|
||||
-----------+--------
|
||||
1 | 10
|
||||
(1 row)
|
||||
|
||||
SELECT * FROM check_estimated_rows('SELECT * FROM virtual_gen_stats WHERE w = 0');
|
||||
estimated | actual
|
||||
-----------+--------
|
||||
1 | 10
|
||||
(1 row)
|
||||
|
||||
CREATE STATISTICS virtual_gen_stats_single ON c FROM virtual_gen_stats;
|
||||
CREATE STATISTICS virtual_gen_stats_single_without_less_than ON w FROM virtual_gen_stats;
|
||||
ANALYZE virtual_gen_stats;
|
||||
SELECT * FROM check_estimated_rows('SELECT * FROM virtual_gen_stats WHERE c = 0');
|
||||
estimated | actual
|
||||
-----------+--------
|
||||
10 | 10
|
||||
(1 row)
|
||||
|
||||
SELECT * FROM check_estimated_rows('SELECT * FROM virtual_gen_stats WHERE w = 0');
|
||||
estimated | actual
|
||||
-----------+--------
|
||||
10 | 10
|
||||
(1 row)
|
||||
|
||||
DROP TABLE virtual_gen_stats;
|
||||
-- Permission tests. Users should not be able to see specific data values in
|
||||
-- the extended statistics, if they lack permission to see those values in
|
||||
-- the underlying table.
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ end;
|
|||
$$;
|
||||
|
||||
-- Verify failures
|
||||
CREATE TABLE ext_stats_test (x text, y int, z int);
|
||||
CREATE TABLE ext_stats_test (x text, y int, z int, w xid);
|
||||
CREATE STATISTICS tst;
|
||||
CREATE STATISTICS tst ON a, b;
|
||||
CREATE STATISTICS tst FROM sometab;
|
||||
|
|
@ -56,21 +56,16 @@ DROP FUNCTION tftest;
|
|||
CREATE STATISTICS tst ON (y) FROM ext_stats_test; -- single column reference
|
||||
CREATE STATISTICS tst ON y + z FROM ext_stats_test; -- missing parentheses
|
||||
CREATE STATISTICS tst ON (x, y) FROM ext_stats_test; -- tuple expression
|
||||
DROP TABLE ext_stats_test;
|
||||
-- statistics on virtual generated column not allowed
|
||||
CREATE TABLE ext_stats_test1 (x int, y int, z int GENERATED ALWAYS AS (x+y) VIRTUAL, w xid);
|
||||
CREATE STATISTICS tst on z from ext_stats_test1;
|
||||
CREATE STATISTICS tst on (z) from ext_stats_test1;
|
||||
CREATE STATISTICS tst on (z+1) from ext_stats_test1;
|
||||
CREATE STATISTICS tst (ndistinct) ON z from ext_stats_test1;
|
||||
-- statistics on system column not allowed
|
||||
CREATE STATISTICS tst on tableoid from ext_stats_test1;
|
||||
CREATE STATISTICS tst on (tableoid) from ext_stats_test1;
|
||||
CREATE STATISTICS tst on (tableoid::int+1) from ext_stats_test1;
|
||||
CREATE STATISTICS tst (ndistinct) ON xmin from ext_stats_test1;
|
||||
-- statistics without a less-than operator not supported
|
||||
CREATE STATISTICS tst (ndistinct) ON w from ext_stats_test1;
|
||||
DROP TABLE ext_stats_test1;
|
||||
CREATE STATISTICS tst on tableoid from ext_stats_test;
|
||||
CREATE STATISTICS tst on (tableoid) from ext_stats_test;
|
||||
CREATE STATISTICS tst on (tableoid::int+1) from ext_stats_test;
|
||||
CREATE STATISTICS tst (ndistinct) ON xmin from ext_stats_test;
|
||||
-- statistics kinds are not allowed with univariate statistics
|
||||
CREATE STATISTICS tst (ndistinct) ON (y + z) FROM ext_stats_test;
|
||||
-- multivariate statistics without a less-than operator not supported
|
||||
CREATE STATISTICS tst (ndistinct) ON x, w from ext_stats_test;
|
||||
DROP TABLE ext_stats_test;
|
||||
|
||||
-- Ensure stats are dropped sanely, and test IF NOT EXISTS while at it
|
||||
CREATE TABLE ab1 (a INTEGER, b INTEGER, c INTEGER);
|
||||
|
|
@ -1584,6 +1579,35 @@ SELECT c0 FROM ONLY expr_stats_incompatible_test WHERE
|
|||
|
||||
DROP TABLE expr_stats_incompatible_test;
|
||||
|
||||
-- multivariate statistics on virtual generated columns
|
||||
CREATE TABLE virtual_gen_stats (a int, b int, c int GENERATED ALWAYS AS (2*a), d int GENERATED ALWAYS AS (a+b), w xid GENERATED ALWAYS AS (a::text::xid));
|
||||
INSERT INTO virtual_gen_stats SELECT mod(i,10), mod(i,10) FROM generate_series(1,100) s(i);
|
||||
ANALYZE virtual_gen_stats;
|
||||
|
||||
SELECT * FROM check_estimated_rows('SELECT * FROM virtual_gen_stats WHERE c = 0 AND (3*b) = 0');
|
||||
SELECT * FROM check_estimated_rows('SELECT * FROM virtual_gen_stats WHERE d = 0 AND (d-2*a) = 0');
|
||||
|
||||
CREATE STATISTICS virtual_gen_stats_1 (mcv) ON c, (3*b), d, (d-2*a) FROM virtual_gen_stats;
|
||||
ANALYZE virtual_gen_stats;
|
||||
|
||||
SELECT * FROM check_estimated_rows('SELECT * FROM virtual_gen_stats WHERE c = 0 AND (3*b) = 0');
|
||||
SELECT * FROM check_estimated_rows('SELECT * FROM virtual_gen_stats WHERE d = 0 AND (d-2*a) = 0');
|
||||
|
||||
-- univariate statistics on individual virtual generated columns
|
||||
DROP STATISTICS virtual_gen_stats_1;
|
||||
|
||||
SELECT * FROM check_estimated_rows('SELECT * FROM virtual_gen_stats WHERE c = 0');
|
||||
SELECT * FROM check_estimated_rows('SELECT * FROM virtual_gen_stats WHERE w = 0');
|
||||
|
||||
CREATE STATISTICS virtual_gen_stats_single ON c FROM virtual_gen_stats;
|
||||
CREATE STATISTICS virtual_gen_stats_single_without_less_than ON w FROM virtual_gen_stats;
|
||||
ANALYZE virtual_gen_stats;
|
||||
|
||||
SELECT * FROM check_estimated_rows('SELECT * FROM virtual_gen_stats WHERE c = 0');
|
||||
SELECT * FROM check_estimated_rows('SELECT * FROM virtual_gen_stats WHERE w = 0');
|
||||
|
||||
DROP TABLE virtual_gen_stats;
|
||||
|
||||
-- Permission tests. Users should not be able to see specific data values in
|
||||
-- the extended statistics, if they lack permission to see those values in
|
||||
-- the underlying table.
|
||||
|
|
|
|||
Loading…
Reference in a new issue