mirror of
https://github.com/beard7n/bsdports.git
synced 2026-04-10 10:31:20 +02:00
269 lines
6.8 KiB
Diff
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
|