Skip to content

Commit c52c15c

Browse files
committed
chore: fixed additional review comments and added docs for the node
1 parent bc1825e commit c52c15c

17 files changed

Lines changed: 196 additions & 30 deletions

File tree

docs/en_US/managing_database_objects.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ node, and select *Create Cast...*
3939
publication_dialog
4040
schema_dialog
4141
sequence_dialog
42+
statistics_dialog
4243
subscription_dialog
4344
synonym_dialog
4445
trigger_function_dialog

docs/en_US/release_notes_9_16.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ New features
2929
| `Issue #9626 <https://github.com/pgadmin-org/pgadmin4/issues/9626>`_ - Add support for the TOAST tuple target storage parameter in the Materialized View dialog.
3030
| `Issue #9646 <https://github.com/pgadmin-org/pgadmin4/issues/9646>`_ - Make the init container security context in the Helm chart configurable via containerSecurityContext, consistent with the main container.
3131
| `Issue #9699 <https://github.com/pgadmin-org/pgadmin4/issues/9699>`_ - Add support for closing a tab with a middle-click on its title.
32+
| `Issue #2018 <https://github.com/pgadmin-org/pgadmin4/issues/2018>`_ - Added support for Extended Statistics objects (CREATE STATISTICS) under the Schema node, with full create, edit, delete, and SQL-generation support for column-based and expression-based statistics on PostgreSQL 14+.
3233
3334
Housekeeping
3435
************

docs/en_US/statistics_dialog.rst

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
.. _statistics_dialog:
2+
3+
**************************
4+
`Statistics Dialog`:index:
5+
**************************
6+
7+
Use the *Statistics* dialog to define extended statistics on one or more columns
8+
(or expressions) of a table. Extended statistics let PostgreSQL collect
9+
correlation data across columns that can significantly improve query-plan
10+
estimates for queries that filter or group by multiple columns.
11+
12+
Extended statistics require PostgreSQL 14 or later.
13+
14+
The *Statistics* dialog organizes options across the *General* and *Definition*
15+
tabs. The *SQL* tab displays the SQL command generated by your selections.
16+
17+
Use the fields in the *General* tab to identify the statistics object:
18+
19+
* Use the *Name* field to enter a descriptive name. On PostgreSQL 16 and later,
20+
the name is optional — PostgreSQL will auto-generate one if left blank.
21+
* Use the *Owner* field to select the role that will own the statistics object.
22+
* Use the *Schema* field to select the schema in which the statistics object
23+
will reside.
24+
* Use the *Comment* field to store an optional note about the statistics object.
25+
26+
Click the *Definition* tab to continue.
27+
28+
Use the fields in the *Definition* tab to describe the statistics:
29+
30+
* Use the *Table* field to select the table on which the statistics will be
31+
collected. The list is filtered to tables in the selected schema.
32+
* Use the *Columns* field to select two or more columns. Hold *Ctrl* (or *Cmd*
33+
on macOS) to select multiple columns. At least two columns are required when
34+
collecting column-based statistics.
35+
* Use the *Expressions* field to enter one or more SQL expressions separated by
36+
commas (e.g. ``lower(col1), (col1 + col2)``). Specify expressions instead of
37+
columns when you want statistics on derived values.
38+
* Use the *Statistics types* field to choose which kinds of extended statistics
39+
to collect:
40+
41+
* *N-distinct* — estimates the number of distinct value combinations across
42+
the selected columns or expressions.
43+
* *Dependencies* — detects functional dependencies between columns, improving
44+
estimates for queries with correlated ``WHERE`` clauses.
45+
* *MCV (Most Common Values)* — records the most common combinations of values,
46+
available on PostgreSQL 12 and later.
47+
48+
Click the *SQL* tab to continue.
49+
50+
Your entries in the *Statistics* dialog generate a SQL command (see an example
51+
below). Use the *SQL* tab for review; revisit or switch tabs to make any changes.
52+
53+
Example
54+
*******
55+
56+
The following is an example of the SQL command generated by user selections in
57+
the *Statistics* dialog::
58+
59+
CREATE STATISTICS public.order_stats
60+
(ndistinct, dependencies)
61+
ON customer_id, region_id
62+
FROM public.orders;
63+
64+
* Click the *Info* button (i) to access online help.
65+
* Click the *Save* button to save work.
66+
* Click the *Close* button to exit without saving work.
67+
* Click the *Reset* button to restore configuration parameters.

web/pgadmin/browser/server_groups/servers/databases/schemas/statistics/__init__.py

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -363,12 +363,9 @@ def _fetch_properties(self, scid, stid):
363363
if row.get('columns') is None:
364364
row['columns'] = []
365365

366-
# Set has_expressions boolean based on expressions field
367-
# expressions is pg_node_tree (bytea) - we just check if it exists
368-
row['has_expressions'] = row.get('expressions') is not None
369-
370-
# Remove expressions from display (it's internal PostgreSQL format)
371-
row.pop('expressions', None)
366+
# expression_list is the deparsed text from pg_get_expr; keep it for
367+
# SQL-tab round-trip and set has_expressions for the properties switch
368+
row['has_expressions'] = row.get('expression_list') is not None
372369

373370
# Ensure stattarget has a default value if None
374371
if row.get('stattarget') is None:

web/pgadmin/browser/server_groups/servers/databases/schemas/statistics/static/js/statistics.ui.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,9 @@ export default class StatisticsSchema extends BaseUISchema {
116116
let tid = obj.getTableOid(state.table);
117117
return {
118118
type: 'select',
119-
options: state.table ? ()=>obj.fieldOptions.getColumns({tid: tid}) : [],
119+
options: (state.table && tid)
120+
? () => obj.fieldOptions.getColumns({tid: tid})
121+
: (state.columns || []).map(col => ({label: col, value: col})),
120122
optionsReloadBasis: state.table,
121123
};
122124
},

web/pgadmin/browser/server_groups/servers/databases/schemas/statistics/templates/statistics/sql/16_plus/create.sql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ CREATE STATISTICS{% if data.name %}{% if add_not_exists_clause %} IF NOT EXISTS{
44

55
({% for stype in data.stat_types %}{{ stype }}{% if not loop.last %}, {% endif %}{% endfor %}){% endif %}
66

7-
ON {% if data.expressions and data.expressions|length > 0 %}{% for expr in data.expressions %}({{ expr.expression if expr.expression is defined else expr }}){% if not loop.last %}, {% endif %}{% endfor %}{% elif data.columns %}{% for col in data.columns %}{{ conn|qtIdent(col) }}{% if not loop.last %}, {% endif %}{% endfor %}{% endif %}
7+
ON {% if data.expressions and data.expressions|length > 0 %}{% for expr in data.expressions %}({{ expr.expression if expr.expression is defined else expr }}){% if not loop.last %}, {% endif %}{% endfor %}{% elif data.expression_list %}{{ data.expression_list }}{% elif data.columns %}{% for col in data.columns %}{{ conn|qtIdent(col) }}{% if not loop.last %}, {% endif %}{% endfor %}{% endif %}
88

99
FROM {{ conn|qtIdent(data.schema, data.table) }};
1010
{% if data.comment and data.name %}

web/pgadmin/browser/server_groups/servers/databases/schemas/statistics/templates/statistics/sql/16_plus/properties.sql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ SELECT
2020
CASE WHEN 'm' = ANY(s.stxkind) THEN true ELSE false END AS has_mcv,
2121
s.stxstattarget AS stattarget,
2222
{### stxexprs added in PostgreSQL 14 for expression statistics ###}
23-
s.stxexprs AS expressions,
23+
pg_catalog.pg_get_expr(s.stxexprs, s.stxrelid) AS expression_list,
2424
{### Statistics data from pg_statistic_ext_data (PostgreSQL 12+) ###}
2525
sd.stxdndistinct AS ndistinct_values,
2626
sd.stxddependencies AS dependencies_values,

web/pgadmin/browser/server_groups/servers/databases/schemas/statistics/templates/statistics/sql/16_plus/update.sql

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
{### SQL to update extended statistics object (PostgreSQL 16+) ###}
22
{### Rename statistics ###}
33
{% if data.name and data.name != o_data.name %}
4-
ALTER STATISTICS {% if data.schema and data.schema != o_data.schema %}{{ conn|qtIdent(o_data.schema, o_data.name) }}{% else %}{{ conn|qtIdent(o_data.schema, o_data.name) }}{% endif %}
5-
4+
ALTER STATISTICS {{ conn|qtIdent(o_data.schema, o_data.name) }}
65
RENAME TO {{ conn|qtIdent(data.name) }};
76

87
{% endif %}

web/pgadmin/browser/server_groups/servers/databases/schemas/statistics/templates/statistics/sql/17_plus/create.sql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ CREATE STATISTICS{% if data.name %}{% if add_not_exists_clause %} IF NOT EXISTS{
44

55
({% for stype in data.stat_types %}{{ stype }}{% if not loop.last %}, {% endif %}{% endfor %}){% endif %}
66

7-
ON {% if data.expressions and data.expressions|length > 0 %}{% for expr in data.expressions %}({{ expr.expression if expr.expression is defined else expr }}){% if not loop.last %}, {% endif %}{% endfor %}{% elif data.columns %}{% for col in data.columns %}{{ conn|qtIdent(col) }}{% if not loop.last %}, {% endif %}{% endfor %}{% endif %}
7+
ON {% if data.expressions and data.expressions|length > 0 %}{% for expr in data.expressions %}({{ expr.expression if expr.expression is defined else expr }}){% if not loop.last %}, {% endif %}{% endfor %}{% elif data.expression_list %}{{ data.expression_list }}{% elif data.columns %}{% for col in data.columns %}{{ conn|qtIdent(col) }}{% if not loop.last %}, {% endif %}{% endfor %}{% endif %}
88

99
FROM {{ conn|qtIdent(data.schema, data.table) }};
1010
{% if data.comment and data.name %}

web/pgadmin/browser/server_groups/servers/databases/schemas/statistics/templates/statistics/sql/17_plus/properties.sql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ SELECT
2020
CASE WHEN 'm' = ANY(s.stxkind) THEN true ELSE false END AS has_mcv,
2121
s.stxstattarget AS stattarget,
2222
{### stxexprs added in PostgreSQL 14 for expression statistics ###}
23-
s.stxexprs AS expressions,
23+
pg_catalog.pg_get_expr(s.stxexprs, s.stxrelid) AS expression_list,
2424
{### Statistics data from pg_statistic_ext_data (PostgreSQL 12+) ###}
2525
sd.stxdndistinct AS ndistinct_values,
2626
sd.stxddependencies AS dependencies_values,

0 commit comments

Comments
 (0)