Files
bsdports/data/postgresql11/files/patch-s00014-optimizer_utils.patch
2019-12-26 07:26:06 +00:00

269 lines
6.8 KiB
Diff

diff --git a/src/backend/optimizer/util/relnode.c src/backend/optimizer/util/relnode.c
index 284215a7173..b80ef8e55b8 100644
--- a/src/backend/optimizer/util/relnode.c
+++ src/backend/optimizer/util/relnode.c
@@ -1030,12 +1030,60 @@
joinrel->joininfo = result;
}
+typedef struct UniquePtrList {
+ List *unique_list;
+ HTAB *h;
+} UniquePtrList;
+
+static void
+addUniquePtrList(UniquePtrList *upl, void *v)
+{
+ if (upl->h != NULL || list_length(upl->unique_list) > 32)
+ {
+ bool found;
+
+ if (upl->h == NULL)
+ {
+ HASHCTL hash_ctl;
+ ListCell *l;
+
+ MemSet(&hash_ctl, 0, sizeof(hash_ctl));
+
+ hash_ctl.keysize = sizeof(void*);
+ hash_ctl.entrysize = sizeof(void*);
+
+ upl->h = hash_create("UniquePtrList storage", 64, &hash_ctl,
+ HASH_BLOBS | HASH_ELEM);
+
+ foreach(l, upl->unique_list)
+ {
+ void *k = lfirst(l);
+
+ hash_search(upl->h, &k, HASH_ENTER, &found);
+ Assert(found == false);
+ }
+ }
+
+ hash_search(upl->h, &v, HASH_ENTER, &found);
+ if (found == false)
+ upl->unique_list = lappend(upl->unique_list, v);
+ }
+ else
+ {
+ upl->unique_list = list_append_unique_ptr(upl->unique_list, v);
+ }
+}
+
static List *
subbuild_joinrel_restrictlist(Relids joinrelids,
List *joininfo_list,
List *new_restrictlist)
{
ListCell *l;
+ UniquePtrList upl;
+
+ memset(&upl, 0, sizeof(upl));
+ upl.unique_list = new_restrictlist;
foreach(l, joininfo_list)
{
@@ -1050,7 +1098,7 @@
* different joinlists will have been multiply-linked rather than
* copied, pointer equality should be a sufficient test.)
*/
- new_restrictlist = list_append_unique_ptr(new_restrictlist, rinfo);
+ addUniquePtrList(&upl, rinfo);
}
else
{
@@ -1061,7 +1109,8 @@
}
}
- return new_restrictlist;
+ hash_destroy(upl.h);
+ return upl.unique_list;
}
static List *
@@ -1070,6 +1119,10 @@
List *new_joininfo)
{
ListCell *l;
+ UniquePtrList upl;
+
+ memset(&upl, 0, sizeof(upl));
+ upl.unique_list = new_joininfo;
/* Expected to be called only for join between parent relations. */
Assert(joinrel->reloptkind == RELOPT_JOINREL);
@@ -1095,11 +1148,12 @@
* multiply-linked rather than copied, pointer equality should be
* a sufficient test.)
*/
- new_joininfo = list_append_unique_ptr(new_joininfo, rinfo);
+ addUniquePtrList(&upl, rinfo);
}
}
- return new_joininfo;
+ hash_destroy(upl.h);
+ return upl.unique_list;
}
diff --git a/src/backend/utils/adt/ruleutils.c src/backend/utils/adt/ruleutils.c
index 74a18a146d0..954ee103d85 100644
--- a/src/backend/utils/adt/ruleutils.c
+++ src/backend/utils/adt/ruleutils.c
@@ -272,6 +272,8 @@ typedef struct
int *leftattnos; /* left-child varattnos of join cols, or 0 */
int *rightattnos; /* right-child varattnos of join cols, or 0 */
List *usingNames; /* names assigned to merged columns */
+
+ HTAB *all_names; /* hash to store all names colname_is_unique() */
} deparse_columns;
/* This macro is analogous to rt_fetch(), but for deparse_columns structs */
@@ -347,6 +349,7 @@ static void set_relation_column_names(deparse_namespace *dpns,
deparse_columns *colinfo);
static void set_join_column_names(deparse_namespace *dpns, RangeTblEntry *rte,
deparse_columns *colinfo);
+static void add_colname(deparse_columns *colinfo, char *colname);
static bool colname_is_unique(const char *colname, deparse_namespace *dpns,
deparse_columns *colinfo);
static char *make_colname_unique(char *colname, deparse_namespace *dpns,
@@ -4174,7 +4177,10 @@ set_join_column_names(deparse_namespace *dpns, RangeTblEntry *rte,
changed_any = true;
}
else
+ {
colinfo->new_colnames[j] = child_colname;
+ add_colname(colinfo, child_colname);
+ }
}
colinfo->is_new_col[j] = leftcolinfo->is_new_col[jc];
@@ -4223,7 +4229,10 @@ set_join_column_names(deparse_namespace *dpns, RangeTblEntry *rte,
changed_any = true;
}
else
+ {
colinfo->new_colnames[j] = child_colname;
+ add_colname(colinfo, child_colname);
+ }
}
colinfo->is_new_col[j] = rightcolinfo->is_new_col[jc];
@@ -4248,6 +4257,29 @@ set_join_column_names(deparse_namespace *dpns, RangeTblEntry *rte,
colinfo->printaliases = false;
}
+static uint32
+pstring_hash(const void *key, Size keysize)
+{
+ return string_hash(*(const void **)key, NAMEDATALEN);
+}
+
+static int
+pstring_compare(const void *key1, const void *key2, Size keysize)
+{
+ return strncmp(*(const void **)key1, *(const void **)key2, keysize - 1);
+}
+
+static void
+add_colname(deparse_columns *colinfo, char *colname)
+{
+ if (colinfo->all_names)
+ {
+ bool found;
+
+ hash_search(colinfo->all_names, &colname, HASH_ENTER, &found);
+ }
+}
+
/*
* colname_is_unique: is colname distinct from already-chosen column names?
*
@@ -4260,6 +4292,75 @@ colname_is_unique(const char *colname, deparse_namespace *dpns,
int i;
ListCell *lc;
+ if (colinfo->all_names != NULL ||
+ (colinfo->num_cols + colinfo->num_new_cols +
+ list_length(dpns->using_names) +
+ list_length(colinfo->parentUsing)) > 64)
+ {
+ bool found;
+
+ if (colinfo->all_names == NULL)
+ {
+ HASHCTL hash_ctl;
+
+ MemSet(&hash_ctl, 0, sizeof(hash_ctl));
+
+ hash_ctl.keysize = sizeof(char*);
+ hash_ctl.entrysize = sizeof(char*);
+ hash_ctl.hash = pstring_hash;
+ hash_ctl.match = pstring_compare;
+
+ colinfo->all_names = hash_create("colname_is_unique storage",
+ 512, &hash_ctl,
+ HASH_ELEM | HASH_FUNCTION | HASH_COMPARE);
+
+
+ for (i = 0; i < colinfo->num_cols; i++)
+ {
+ if (colinfo->colnames[i] == NULL)
+ continue;
+
+ hash_search(colinfo->all_names, &colinfo->colnames[i],
+ HASH_ENTER, &found);
+ }
+
+ for (i = 0; i < colinfo->num_new_cols; i++)
+ {
+ if (colinfo->new_colnames[i] == NULL)
+ continue;
+
+ hash_search(colinfo->all_names, &colinfo->new_colnames[i],
+ HASH_ENTER, &found);
+ }
+
+ foreach(lc, dpns->using_names)
+ {
+ char *oldname = (char *) lfirst(lc);
+
+ hash_search(colinfo->all_names, &oldname,
+ HASH_ENTER, &found);
+ }
+
+ foreach(lc, colinfo->parentUsing)
+ {
+ char *oldname = (char *) lfirst(lc);
+
+ hash_search(colinfo->all_names, &oldname,
+ HASH_ENTER, &found);
+ }
+ }
+
+ hash_search(colinfo->all_names, &colname, HASH_FIND, &found);
+
+ if (found)
+ return false;
+
+ hash_search(colinfo->all_names, &colname, HASH_ENTER, &found);
+ Assert(found == false);
+
+ return true;
+ }
+
/* Check against already-assigned column aliases within RTE */
for (i = 0; i < colinfo->num_cols; i++)
{
@@ -4311,6 +4412,8 @@ static char *
make_colname_unique(char *colname, deparse_namespace *dpns,
deparse_columns *colinfo)
{
+ CHECK_FOR_INTERRUPTS();
+
/*
* If the selected name isn't unique, append digits to make it so. For a
* very long input name, we might have to truncate to stay within