summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--contrib/sepgsql/database.c1
-rw-r--r--contrib/sepgsql/label.c1
-rw-r--r--doc/src/sgml/glossary.sgml27
-rw-r--r--src/backend/access/heap/vacuumlazy.c1
-rw-r--r--src/backend/access/transam/multixact.c2
-rw-r--r--src/backend/access/transam/varsup.c2
-rw-r--r--src/backend/catalog/aclchk.c1
-rw-r--r--src/backend/catalog/namespace.c1
-rw-r--r--src/backend/catalog/objectaddress.c1
-rw-r--r--src/backend/catalog/pg_shdepend.c2
-rw-r--r--src/backend/commands/analyze.c1
-rw-r--r--src/backend/commands/comment.c2
-rw-r--r--src/backend/commands/dbcommands.c25
-rw-r--r--src/backend/commands/indexcmds.c1
-rw-r--r--src/backend/commands/publicationcmds.c1
-rw-r--r--src/backend/commands/schemacmds.c2
-rw-r--r--src/backend/commands/subscriptioncmds.c1
-rw-r--r--src/backend/commands/trigger.c1
-rw-r--r--src/backend/optimizer/plan/planner.c80
-rw-r--r--src/backend/parser/parse_expr.c1
-rw-r--r--src/backend/parser/parse_target.c1
-rw-r--r--src/backend/postmaster/autovacuum.c1
-rw-r--r--src/backend/postmaster/walsummarizer.c4
-rw-r--r--src/backend/replication/logical/slotsync.c1
-rw-r--r--src/backend/replication/walsender.c2
-rw-r--r--src/backend/statistics/attribute_stats.c25
-rw-r--r--src/backend/statistics/relation_stats.c2
-rw-r--r--src/backend/statistics/stat_utils.c14
-rw-r--r--src/backend/storage/aio/aio.c10
-rw-r--r--src/backend/storage/aio/aio_funcs.c2
-rw-r--r--src/backend/storage/aio/aio_io.c8
-rw-r--r--src/backend/storage/aio/method_io_uring.c2
-rw-r--r--src/backend/storage/ipc/procarray.c2
-rw-r--r--src/backend/utils/adt/acl.c1
-rw-r--r--src/backend/utils/adt/dbsize.c2
-rw-r--r--src/backend/utils/adt/misc.c1
-rw-r--r--src/backend/utils/adt/regproc.c2
-rw-r--r--src/backend/utils/adt/xml.c1
-rw-r--r--src/backend/utils/cache/lsyscache.c27
-rw-r--r--src/include/catalog/pg_database.h1
-rw-r--r--src/include/commands/dbcommands.h4
-rw-r--r--src/include/storage/aio_internal.h14
-rw-r--r--src/include/utils/lsyscache.h2
-rw-r--r--src/test/modules/worker_spi/worker_spi.c2
-rw-r--r--src/test/regress/expected/aggregates.out20
-rw-r--r--src/test/regress/expected/join.out80
-rw-r--r--src/test/regress/expected/stats_import.out60
-rw-r--r--src/test/regress/sql/aggregates.sql9
-rw-r--r--src/test/regress/sql/join.sql33
49 files changed, 309 insertions, 178 deletions
diff --git a/contrib/sepgsql/database.c b/contrib/sepgsql/database.c
index 6eeb429a28c..c4ed6464369 100644
--- a/contrib/sepgsql/database.c
+++ b/contrib/sepgsql/database.c
@@ -16,7 +16,6 @@
#include "access/table.h"
#include "catalog/dependency.h"
#include "catalog/pg_database.h"
-#include "commands/dbcommands.h"
#include "commands/seclabel.h"
#include "sepgsql.h"
#include "utils/builtins.h"
diff --git a/contrib/sepgsql/label.c b/contrib/sepgsql/label.c
index 996ce174454..a37d89a3f1c 100644
--- a/contrib/sepgsql/label.c
+++ b/contrib/sepgsql/label.c
@@ -23,7 +23,6 @@
#include "catalog/pg_database.h"
#include "catalog/pg_namespace.h"
#include "catalog/pg_proc.h"
-#include "commands/dbcommands.h"
#include "commands/seclabel.h"
#include "libpq/auth.h"
#include "libpq/libpq-be.h"
diff --git a/doc/src/sgml/glossary.sgml b/doc/src/sgml/glossary.sgml
index b88cac598e9..8651f0cdb91 100644
--- a/doc/src/sgml/glossary.sgml
+++ b/doc/src/sgml/glossary.sgml
@@ -1419,11 +1419,15 @@
<glossterm>Relation</glossterm>
<glossdef>
<para>
- The generic term for all objects in a
- <glossterm linkend="glossary-database">database</glossterm>
- that have a name and a list of
- <glossterm linkend="glossary-attribute">attributes</glossterm>
- defined in a specific order.
+ Mathematically, a <firstterm>relation</firstterm> is a set of
+ <glossterm linkend="glossary-tuple">tuples</glossterm>;
+ this is the sense meant in the term "relational database".
+ </para>
+
+ <para>
+ In <productname>PostgreSQL</productname>, "relation" is commonly used to
+ mean an <glossterm linkend="glossary-sql-object">SQL object</glossterm>
+ that has a name and a list of attributes defined in a specific order.
<glossterm linkend="glossary-table">Tables</glossterm>,
<glossterm linkend="glossary-sequence">sequences</glossterm>,
<glossterm linkend="glossary-view">views</glossterm>,
@@ -1431,15 +1435,14 @@
<glossterm linkend="glossary-materialized-view">materialized views</glossterm>,
composite types, and
<glossterm linkend="glossary-index">indexes</glossterm> are all relations.
+ A relation in this sense is a container or a descriptor for a set of tuples.
</para>
+
<para>
- More generically, a relation is a set of tuples; for example,
- the result of a query is also a relation.
- </para>
- <para>
- In <productname>PostgreSQL</productname>,
- <firstterm>Class</firstterm> is an archaic synonym for
- <firstterm>relation</firstterm>.
+ <firstterm>Class</firstterm> is an alternative but archaic term.
+ The system catalog
+ <link linkend="catalog-pg-class"><structname>pg_class</structname></link>
+ holds an entry for each <productname>PostgreSQL</productname> relation.
</para>
</glossdef>
</glossentry>
diff --git a/src/backend/access/heap/vacuumlazy.c b/src/backend/access/heap/vacuumlazy.c
index 14036c27e87..932701d8420 100644
--- a/src/backend/access/heap/vacuumlazy.c
+++ b/src/backend/access/heap/vacuumlazy.c
@@ -140,7 +140,6 @@
#include "access/visibilitymap.h"
#include "access/xloginsert.h"
#include "catalog/storage.h"
-#include "commands/dbcommands.h"
#include "commands/progress.h"
#include "commands/vacuum.h"
#include "common/int.h"
diff --git a/src/backend/access/transam/multixact.c b/src/backend/access/transam/multixact.c
index e89ab0c49b3..8bf59d369f8 100644
--- a/src/backend/access/transam/multixact.c
+++ b/src/backend/access/transam/multixact.c
@@ -75,7 +75,6 @@
#include "access/xlog.h"
#include "access/xloginsert.h"
#include "access/xlogutils.h"
-#include "commands/dbcommands.h"
#include "miscadmin.h"
#include "pg_trace.h"
#include "pgstat.h"
@@ -85,6 +84,7 @@
#include "storage/procarray.h"
#include "utils/guc_hooks.h"
#include "utils/injection_point.h"
+#include "utils/lsyscache.h"
#include "utils/memutils.h"
diff --git a/src/backend/access/transam/varsup.c b/src/backend/access/transam/varsup.c
index fe895787cb7..f8c4dada7c9 100644
--- a/src/backend/access/transam/varsup.c
+++ b/src/backend/access/transam/varsup.c
@@ -19,11 +19,11 @@
#include "access/transam.h"
#include "access/xact.h"
#include "access/xlogutils.h"
-#include "commands/dbcommands.h"
#include "miscadmin.h"
#include "postmaster/autovacuum.h"
#include "storage/pmsignal.h"
#include "storage/proc.h"
+#include "utils/lsyscache.h"
#include "utils/syscache.h"
diff --git a/src/backend/catalog/aclchk.c b/src/backend/catalog/aclchk.c
index 24948c1f05e..cd139bd65a6 100644
--- a/src/backend/catalog/aclchk.c
+++ b/src/backend/catalog/aclchk.c
@@ -64,7 +64,6 @@
#include "catalog/pg_proc.h"
#include "catalog/pg_tablespace.h"
#include "catalog/pg_type.h"
-#include "commands/dbcommands.h"
#include "commands/defrem.h"
#include "commands/event_trigger.h"
#include "commands/extension.h"
diff --git a/src/backend/catalog/namespace.c b/src/backend/catalog/namespace.c
index d97d632a7ef..8bd4d6c3d43 100644
--- a/src/backend/catalog/namespace.c
+++ b/src/backend/catalog/namespace.c
@@ -41,7 +41,6 @@
#include "catalog/pg_ts_parser.h"
#include "catalog/pg_ts_template.h"
#include "catalog/pg_type.h"
-#include "commands/dbcommands.h"
#include "common/hashfn_unstable.h"
#include "funcapi.h"
#include "mb/pg_wchar.h"
diff --git a/src/backend/catalog/objectaddress.c b/src/backend/catalog/objectaddress.c
index 0102c9984e7..91f3018fd0a 100644
--- a/src/backend/catalog/objectaddress.c
+++ b/src/backend/catalog/objectaddress.c
@@ -62,7 +62,6 @@
#include "catalog/pg_ts_template.h"
#include "catalog/pg_type.h"
#include "catalog/pg_user_mapping.h"
-#include "commands/dbcommands.h"
#include "commands/defrem.h"
#include "commands/event_trigger.h"
#include "commands/extension.h"
diff --git a/src/backend/catalog/pg_shdepend.c b/src/backend/catalog/pg_shdepend.c
index 32e544da28a..16e3e5c7457 100644
--- a/src/backend/catalog/pg_shdepend.c
+++ b/src/backend/catalog/pg_shdepend.c
@@ -47,7 +47,6 @@
#include "catalog/pg_type.h"
#include "catalog/pg_user_mapping.h"
#include "commands/alter.h"
-#include "commands/dbcommands.h"
#include "commands/defrem.h"
#include "commands/event_trigger.h"
#include "commands/policy.h"
@@ -61,6 +60,7 @@
#include "storage/lmgr.h"
#include "utils/acl.h"
#include "utils/fmgroids.h"
+#include "utils/lsyscache.h"
#include "utils/memutils.h"
#include "utils/syscache.h"
diff --git a/src/backend/commands/analyze.c b/src/backend/commands/analyze.c
index 40d66537ad7..8ea2913d906 100644
--- a/src/backend/commands/analyze.c
+++ b/src/backend/commands/analyze.c
@@ -29,7 +29,6 @@
#include "catalog/index.h"
#include "catalog/indexing.h"
#include "catalog/pg_inherits.h"
-#include "commands/dbcommands.h"
#include "commands/progress.h"
#include "commands/tablecmds.h"
#include "commands/vacuum.h"
diff --git a/src/backend/commands/comment.c b/src/backend/commands/comment.c
index f67a8b95d29..5c783cc61f1 100644
--- a/src/backend/commands/comment.c
+++ b/src/backend/commands/comment.c
@@ -20,10 +20,10 @@
#include "access/table.h"
#include "catalog/indexing.h"
#include "catalog/objectaddress.h"
+#include "catalog/pg_database.h"
#include "catalog/pg_description.h"
#include "catalog/pg_shdescription.h"
#include "commands/comment.h"
-#include "commands/dbcommands.h"
#include "miscadmin.h"
#include "utils/builtins.h"
#include "utils/fmgroids.h"
diff --git a/src/backend/commands/dbcommands.c b/src/backend/commands/dbcommands.c
index 92a396b8406..2793fd83771 100644
--- a/src/backend/commands/dbcommands.c
+++ b/src/backend/commands/dbcommands.c
@@ -64,6 +64,7 @@
#include "utils/acl.h"
#include "utils/builtins.h"
#include "utils/fmgroids.h"
+#include "utils/lsyscache.h"
#include "utils/pg_locale.h"
#include "utils/relmapper.h"
#include "utils/snapmgr.h"
@@ -3205,30 +3206,6 @@ get_database_oid(const char *dbname, bool missing_ok)
/*
- * get_database_name - given a database OID, look up the name
- *
- * Returns a palloc'd string, or NULL if no such database.
- */
-char *
-get_database_name(Oid dbid)
-{
- HeapTuple dbtuple;
- char *result;
-
- dbtuple = SearchSysCache1(DATABASEOID, ObjectIdGetDatum(dbid));
- if (HeapTupleIsValid(dbtuple))
- {
- result = pstrdup(NameStr(((Form_pg_database) GETSTRUCT(dbtuple))->datname));
- ReleaseSysCache(dbtuple);
- }
- else
- result = NULL;
-
- return result;
-}
-
-
-/*
* While dropping a database the pg_database row is marked invalid, but the
* catalog contents still exist. Connections to such a database are not
* allowed.
diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c
index 6f753ab6d7a..ca2bde62e82 100644
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -38,7 +38,6 @@
#include "catalog/pg_tablespace.h"
#include "catalog/pg_type.h"
#include "commands/comment.h"
-#include "commands/dbcommands.h"
#include "commands/defrem.h"
#include "commands/event_trigger.h"
#include "commands/progress.h"
diff --git a/src/backend/commands/publicationcmds.c b/src/backend/commands/publicationcmds.c
index 803c26ab216..3de5687461c 100644
--- a/src/backend/commands/publicationcmds.c
+++ b/src/backend/commands/publicationcmds.c
@@ -29,7 +29,6 @@
#include "catalog/pg_publication.h"
#include "catalog/pg_publication_namespace.h"
#include "catalog/pg_publication_rel.h"
-#include "commands/dbcommands.h"
#include "commands/defrem.h"
#include "commands/event_trigger.h"
#include "commands/publicationcmds.h"
diff --git a/src/backend/commands/schemacmds.c b/src/backend/commands/schemacmds.c
index 0f03d9743d2..3cc1472103a 100644
--- a/src/backend/commands/schemacmds.c
+++ b/src/backend/commands/schemacmds.c
@@ -25,7 +25,6 @@
#include "catalog/pg_authid.h"
#include "catalog/pg_database.h"
#include "catalog/pg_namespace.h"
-#include "commands/dbcommands.h"
#include "commands/event_trigger.h"
#include "commands/schemacmds.h"
#include "miscadmin.h"
@@ -34,6 +33,7 @@
#include "tcop/utility.h"
#include "utils/acl.h"
#include "utils/builtins.h"
+#include "utils/lsyscache.h"
#include "utils/rel.h"
#include "utils/syscache.h"
diff --git a/src/backend/commands/subscriptioncmds.c b/src/backend/commands/subscriptioncmds.c
index 4c01d21b2f3..0d74398faf3 100644
--- a/src/backend/commands/subscriptioncmds.c
+++ b/src/backend/commands/subscriptioncmds.c
@@ -30,7 +30,6 @@
#include "catalog/pg_subscription.h"
#include "catalog/pg_subscription_rel.h"
#include "catalog/pg_type.h"
-#include "commands/dbcommands.h"
#include "commands/defrem.h"
#include "commands/event_trigger.h"
#include "commands/subscriptioncmds.h"
diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c
index 235533ac17f..579ac8d76ae 100644
--- a/src/backend/commands/trigger.c
+++ b/src/backend/commands/trigger.c
@@ -30,7 +30,6 @@
#include "catalog/pg_proc.h"
#include "catalog/pg_trigger.h"
#include "catalog/pg_type.h"
-#include "commands/dbcommands.h"
#include "commands/trigger.h"
#include "executor/executor.h"
#include "miscadmin.h"
diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c
index 65f17101591..a8c8edfac75 100644
--- a/src/backend/optimizer/plan/planner.c
+++ b/src/backend/optimizer/plan/planner.c
@@ -8284,8 +8284,8 @@ generate_setop_child_grouplist(SetOperationStmt *op, List *targetlist)
* the needs of the semijoin represented by sjinfo. If it is not possible
* to identify how to make the data unique, NULL is returned.
*
- * If used at all, this is likely to be called repeatedly on the same rel;
- * So we cache the result.
+ * If used at all, this is likely to be called repeatedly on the same rel,
+ * so we cache the result.
*/
RelOptInfo *
create_unique_paths(PlannerInfo *root, RelOptInfo *rel, SpecialJoinInfo *sjinfo)
@@ -8375,9 +8375,14 @@ create_unique_paths(PlannerInfo *root, RelOptInfo *rel, SpecialJoinInfo *sjinfo)
* variables of the input rel's targetlist. We have to add any such
* expressions to the unique rel's targetlist.
*
- * While in the loop, build the lists of SortGroupClause's that
- * represent the ordering for the sort-based implementation and the
- * grouping for the hash-based implementation.
+ * To complicate matters, some of the values to be unique-ified may be
+ * known redundant by the EquivalenceClass machinery (e.g., because
+ * they have been equated to constants). There is no need to compare
+ * such values during unique-ification, and indeed we had better not
+ * try because the Vars involved may not have propagated as high as
+ * the semijoin's level. We use make_pathkeys_for_sortclauses to
+ * detect such cases, which is a tad inefficient but it doesn't seem
+ * worth building specialized infrastructure for this.
*/
newtlist = make_tlist_from_pathtarget(rel->reltarget);
nextresno = list_length(newtlist) + 1;
@@ -8386,8 +8391,9 @@ create_unique_paths(PlannerInfo *root, RelOptInfo *rel, SpecialJoinInfo *sjinfo)
{
Expr *uniqexpr = lfirst(lc1);
Oid in_oper = lfirst_oid(lc2);
- Oid sortop = InvalidOid;
+ Oid sortop;
TargetEntry *tle;
+ bool made_tle = false;
tle = tlist_member(uniqexpr, newtlist);
if (!tle)
@@ -8398,19 +8404,21 @@ create_unique_paths(PlannerInfo *root, RelOptInfo *rel, SpecialJoinInfo *sjinfo)
false);
newtlist = lappend(newtlist, tle);
nextresno++;
+ made_tle = true;
}
- if (sjinfo->semi_can_btree)
+ /*
+ * Try to build an ORDER BY list to sort the input compatibly. We
+ * do this for each sortable clause even when the clauses are not
+ * all sortable, so that we can detect clauses that are redundant
+ * according to the pathkey machinery.
+ */
+ sortop = get_ordering_op_for_equality_op(in_oper, false);
+ if (OidIsValid(sortop))
{
- /* Create an ORDER BY list to sort the input compatibly */
Oid eqop;
SortGroupClause *sortcl;
- sortop = get_ordering_op_for_equality_op(in_oper, false);
- if (!OidIsValid(sortop)) /* shouldn't happen */
- elog(ERROR, "could not find ordering operator for equality operator %u",
- in_oper);
-
/*
* The Unique node will need equality operators. Normally
* these are the same as the IN clause operators, but if those
@@ -8430,7 +8438,32 @@ create_unique_paths(PlannerInfo *root, RelOptInfo *rel, SpecialJoinInfo *sjinfo)
sortcl->nulls_first = false;
sortcl->hashable = false; /* no need to make this accurate */
sortList = lappend(sortList, sortcl);
+
+ /*
+ * At each step, convert the SortGroupClause list to pathkey
+ * form. If the just-added SortGroupClause is redundant, the
+ * result will be shorter than the SortGroupClause list.
+ */
+ sortPathkeys = make_pathkeys_for_sortclauses(root, sortList,
+ newtlist);
+ if (list_length(sortPathkeys) != list_length(sortList))
+ {
+ /* Drop the redundant SortGroupClause */
+ sortList = list_delete_last(sortList);
+ Assert(list_length(sortPathkeys) == list_length(sortList));
+ /* Undo tlist addition, if we made one */
+ if (made_tle)
+ {
+ newtlist = list_delete_last(newtlist);
+ nextresno--;
+ }
+ /* We need not consider this clause for hashing, either */
+ continue;
+ }
}
+ else if (sjinfo->semi_can_btree) /* shouldn't happen */
+ elog(ERROR, "could not find ordering operator for equality operator %u",
+ in_oper);
if (sjinfo->semi_can_hash)
{
@@ -8460,8 +8493,27 @@ create_unique_paths(PlannerInfo *root, RelOptInfo *rel, SpecialJoinInfo *sjinfo)
}
}
+ /*
+ * Done building the sortPathkeys and groupClause. But the
+ * sortPathkeys are bogus if not all the clauses were sortable.
+ */
+ if (!sjinfo->semi_can_btree)
+ sortPathkeys = NIL;
+
+ /*
+ * It can happen that all the RHS columns are equated to constants.
+ * We'd have to do something special to unique-ify in that case, and
+ * it's such an unlikely-in-the-real-world case that it's not worth
+ * the effort. So just punt if we found no columns to unique-ify.
+ */
+ if (sortPathkeys == NIL && groupClause == NIL)
+ {
+ MemoryContextSwitchTo(oldcontext);
+ return NULL;
+ }
+
+ /* Convert the required targetlist back to PathTarget form */
unique_rel->reltarget = create_pathtarget(root, newtlist);
- sortPathkeys = make_pathkeys_for_sortclauses(root, sortList, newtlist);
}
/* build unique paths based on input rel's pathlist */
diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c
index d66276801c6..e1979a80c19 100644
--- a/src/backend/parser/parse_expr.c
+++ b/src/backend/parser/parse_expr.c
@@ -17,7 +17,6 @@
#include "catalog/pg_aggregate.h"
#include "catalog/pg_type.h"
-#include "commands/dbcommands.h"
#include "miscadmin.h"
#include "nodes/makefuncs.h"
#include "nodes/nodeFuncs.h"
diff --git a/src/backend/parser/parse_target.c b/src/backend/parser/parse_target.c
index 4aba0d9d4d5..905c975d83b 100644
--- a/src/backend/parser/parse_target.c
+++ b/src/backend/parser/parse_target.c
@@ -16,7 +16,6 @@
#include "catalog/namespace.h"
#include "catalog/pg_type.h"
-#include "commands/dbcommands.h"
#include "funcapi.h"
#include "miscadmin.h"
#include "nodes/makefuncs.h"
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index ff96b36d710..dce4c8c45b9 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -77,7 +77,6 @@
#include "catalog/namespace.h"
#include "catalog/pg_database.h"
#include "catalog/pg_namespace.h"
-#include "commands/dbcommands.h"
#include "commands/vacuum.h"
#include "common/int.h"
#include "lib/ilist.h"
diff --git a/src/backend/postmaster/walsummarizer.c b/src/backend/postmaster/walsummarizer.c
index 777c9a8d555..e1f142f20c7 100644
--- a/src/backend/postmaster/walsummarizer.c
+++ b/src/backend/postmaster/walsummarizer.c
@@ -644,7 +644,7 @@ WakeupWalSummarizer(void)
if (WalSummarizerCtl == NULL)
return;
- LWLockAcquire(WALSummarizerLock, LW_EXCLUSIVE);
+ LWLockAcquire(WALSummarizerLock, LW_SHARED);
pgprocno = WalSummarizerCtl->summarizer_pgprocno;
LWLockRelease(WALSummarizerLock);
@@ -685,7 +685,7 @@ WaitForWalSummarization(XLogRecPtr lsn)
/*
* If the LSN summarized on disk has reached the target value, stop.
*/
- LWLockAcquire(WALSummarizerLock, LW_EXCLUSIVE);
+ LWLockAcquire(WALSummarizerLock, LW_SHARED);
summarized_lsn = WalSummarizerCtl->summarized_lsn;
pending_lsn = WalSummarizerCtl->pending_lsn;
LWLockRelease(WALSummarizerLock);
diff --git a/src/backend/replication/logical/slotsync.c b/src/backend/replication/logical/slotsync.c
index 37738440113..caa003cb7b3 100644
--- a/src/backend/replication/logical/slotsync.c
+++ b/src/backend/replication/logical/slotsync.c
@@ -52,7 +52,6 @@
#include "access/xlog_internal.h"
#include "access/xlogrecovery.h"
#include "catalog/pg_database.h"
-#include "commands/dbcommands.h"
#include "libpq/pqsignal.h"
#include "pgstat.h"
#include "postmaster/interrupt.h"
diff --git a/src/backend/replication/walsender.c b/src/backend/replication/walsender.c
index 0855bae3535..e3dce9dc68d 100644
--- a/src/backend/replication/walsender.c
+++ b/src/backend/replication/walsender.c
@@ -60,7 +60,6 @@
#include "backup/basebackup_incremental.h"
#include "catalog/pg_authid.h"
#include "catalog/pg_type.h"
-#include "commands/dbcommands.h"
#include "commands/defrem.h"
#include "funcapi.h"
#include "libpq/libpq.h"
@@ -91,6 +90,7 @@
#include "utils/acl.h"
#include "utils/builtins.h"
#include "utils/guc.h"
+#include "utils/lsyscache.h"
#include "utils/memutils.h"
#include "utils/pg_lsn.h"
#include "utils/pgstat_internal.h"
diff --git a/src/backend/statistics/attribute_stats.c b/src/backend/statistics/attribute_stats.c
index e8241926d2c..1db6a7f784c 100644
--- a/src/backend/statistics/attribute_stats.c
+++ b/src/backend/statistics/attribute_stats.c
@@ -199,7 +199,7 @@ attribute_statistics_update(FunctionCallInfo fcinfo)
if (!PG_ARGISNULL(ATTNUM_ARG))
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("cannot specify both attname and attnum")));
+ errmsg("cannot specify both \"%s\" and \"%s\"", "attname", "attnum")));
attname = TextDatumGetCString(PG_GETARG_DATUM(ATTNAME_ARG));
attnum = get_attnum(reloid, attname);
/* note that this test covers attisdropped cases too: */
@@ -225,7 +225,7 @@ attribute_statistics_update(FunctionCallInfo fcinfo)
{
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("must specify either attname or attnum")));
+ errmsg("must specify either \"%s\" or \"%s\"", "attname", "attnum")));
attname = NULL; /* keep compiler quiet */
attnum = 0;
}
@@ -297,8 +297,9 @@ attribute_statistics_update(FunctionCallInfo fcinfo)
&elemtypid, &elem_eq_opr))
{
ereport(WARNING,
- (errmsg("unable to determine element type of attribute \"%s\"", attname),
- errdetail("Cannot set STATISTIC_KIND_MCELEM or STATISTIC_KIND_DECHIST.")));
+ (errmsg("could not determine element type of column \"%s\"", attname),
+ errdetail("Cannot set %s or %s.",
+ "STATISTIC_KIND_MCELEM", "STATISTIC_KIND_DECHIST")));
elemtypid = InvalidOid;
elem_eq_opr = InvalidOid;
@@ -313,8 +314,9 @@ attribute_statistics_update(FunctionCallInfo fcinfo)
{
ereport(WARNING,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("could not determine less-than operator for attribute \"%s\"", attname),
- errdetail("Cannot set STATISTIC_KIND_HISTOGRAM or STATISTIC_KIND_CORRELATION.")));
+ errmsg("could not determine less-than operator for column \"%s\"", attname),
+ errdetail("Cannot set %s or %s.",
+ "STATISTIC_KIND_HISTOGRAM", "STATISTIC_KIND_CORRELATION")));
do_histogram = false;
do_correlation = false;
@@ -327,8 +329,9 @@ attribute_statistics_update(FunctionCallInfo fcinfo)
{
ereport(WARNING,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("attribute \"%s\" is not a range type", attname),
- errdetail("Cannot set STATISTIC_KIND_RANGE_LENGTH_HISTOGRAM or STATISTIC_KIND_BOUNDS_HISTOGRAM.")));
+ errmsg("column \"%s\" is not a range type", attname),
+ errdetail("Cannot set %s or %s.",
+ "STATISTIC_KIND_RANGE_LENGTH_HISTOGRAM", "STATISTIC_KIND_BOUNDS_HISTOGRAM")));
do_bounds_histogram = false;
do_range_length_histogram = false;
@@ -587,7 +590,7 @@ get_attr_stat_type(Oid reloid, AttrNumber attnum,
if (!HeapTupleIsValid(atup))
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_COLUMN),
- errmsg("attribute %d of relation \"%s\" does not exist",
+ errmsg("column %d of relation \"%s\" does not exist",
attnum, RelationGetRelationName(rel))));
attr = (Form_pg_attribute) GETSTRUCT(atup);
@@ -595,7 +598,7 @@ get_attr_stat_type(Oid reloid, AttrNumber attnum,
if (attr->attisdropped)
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_COLUMN),
- errmsg("attribute %d of relation \"%s\" does not exist",
+ errmsg("column %d of relation \"%s\" does not exist",
attnum, RelationGetRelationName(rel))));
expr = get_attr_expr(rel, attr->attnum);
@@ -729,7 +732,7 @@ text_to_stavalues(const char *staname, FmgrInfo *array_in, Datum d, Oid typid,
{
ereport(WARNING,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("\"%s\" array cannot contain NULL values", staname)));
+ errmsg("\"%s\" array must not contain null values", staname)));
*ok = false;
return (Datum) 0;
}
diff --git a/src/backend/statistics/relation_stats.c b/src/backend/statistics/relation_stats.c
index cd3a75b621a..a59f0c519a4 100644
--- a/src/backend/statistics/relation_stats.c
+++ b/src/backend/statistics/relation_stats.c
@@ -112,7 +112,7 @@ relation_statistics_update(FunctionCallInfo fcinfo)
{
ereport(WARNING,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("reltuples cannot be < -1.0")));
+ errmsg("argument \"%s\" must not be less than -1.0", "reltuples")));
result = false;
}
else
diff --git a/src/backend/statistics/stat_utils.c b/src/backend/statistics/stat_utils.c
index a9a3224efe6..ef7e5168bed 100644
--- a/src/backend/statistics/stat_utils.c
+++ b/src/backend/statistics/stat_utils.c
@@ -41,7 +41,7 @@ stats_check_required_arg(FunctionCallInfo fcinfo,
if (PG_ARGISNULL(argnum))
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("\"%s\" cannot be NULL",
+ errmsg("argument \"%s\" must not be null",
arginfo[argnum].argname)));
}
@@ -68,7 +68,7 @@ stats_check_arg_array(FunctionCallInfo fcinfo,
{
ereport(WARNING,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("\"%s\" cannot be a multidimensional array",
+ errmsg("argument \"%s\" must not be a multidimensional array",
arginfo[argnum].argname)));
return false;
}
@@ -77,7 +77,7 @@ stats_check_arg_array(FunctionCallInfo fcinfo,
{
ereport(WARNING,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("\"%s\" array cannot contain NULL values",
+ errmsg("argument \"%s\" array must not contain null values",
arginfo[argnum].argname)));
return false;
}
@@ -108,7 +108,7 @@ stats_check_arg_pair(FunctionCallInfo fcinfo,
ereport(WARNING,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("\"%s\" must be specified when \"%s\" is specified",
+ errmsg("argument \"%s\" must be specified when argument \"%s\" is specified",
arginfo[nullarg].argname,
arginfo[otherarg].argname)));
@@ -263,7 +263,7 @@ stats_check_arg_type(const char *argname, Oid argtype, Oid expectedtype)
if (argtype != expectedtype)
{
ereport(WARNING,
- (errmsg("argument \"%s\" has type \"%s\", expected type \"%s\"",
+ (errmsg("argument \"%s\" has type %s, expected type %s",
argname, format_type_be(argtype),
format_type_be(expectedtype))));
return false;
@@ -319,11 +319,11 @@ stats_fill_fcinfo_from_arg_pairs(FunctionCallInfo pairs_fcinfo,
if (argnulls[i])
ereport(ERROR,
- (errmsg("name at variadic position %d is NULL", i + 1)));
+ (errmsg("name at variadic position %d is null", i + 1)));
if (types[i] != TEXTOID)
ereport(ERROR,
- (errmsg("name at variadic position %d has type \"%s\", expected type \"%s\"",
+ (errmsg("name at variadic position %d has type %s, expected type %s",
i + 1, format_type_be(types[i]),
format_type_be(TEXTOID))));
diff --git a/src/backend/storage/aio/aio.c b/src/backend/storage/aio/aio.c
index 3643f27ad6e..87d7136a936 100644
--- a/src/backend/storage/aio/aio.c
+++ b/src/backend/storage/aio/aio.c
@@ -275,7 +275,7 @@ pgaio_io_release_resowner(dlist_node *ioh_node, bool on_error)
ResourceOwnerForgetAioHandle(ioh->resowner, &ioh->resowner_node);
ioh->resowner = NULL;
- switch (ioh->state)
+ switch ((PgAioHandleState) ioh->state)
{
case PGAIO_HS_IDLE:
elog(ERROR, "unexpected");
@@ -600,7 +600,7 @@ pgaio_io_wait(PgAioHandle *ioh, uint64 ref_generation)
if (pgaio_io_was_recycled(ioh, ref_generation, &state))
return;
- switch (state)
+ switch ((PgAioHandleState) state)
{
case PGAIO_HS_IDLE:
case PGAIO_HS_HANDED_OUT:
@@ -825,7 +825,7 @@ pgaio_io_wait_for_free(void)
&pgaio_my_backend->in_flight_ios);
uint64 generation = ioh->generation;
- switch (ioh->state)
+ switch ((PgAioHandleState) ioh->state)
{
/* should not be in in-flight list */
case PGAIO_HS_IDLE:
@@ -905,7 +905,7 @@ static const char *
pgaio_io_state_get_name(PgAioHandleState s)
{
#define PGAIO_HS_TOSTR_CASE(sym) case PGAIO_HS_##sym: return #sym
- switch (s)
+ switch ((PgAioHandleState) s)
{
PGAIO_HS_TOSTR_CASE(IDLE);
PGAIO_HS_TOSTR_CASE(HANDED_OUT);
@@ -930,7 +930,7 @@ pgaio_io_get_state_name(PgAioHandle *ioh)
const char *
pgaio_result_status_string(PgAioResultStatus rs)
{
- switch (rs)
+ switch ((PgAioResultStatus) rs)
{
case PGAIO_RS_UNKNOWN:
return "UNKNOWN";
diff --git a/src/backend/storage/aio/aio_funcs.c b/src/backend/storage/aio/aio_funcs.c
index 34f8f632733..d7977387b8f 100644
--- a/src/backend/storage/aio/aio_funcs.c
+++ b/src/backend/storage/aio/aio_funcs.c
@@ -175,7 +175,7 @@ retry:
values[4] = CStringGetTextDatum(pgaio_io_get_op_name(&ioh_copy));
/* columns: details about the IO's operation (offset, length) */
- switch (ioh_copy.op)
+ switch ((PgAioOp) ioh_copy.op)
{
case PGAIO_OP_INVALID:
nulls[5] = true;
diff --git a/src/backend/storage/aio/aio_io.c b/src/backend/storage/aio/aio_io.c
index 520b5077df2..7d11d40284a 100644
--- a/src/backend/storage/aio/aio_io.c
+++ b/src/backend/storage/aio/aio_io.c
@@ -121,7 +121,7 @@ pgaio_io_perform_synchronously(PgAioHandle *ioh)
START_CRIT_SECTION();
/* Perform IO. */
- switch (ioh->op)
+ switch ((PgAioOp) ioh->op)
{
case PGAIO_OP_READV:
pgstat_report_wait_start(WAIT_EVENT_DATA_FILE_READ);
@@ -176,7 +176,7 @@ pgaio_io_get_op_name(PgAioHandle *ioh)
{
Assert(ioh->op >= 0 && ioh->op < PGAIO_OP_COUNT);
- switch (ioh->op)
+ switch ((PgAioOp) ioh->op)
{
case PGAIO_OP_INVALID:
return "invalid";
@@ -198,7 +198,7 @@ pgaio_io_uses_fd(PgAioHandle *ioh, int fd)
{
Assert(ioh->state >= PGAIO_HS_DEFINED);
- switch (ioh->op)
+ switch ((PgAioOp) ioh->op)
{
case PGAIO_OP_READV:
return ioh->op_data.read.fd == fd;
@@ -222,7 +222,7 @@ pgaio_io_get_iovec_length(PgAioHandle *ioh, struct iovec **iov)
*iov = &pgaio_ctl->iovecs[ioh->iovec_off];
- switch (ioh->op)
+ switch ((PgAioOp) ioh->op)
{
case PGAIO_OP_READV:
return ioh->op_data.read.iov_length;
diff --git a/src/backend/storage/aio/method_io_uring.c b/src/backend/storage/aio/method_io_uring.c
index 093a71359ef..bb06da63a8e 100644
--- a/src/backend/storage/aio/method_io_uring.c
+++ b/src/backend/storage/aio/method_io_uring.c
@@ -660,7 +660,7 @@ pgaio_uring_sq_from_io(PgAioHandle *ioh, struct io_uring_sqe *sqe)
{
struct iovec *iov;
- switch (ioh->op)
+ switch ((PgAioOp) ioh->op)
{
case PGAIO_OP_READV:
iov = &pgaio_ctl->iovecs[ioh->iovec_off];
diff --git a/src/backend/storage/ipc/procarray.c b/src/backend/storage/ipc/procarray.c
index bf987aed8d3..200f72c6e25 100644
--- a/src/backend/storage/ipc/procarray.c
+++ b/src/backend/storage/ipc/procarray.c
@@ -54,7 +54,6 @@
#include "access/xlogutils.h"
#include "catalog/catalog.h"
#include "catalog/pg_authid.h"
-#include "commands/dbcommands.h"
#include "miscadmin.h"
#include "pgstat.h"
#include "port/pg_lfind.h"
@@ -62,6 +61,7 @@
#include "storage/procarray.h"
#include "utils/acl.h"
#include "utils/builtins.h"
+#include "utils/lsyscache.h"
#include "utils/rel.h"
#include "utils/snapmgr.h"
diff --git a/src/backend/utils/adt/acl.c b/src/backend/utils/adt/acl.c
index 1213f9106d5..7dadaefdfc1 100644
--- a/src/backend/utils/adt/acl.c
+++ b/src/backend/utils/adt/acl.c
@@ -31,7 +31,6 @@
#include "catalog/pg_proc.h"
#include "catalog/pg_tablespace.h"
#include "catalog/pg_type.h"
-#include "commands/dbcommands.h"
#include "commands/proclang.h"
#include "commands/tablespace.h"
#include "common/hashfn.h"
diff --git a/src/backend/utils/adt/dbsize.c b/src/backend/utils/adt/dbsize.c
index 3a059f4ace0..894d226541f 100644
--- a/src/backend/utils/adt/dbsize.c
+++ b/src/backend/utils/adt/dbsize.c
@@ -19,12 +19,12 @@
#include "catalog/pg_authid.h"
#include "catalog/pg_database.h"
#include "catalog/pg_tablespace.h"
-#include "commands/dbcommands.h"
#include "commands/tablespace.h"
#include "miscadmin.h"
#include "storage/fd.h"
#include "utils/acl.h"
#include "utils/builtins.h"
+#include "utils/lsyscache.h"
#include "utils/numeric.h"
#include "utils/rel.h"
#include "utils/relfilenumbermap.h"
diff --git a/src/backend/utils/adt/misc.c b/src/backend/utils/adt/misc.c
index 6fcfd031428..6c5e3438447 100644
--- a/src/backend/utils/adt/misc.c
+++ b/src/backend/utils/adt/misc.c
@@ -26,7 +26,6 @@
#include "catalog/pg_tablespace.h"
#include "catalog/pg_type.h"
#include "catalog/system_fk_info.h"
-#include "commands/dbcommands.h"
#include "commands/tablespace.h"
#include "common/keywords.h"
#include "funcapi.h"
diff --git a/src/backend/utils/adt/regproc.c b/src/backend/utils/adt/regproc.c
index b8bbe95e82e..af17a3421a0 100644
--- a/src/backend/utils/adt/regproc.c
+++ b/src/backend/utils/adt/regproc.c
@@ -25,12 +25,12 @@
#include "catalog/namespace.h"
#include "catalog/pg_class.h"
#include "catalog/pg_collation.h"
+#include "catalog/pg_database.h"
#include "catalog/pg_operator.h"
#include "catalog/pg_proc.h"
#include "catalog/pg_ts_config.h"
#include "catalog/pg_ts_dict.h"
#include "catalog/pg_type.h"
-#include "commands/dbcommands.h"
#include "lib/stringinfo.h"
#include "mb/pg_wchar.h"
#include "miscadmin.h"
diff --git a/src/backend/utils/adt/xml.c b/src/backend/utils/adt/xml.c
index 182e8f75db7..7b7396cdf83 100644
--- a/src/backend/utils/adt/xml.c
+++ b/src/backend/utils/adt/xml.c
@@ -84,7 +84,6 @@
#include "catalog/namespace.h"
#include "catalog/pg_class.h"
#include "catalog/pg_type.h"
-#include "commands/dbcommands.h"
#include "executor/spi.h"
#include "executor/tablefunc.h"
#include "fmgr.h"
diff --git a/src/backend/utils/cache/lsyscache.c b/src/backend/utils/cache/lsyscache.c
index 032bb6222c4..fa7cd7e06a7 100644
--- a/src/backend/utils/cache/lsyscache.c
+++ b/src/backend/utils/cache/lsyscache.c
@@ -26,6 +26,7 @@
#include "catalog/pg_class.h"
#include "catalog/pg_collation.h"
#include "catalog/pg_constraint.h"
+#include "catalog/pg_database.h"
#include "catalog/pg_index.h"
#include "catalog/pg_language.h"
#include "catalog/pg_namespace.h"
@@ -1247,6 +1248,32 @@ get_constraint_type(Oid conoid)
return contype;
}
+/* ---------- DATABASE CACHE ---------- */
+
+/*
+ * get_database_name - given a database OID, look up the name
+ *
+ * Returns a palloc'd string, or NULL if no such database.
+ */
+char *
+get_database_name(Oid dbid)
+{
+ HeapTuple dbtuple;
+ char *result;
+
+ dbtuple = SearchSysCache1(DATABASEOID, ObjectIdGetDatum(dbid));
+ if (HeapTupleIsValid(dbtuple))
+ {
+ result = pstrdup(NameStr(((Form_pg_database) GETSTRUCT(dbtuple))->datname));
+ ReleaseSysCache(dbtuple);
+ }
+ else
+ result = NULL;
+
+ return result;
+}
+
+
/* ---------- LANGUAGE CACHE ---------- */
char *
diff --git a/src/include/catalog/pg_database.h b/src/include/catalog/pg_database.h
index 54f0d38c9c9..97bc1874508 100644
--- a/src/include/catalog/pg_database.h
+++ b/src/include/catalog/pg_database.h
@@ -123,6 +123,7 @@ DECLARE_OID_DEFINING_MACRO(PostgresDbOid, 5);
*/
#define DATCONNLIMIT_INVALID_DB -2
+extern Oid get_database_oid(const char *dbname, bool missing_ok);
extern bool database_is_invalid_form(Form_pg_database datform);
extern bool database_is_invalid_oid(Oid dboid);
diff --git a/src/include/commands/dbcommands.h b/src/include/commands/dbcommands.h
index 524ac6d97e8..d48ab6d7d7d 100644
--- a/src/include/commands/dbcommands.h
+++ b/src/include/commands/dbcommands.h
@@ -14,9 +14,7 @@
#ifndef DBCOMMANDS_H
#define DBCOMMANDS_H
-#include "access/xlogreader.h"
#include "catalog/objectaddress.h"
-#include "lib/stringinfo.h"
#include "parser/parse_node.h"
extern Oid createdb(ParseState *pstate, const CreatedbStmt *stmt);
@@ -28,8 +26,6 @@ extern ObjectAddress AlterDatabaseRefreshColl(AlterDatabaseRefreshCollStmt *stmt
extern Oid AlterDatabaseSet(AlterDatabaseSetStmt *stmt);
extern ObjectAddress AlterDatabaseOwner(const char *dbname, Oid newOwnerId);
-extern Oid get_database_oid(const char *dbname, bool missing_ok);
-extern char *get_database_name(Oid dbid);
extern bool have_createdb_privilege(void);
extern void check_encoding_locale_matches(int encoding, const char *collate, const char *ctype);
diff --git a/src/include/storage/aio_internal.h b/src/include/storage/aio_internal.h
index 2d37a243abe..b4de30f2ec1 100644
--- a/src/include/storage/aio_internal.h
+++ b/src/include/storage/aio_internal.h
@@ -92,17 +92,23 @@ typedef enum PgAioHandleState
struct ResourceOwnerData;
-/* typedef is in aio_types.h */
+/*
+ * Typedef is in aio_types.h
+ *
+ * We don't use the underlying enums for state, target and op to avoid wasting
+ * space. We tried using bitfields, but several compilers generate rather
+ * horrid code for that.
+ */
struct PgAioHandle
{
/* all state updates should go through pgaio_io_update_state() */
- PgAioHandleState state:8;
+ uint8 state;
/* what are we operating on */
- PgAioTargetID target:8;
+ uint8 target;
/* which IO operation */
- PgAioOp op:8;
+ uint8 op;
/* bitfield of PgAioHandleFlags */
uint8 flags;
diff --git a/src/include/utils/lsyscache.h b/src/include/utils/lsyscache.h
index fa7c7e0323b..c65cee4f24c 100644
--- a/src/include/utils/lsyscache.h
+++ b/src/include/utils/lsyscache.h
@@ -104,7 +104,7 @@ extern bool get_collation_isdeterministic(Oid colloid);
extern char *get_constraint_name(Oid conoid);
extern Oid get_constraint_index(Oid conoid);
extern char get_constraint_type(Oid conoid);
-
+extern char *get_database_name(Oid dbid);
extern char *get_language_name(Oid langoid, bool missing_ok);
extern Oid get_opclass_family(Oid opclass);
extern Oid get_opclass_input_type(Oid opclass);
diff --git a/src/test/modules/worker_spi/worker_spi.c b/src/test/modules/worker_spi/worker_spi.c
index 9c53d896b6a..bea8339f464 100644
--- a/src/test/modules/worker_spi/worker_spi.c
+++ b/src/test/modules/worker_spi/worker_spi.c
@@ -30,7 +30,7 @@
/* these headers are used by this particular worker's code */
#include "access/xact.h"
-#include "commands/dbcommands.h"
+#include "catalog/pg_database.h"
#include "executor/spi.h"
#include "fmgr.h"
#include "lib/stringinfo.h"
diff --git a/src/test/regress/expected/aggregates.out b/src/test/regress/expected/aggregates.out
index 7319945ffe3..c35288eecde 100644
--- a/src/test/regress/expected/aggregates.out
+++ b/src/test/regress/expected/aggregates.out
@@ -3398,26 +3398,6 @@ select v||'a', case when v||'a' = 'aa' then 1 else 0 end, count(*)
ba | 0 | 1
(2 rows)
--- Make sure that generation of HashAggregate for uniqification purposes
--- does not lead to array overflow due to unexpected duplicate hash keys
--- see CAFeeJoKKu0u+A_A9R9316djW-YW3-+Gtgvy3ju655qRHR3jtdA@mail.gmail.com
-set enable_memoize to off;
-explain (costs off)
- select 1 from tenk1
- where (hundred, thousand) in (select twothousand, twothousand from onek);
- QUERY PLAN
--------------------------------------------------------------
- Hash Join
- Hash Cond: (tenk1.hundred = onek.twothousand)
- -> Seq Scan on tenk1
- Filter: (hundred = thousand)
- -> Hash
- -> HashAggregate
- Group Key: onek.twothousand, onek.twothousand
- -> Seq Scan on onek
-(8 rows)
-
-reset enable_memoize;
--
-- Hash Aggregation Spill tests
--
diff --git a/src/test/regress/expected/join.out b/src/test/regress/expected/join.out
index 98b05c94a11..b26b8c5bdbe 100644
--- a/src/test/regress/expected/join.out
+++ b/src/test/regress/expected/join.out
@@ -3222,6 +3222,24 @@ where b.unique2 is null;
-> Index Only Scan using tenk1_unique2 on tenk1 b
(5 rows)
+-- check that we avoid de-duplicating columns redundantly
+set enable_memoize to off;
+explain (costs off)
+select 1 from tenk1
+where (hundred, thousand) in (select twothousand, twothousand from onek);
+ QUERY PLAN
+-------------------------------------------------
+ Hash Join
+ Hash Cond: (tenk1.hundred = onek.twothousand)
+ -> Seq Scan on tenk1
+ Filter: (hundred = thousand)
+ -> Hash
+ -> HashAggregate
+ Group Key: onek.twothousand
+ -> Seq Scan on onek
+(8 rows)
+
+reset enable_memoize;
--
-- regression test for bogus RTE_GROUP entries
--
@@ -6501,6 +6519,68 @@ where t1.a = s.c;
(0 rows)
rollback;
+-- check handling of semijoins after join removal: we must suppress
+-- unique-ification of known-constant values
+begin;
+create temp table t (a int unique, b int);
+insert into t values (1, 2);
+explain (verbose, costs off)
+select t1.a from t t1
+ left join t t2 on t1.a = t2.a
+ join t t3 on true
+where exists (select 1 from t t4
+ join t t5 on t4.b = t5.b
+ join t t6 on t5.b = t6.b
+ where t1.a = t4.a and t3.a = t5.a and t4.a = 1);
+ QUERY PLAN
+------------------------------------------------------------------------------------
+ Nested Loop
+ Output: t1.a
+ Inner Unique: true
+ -> Nested Loop
+ Output: t1.a, t5.a
+ -> Index Only Scan using t_a_key on pg_temp.t t1
+ Output: t1.a
+ Index Cond: (t1.a = 1)
+ -> HashAggregate
+ Output: t5.a
+ Group Key: t5.a
+ -> Hash Join
+ Output: t5.a
+ Hash Cond: (t6.b = t4.b)
+ -> Seq Scan on pg_temp.t t6
+ Output: t6.a, t6.b
+ -> Hash
+ Output: t4.b, t5.b, t5.a
+ -> Hash Join
+ Output: t4.b, t5.b, t5.a
+ Inner Unique: true
+ Hash Cond: (t5.b = t4.b)
+ -> Seq Scan on pg_temp.t t5
+ Output: t5.a, t5.b
+ -> Hash
+ Output: t4.b, t4.a
+ -> Index Scan using t_a_key on pg_temp.t t4
+ Output: t4.b, t4.a
+ Index Cond: (t4.a = 1)
+ -> Index Only Scan using t_a_key on pg_temp.t t3
+ Output: t3.a
+ Index Cond: (t3.a = t5.a)
+(32 rows)
+
+select t1.a from t t1
+ left join t t2 on t1.a = t2.a
+ join t t3 on true
+where exists (select 1 from t t4
+ join t t5 on t4.b = t5.b
+ join t t6 on t5.b = t6.b
+ where t1.a = t4.a and t3.a = t5.a and t4.a = 1);
+ a
+---
+ 1
+(1 row)
+
+rollback;
-- test cases where we can remove a join, but not a PHV computed at it
begin;
create temp table t (a int unique, b int);
diff --git a/src/test/regress/expected/stats_import.out b/src/test/regress/expected/stats_import.out
index 48d6392b4ad..9e615ccd0af 100644
--- a/src/test/regress/expected/stats_import.out
+++ b/src/test/regress/expected/stats_import.out
@@ -50,26 +50,26 @@ SELECT pg_clear_relation_stats('stats_import', 'test');
SELECT pg_catalog.pg_restore_relation_stats(
'relname', 'test',
'relpages', 17::integer);
-ERROR: "schemaname" cannot be NULL
+ERROR: argument "schemaname" must not be null
-- error: relname missing
SELECT pg_catalog.pg_restore_relation_stats(
'schemaname', 'stats_import',
'relpages', 17::integer);
-ERROR: "relname" cannot be NULL
+ERROR: argument "relname" must not be null
--- error: schemaname is wrong type
SELECT pg_catalog.pg_restore_relation_stats(
'schemaname', 3.6::float,
'relname', 'test',
'relpages', 17::integer);
-WARNING: argument "schemaname" has type "double precision", expected type "text"
-ERROR: "schemaname" cannot be NULL
+WARNING: argument "schemaname" has type double precision, expected type text
+ERROR: argument "schemaname" must not be null
--- error: relname is wrong type
SELECT pg_catalog.pg_restore_relation_stats(
'schemaname', 'stats_import',
'relname', 0::oid,
'relpages', 17::integer);
-WARNING: argument "relname" has type "oid", expected type "text"
-ERROR: "relname" cannot be NULL
+WARNING: argument "relname" has type oid, expected type text
+ERROR: argument "relname" must not be null
-- error: relation not found
SELECT pg_catalog.pg_restore_relation_stats(
'schemaname', 'stats_import',
@@ -88,7 +88,7 @@ SELECT pg_restore_relation_stats(
'schemaname', 'stats_import',
'relname', 'test',
NULL, '17'::integer);
-ERROR: name at variadic position 5 is NULL
+ERROR: name at variadic position 5 is null
-- starting stats
SELECT relpages, reltuples, relallvisible, relallfrozen
FROM pg_class
@@ -286,7 +286,7 @@ SELECT pg_restore_relation_stats(
'reltuples', 400.0::real,
'relallvisible', 4::integer,
'relallfrozen', 3::integer);
-WARNING: argument "relpages" has type "text", expected type "integer"
+WARNING: argument "relpages" has type text, expected type integer
pg_restore_relation_stats
---------------------------
f
@@ -358,7 +358,7 @@ SELECT pg_catalog.pg_restore_attribute_stats(
'attname', 'id',
'inherited', false::boolean,
'null_frac', 0.1::real);
-ERROR: "schemaname" cannot be NULL
+ERROR: argument "schemaname" must not be null
-- error: schema does not exist
SELECT pg_catalog.pg_restore_attribute_stats(
'schemaname', 'nope',
@@ -373,7 +373,7 @@ SELECT pg_catalog.pg_restore_attribute_stats(
'attname', 'id',
'inherited', false::boolean,
'null_frac', 0.1::real);
-ERROR: "relname" cannot be NULL
+ERROR: argument "relname" must not be null
-- error: relname does not exist
SELECT pg_catalog.pg_restore_attribute_stats(
'schemaname', 'stats_import',
@@ -389,7 +389,7 @@ SELECT pg_catalog.pg_restore_attribute_stats(
'attname', 'id',
'inherited', false::boolean,
'null_frac', 0.1::real);
-ERROR: "relname" cannot be NULL
+ERROR: argument "relname" must not be null
-- error: NULL attname
SELECT pg_catalog.pg_restore_attribute_stats(
'schemaname', 'stats_import',
@@ -397,7 +397,7 @@ SELECT pg_catalog.pg_restore_attribute_stats(
'attname', NULL,
'inherited', false::boolean,
'null_frac', 0.1::real);
-ERROR: must specify either attname or attnum
+ERROR: must specify either "attname" or "attnum"
-- error: attname doesn't exist
SELECT pg_catalog.pg_restore_attribute_stats(
'schemaname', 'stats_import',
@@ -416,14 +416,14 @@ SELECT pg_catalog.pg_restore_attribute_stats(
'attnum', 1::smallint,
'inherited', false::boolean,
'null_frac', 0.1::real);
-ERROR: cannot specify both attname and attnum
+ERROR: cannot specify both "attname" and "attnum"
-- error: neither attname nor attnum
SELECT pg_catalog.pg_restore_attribute_stats(
'schemaname', 'stats_import',
'relname', 'test',
'inherited', false::boolean,
'null_frac', 0.1::real);
-ERROR: must specify either attname or attnum
+ERROR: must specify either "attname" or "attnum"
-- error: attribute is system column
SELECT pg_catalog.pg_restore_attribute_stats(
'schemaname', 'stats_import',
@@ -439,7 +439,7 @@ SELECT pg_catalog.pg_restore_attribute_stats(
'attname', 'id',
'inherited', NULL::boolean,
'null_frac', 0.1::real);
-ERROR: "inherited" cannot be NULL
+ERROR: argument "inherited" must not be null
-- ok: just the fixed values, with version, no stakinds
SELECT pg_catalog.pg_restore_attribute_stats(
'schemaname', 'stats_import',
@@ -527,7 +527,7 @@ SELECT pg_catalog.pg_restore_attribute_stats(
'null_frac', 0.21::real,
'most_common_freqs', '{0.1,0.2,0.3}'::real[]
);
-WARNING: "most_common_vals" must be specified when "most_common_freqs" is specified
+WARNING: argument "most_common_vals" must be specified when argument "most_common_freqs" is specified
pg_restore_attribute_stats
----------------------------
f
@@ -553,7 +553,7 @@ SELECT pg_catalog.pg_restore_attribute_stats(
'null_frac', 0.21::real,
'most_common_vals', '{1,2,3}'::text
);
-WARNING: "most_common_freqs" must be specified when "most_common_vals" is specified
+WARNING: argument "most_common_freqs" must be specified when argument "most_common_vals" is specified
pg_restore_attribute_stats
----------------------------
f
@@ -580,8 +580,8 @@ SELECT pg_catalog.pg_restore_attribute_stats(
'most_common_vals', '{2,1,3}'::text,
'most_common_freqs', '{0.2,0.1}'::double precision[]
);
-WARNING: argument "most_common_freqs" has type "double precision[]", expected type "real[]"
-WARNING: "most_common_freqs" must be specified when "most_common_vals" is specified
+WARNING: argument "most_common_freqs" has type double precision[], expected type real[]
+WARNING: argument "most_common_freqs" must be specified when argument "most_common_vals" is specified
pg_restore_attribute_stats
----------------------------
f
@@ -659,7 +659,7 @@ SELECT pg_catalog.pg_restore_attribute_stats(
'null_frac', 0.24::real,
'histogram_bounds', '{1,NULL,3,4}'::text
);
-WARNING: "histogram_bounds" array cannot contain NULL values
+WARNING: "histogram_bounds" array must not contain null values
pg_restore_attribute_stats
----------------------------
f
@@ -709,7 +709,7 @@ SELECT pg_catalog.pg_restore_attribute_stats(
'null_frac', 0.25::real,
'elem_count_histogram', '{1,1,NULL,1,1,1,1,1}'::real[]
);
-WARNING: "elem_count_histogram" array cannot contain NULL values
+WARNING: argument "elem_count_histogram" array must not contain null values
pg_restore_attribute_stats
----------------------------
f
@@ -761,7 +761,7 @@ SELECT pg_catalog.pg_restore_attribute_stats(
'range_empty_frac', 0.5::real,
'range_length_histogram', '{399,499,Infinity}'::text
);
-WARNING: attribute "id" is not a range type
+WARNING: column "id" is not a range type
DETAIL: Cannot set STATISTIC_KIND_RANGE_LENGTH_HISTOGRAM or STATISTIC_KIND_BOUNDS_HISTOGRAM.
pg_restore_attribute_stats
----------------------------
@@ -788,7 +788,7 @@ SELECT pg_catalog.pg_restore_attribute_stats(
'null_frac', 0.28::real,
'range_length_histogram', '{399,499,Infinity}'::text
);
-WARNING: "range_empty_frac" must be specified when "range_length_histogram" is specified
+WARNING: argument "range_empty_frac" must be specified when argument "range_length_histogram" is specified
pg_restore_attribute_stats
----------------------------
f
@@ -814,7 +814,7 @@ SELECT pg_catalog.pg_restore_attribute_stats(
'null_frac', 0.29::real,
'range_empty_frac', 0.5::real
);
-WARNING: "range_length_histogram" must be specified when "range_empty_frac" is specified
+WARNING: argument "range_length_histogram" must be specified when argument "range_empty_frac" is specified
pg_restore_attribute_stats
----------------------------
f
@@ -865,7 +865,7 @@ SELECT pg_catalog.pg_restore_attribute_stats(
'null_frac', 0.31::real,
'range_bounds_histogram', '{"[-1,1)","[0,4)","[1,4)","[1,100)"}'::text
);
-WARNING: attribute "id" is not a range type
+WARNING: column "id" is not a range type
DETAIL: Cannot set STATISTIC_KIND_RANGE_LENGTH_HISTOGRAM or STATISTIC_KIND_BOUNDS_HISTOGRAM.
pg_restore_attribute_stats
----------------------------
@@ -917,7 +917,7 @@ SELECT pg_catalog.pg_restore_attribute_stats(
'most_common_elems', '{3,1}'::text,
'most_common_elem_freqs', '{0.3,0.2,0.2,0.3,0.0}'::real[]
);
-WARNING: unable to determine element type of attribute "arange"
+WARNING: could not determine element type of column "arange"
DETAIL: Cannot set STATISTIC_KIND_MCELEM or STATISTIC_KIND_DECHIST.
pg_restore_attribute_stats
----------------------------
@@ -945,7 +945,7 @@ SELECT pg_catalog.pg_restore_attribute_stats(
'most_common_elems', '{1,3}'::text,
'most_common_elem_freqs', '{0.3,0.2,0.2,0.3,0.0}'::real[]
);
-WARNING: unable to determine element type of attribute "id"
+WARNING: could not determine element type of column "id"
DETAIL: Cannot set STATISTIC_KIND_MCELEM or STATISTIC_KIND_DECHIST.
pg_restore_attribute_stats
----------------------------
@@ -972,7 +972,7 @@ SELECT pg_catalog.pg_restore_attribute_stats(
'null_frac', 0.34::real,
'most_common_elems', '{one,two}'::text
);
-WARNING: "most_common_elem_freqs" must be specified when "most_common_elems" is specified
+WARNING: argument "most_common_elem_freqs" must be specified when argument "most_common_elems" is specified
pg_restore_attribute_stats
----------------------------
f
@@ -998,7 +998,7 @@ SELECT pg_catalog.pg_restore_attribute_stats(
'null_frac', 0.35::real,
'most_common_elem_freqs', '{0.3,0.2,0.2,0.3}'::real[]
);
-WARNING: "most_common_elems" must be specified when "most_common_elem_freqs" is specified
+WARNING: argument "most_common_elems" must be specified when argument "most_common_elem_freqs" is specified
pg_restore_attribute_stats
----------------------------
f
@@ -1049,7 +1049,7 @@ SELECT pg_catalog.pg_restore_attribute_stats(
'null_frac', 0.36::real,
'elem_count_histogram', '{1,1,1,1,1,1,1,1,1,1}'::real[]
);
-WARNING: unable to determine element type of attribute "id"
+WARNING: could not determine element type of column "id"
DETAIL: Cannot set STATISTIC_KIND_MCELEM or STATISTIC_KIND_DECHIST.
pg_restore_attribute_stats
----------------------------
diff --git a/src/test/regress/sql/aggregates.sql b/src/test/regress/sql/aggregates.sql
index dde85d0dfb2..62540b1ffa4 100644
--- a/src/test/regress/sql/aggregates.sql
+++ b/src/test/regress/sql/aggregates.sql
@@ -1510,15 +1510,6 @@ select v||'a', case when v||'a' = 'aa' then 1 else 0 end, count(*)
from unnest(array['a','b']) u(v)
group by v||'a' order by 1;
--- Make sure that generation of HashAggregate for uniqification purposes
--- does not lead to array overflow due to unexpected duplicate hash keys
--- see CAFeeJoKKu0u+A_A9R9316djW-YW3-+Gtgvy3ju655qRHR3jtdA@mail.gmail.com
-set enable_memoize to off;
-explain (costs off)
- select 1 from tenk1
- where (hundred, thousand) in (select twothousand, twothousand from onek);
-reset enable_memoize;
-
--
-- Hash Aggregation Spill tests
--
diff --git a/src/test/regress/sql/join.sql b/src/test/regress/sql/join.sql
index 5f0a475894d..bccd171afb6 100644
--- a/src/test/regress/sql/join.sql
+++ b/src/test/regress/sql/join.sql
@@ -839,6 +839,13 @@ explain (costs off)
select a.* from tenk1 a left join tenk1 b on a.unique1 = b.unique2
where b.unique2 is null;
+-- check that we avoid de-duplicating columns redundantly
+set enable_memoize to off;
+explain (costs off)
+select 1 from tenk1
+where (hundred, thousand) in (select twothousand, twothousand from onek);
+reset enable_memoize;
+
--
-- regression test for bogus RTE_GROUP entries
--
@@ -2420,6 +2427,32 @@ where t1.a = s.c;
rollback;
+-- check handling of semijoins after join removal: we must suppress
+-- unique-ification of known-constant values
+begin;
+
+create temp table t (a int unique, b int);
+insert into t values (1, 2);
+
+explain (verbose, costs off)
+select t1.a from t t1
+ left join t t2 on t1.a = t2.a
+ join t t3 on true
+where exists (select 1 from t t4
+ join t t5 on t4.b = t5.b
+ join t t6 on t5.b = t6.b
+ where t1.a = t4.a and t3.a = t5.a and t4.a = 1);
+
+select t1.a from t t1
+ left join t t2 on t1.a = t2.a
+ join t t3 on true
+where exists (select 1 from t t4
+ join t t5 on t4.b = t5.b
+ join t t6 on t5.b = t6.b
+ where t1.a = t4.a and t3.a = t5.a and t4.a = 1);
+
+rollback;
+
-- test cases where we can remove a join, but not a PHV computed at it
begin;