summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Haas2024-08-30 14:27:31 +0000
committerRobert Haas2024-08-30 18:14:15 +0000
commit868dc508088e734021099e5716f9e6da4de8337f (patch)
treeb77313f7980caf8e7e950df5d4fd16ff4458d567
parent58d495a03f78d157f2d13a355d21a8bccf2c9de8 (diff)
New contrib module: alphabet_join.
This forces joins to be done alphabetically by alias name. It demonstrates that join_path_setup_hook is sufficient to control the join order, and is not intended for commit.
-rw-r--r--contrib/Makefile1
-rw-r--r--contrib/alphabet_join/Makefile17
-rw-r--r--contrib/alphabet_join/alphabet_join.c74
-rw-r--r--contrib/alphabet_join/meson.build12
-rw-r--r--contrib/meson.build1
5 files changed, 105 insertions, 0 deletions
diff --git a/contrib/Makefile b/contrib/Makefile
index abd780f277..b342261669 100644
--- a/contrib/Makefile
+++ b/contrib/Makefile
@@ -5,6 +5,7 @@ top_builddir = ..
include $(top_builddir)/src/Makefile.global
SUBDIRS = \
+ alphabet_join \
amcheck \
auth_delay \
auto_explain \
diff --git a/contrib/alphabet_join/Makefile b/contrib/alphabet_join/Makefile
new file mode 100644
index 0000000000..204bc35b3d
--- /dev/null
+++ b/contrib/alphabet_join/Makefile
@@ -0,0 +1,17 @@
+# contrib/alphabet_join/Makefile
+
+MODULE_big = alphabet_join
+OBJS = \
+ $(WIN32RES) \
+ alphabet_join.o
+
+ifdef USE_PGXS
+PG_CONFIG = pg_config
+PGXS := $(shell $(PG_CONFIG) --pgxs)
+include $(PGXS)
+else
+subdir = contrib/alphabet_join
+top_builddir = ../..
+include $(top_builddir)/src/Makefile.global
+include $(top_srcdir)/contrib/contrib-global.mk
+endif
diff --git a/contrib/alphabet_join/alphabet_join.c b/contrib/alphabet_join/alphabet_join.c
new file mode 100644
index 0000000000..6794bded04
--- /dev/null
+++ b/contrib/alphabet_join/alphabet_join.c
@@ -0,0 +1,74 @@
+/*-------------------------------------------------------------------------
+ *
+ * alphabet_join.c
+ * force tables to be joined in alphabetical order by alias name.
+ * this is just a demonstration, so we don't worry about collation here.
+ *
+ * Copyright (c) 2016-2024, PostgreSQL Global Development Group
+ *
+ * contrib/alphabet_join/alphabet_join.c
+ *-------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include "fmgr.h"
+#include "optimizer/paths.h"
+#include "parser/parsetree.h"
+
+static void aj_join_path_setup_hook(PlannerInfo *root,
+ RelOptInfo *joinrel,
+ RelOptInfo *outerrel,
+ RelOptInfo *innerrel,
+ JoinType jointype,
+ JoinPathExtraData *extra);
+
+static join_path_setup_hook_type prev_join_path_setup_hook = NULL;
+
+PG_MODULE_MAGIC;
+
+void
+_PG_init(void)
+{
+ prev_join_path_setup_hook = join_path_setup_hook;
+ join_path_setup_hook = aj_join_path_setup_hook;
+}
+
+static void
+aj_join_path_setup_hook(PlannerInfo *root, RelOptInfo *joinrel,
+ RelOptInfo *outerrel, RelOptInfo *innerrel,
+ JoinType jointype, JoinPathExtraData *extra)
+{
+ int relid;
+ char *outerrel_last = NULL;
+
+ /* Find the alphabetically last outerrel. */
+ relid = -1;
+ while ((relid = bms_next_member(outerrel->relids, relid)) >= 0)
+ {
+ RangeTblEntry *rte = planner_rt_fetch(relid, root);
+
+ Assert(rte->eref != NULL && rte->eref->aliasname != NULL);
+
+ if (outerrel_last == NULL ||
+ strcmp(outerrel_last, rte->eref->aliasname) < 0)
+ outerrel_last = rte->eref->aliasname;
+ }
+
+ /*
+ * If any innerrel is alphabetically before the last outerrel, then
+ * this join order is not alphabetical and should be rejected.
+ */
+ relid = -1;
+ while ((relid = bms_next_member(innerrel->relids, relid)) >= 0)
+ {
+ RangeTblEntry *rte = planner_rt_fetch(relid, root);
+
+ Assert(rte->eref != NULL && rte->eref->aliasname != NULL);
+
+ if (strcmp(rte->eref->aliasname, outerrel_last) < 0)
+ {
+ extra->jsa_mask = 0;
+ return;
+ }
+ }
+}
diff --git a/contrib/alphabet_join/meson.build b/contrib/alphabet_join/meson.build
new file mode 100644
index 0000000000..437cb14af5
--- /dev/null
+++ b/contrib/alphabet_join/meson.build
@@ -0,0 +1,12 @@
+# Copyright (c) 2022-2024, PostgreSQL Global Development Group
+
+alphabet_join_sources = files(
+ 'alphabet_join.c',
+)
+
+alphabet_join = shared_module('alphabet_join',
+ alphabet_join_sources,
+ kwargs: contrib_mod_args,
+)
+
+contrib_targets += alphabet_join
diff --git a/contrib/meson.build b/contrib/meson.build
index 14a8906865..4372242c8f 100644
--- a/contrib/meson.build
+++ b/contrib/meson.build
@@ -12,6 +12,7 @@ contrib_doc_args = {
'install_dir': contrib_doc_dir,
}
+subdir('alphabet_join')
subdir('amcheck')
subdir('auth_delay')
subdir('auto_explain')