diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/backend/access/nbtree/nbtutils.c | 19 | ||||
-rw-r--r-- | src/backend/executor/nodeTidscan.c | 13 | ||||
-rw-r--r-- | src/backend/utils/adt/acl.c | 15 | ||||
-rw-r--r-- | src/backend/utils/adt/tsgistidx.c | 29 | ||||
-rw-r--r-- | src/backend/utils/adt/tsquery_op.c | 29 | ||||
-rw-r--r-- | src/backend/utils/adt/tsvector.c | 5 | ||||
-rw-r--r-- | src/backend/utils/adt/tsvector_op.c | 59 | ||||
-rw-r--r-- | src/backend/utils/adt/txid.c | 19 | ||||
-rw-r--r-- | src/backend/utils/cache/syscache.c | 21 | ||||
-rw-r--r-- | src/include/lib/qunique.h | 65 |
10 files changed, 102 insertions, 172 deletions
diff --git a/src/backend/access/nbtree/nbtutils.c b/src/backend/access/nbtree/nbtutils.c index bc855dd25dc..6a3008dd48d 100644 --- a/src/backend/access/nbtree/nbtutils.c +++ b/src/backend/access/nbtree/nbtutils.c @@ -21,6 +21,7 @@ #include "access/reloptions.h" #include "access/relscan.h" #include "commands/progress.h" +#include "lib/qunique.h" #include "miscadmin.h" #include "utils/array.h" #include "utils/datum.h" @@ -435,8 +436,6 @@ _bt_sort_array_elements(IndexScanDesc scan, ScanKey skey, Oid elemtype; RegProcedure cmp_proc; BTSortArrayContext cxt; - int last_non_dup; - int i; if (nelems <= 1) return nelems; /* no work to do */ @@ -475,20 +474,8 @@ _bt_sort_array_elements(IndexScanDesc scan, ScanKey skey, _bt_compare_array_elements, (void *) &cxt); /* Now scan the sorted elements and remove duplicates */ - last_non_dup = 0; - for (i = 1; i < nelems; i++) - { - int32 compare; - - compare = DatumGetInt32(FunctionCall2Coll(&cxt.flinfo, - cxt.collation, - elems[last_non_dup], - elems[i])); - if (compare != 0) - elems[++last_non_dup] = elems[i]; - } - - return last_non_dup + 1; + return qunique_arg(elems, nelems, sizeof(Datum), + _bt_compare_array_elements, &cxt); } /* diff --git a/src/backend/executor/nodeTidscan.c b/src/backend/executor/nodeTidscan.c index 8cf22d5bf00..a59480f9068 100644 --- a/src/backend/executor/nodeTidscan.c +++ b/src/backend/executor/nodeTidscan.c @@ -27,6 +27,7 @@ #include "catalog/pg_type.h" #include "executor/execdebug.h" #include "executor/nodeTidscan.h" +#include "lib/qunique.h" #include "miscadmin.h" #include "nodes/nodeFuncs.h" #include "storage/bufmgr.h" @@ -260,21 +261,13 @@ TidListEval(TidScanState *tidstate) */ if (numTids > 1) { - int lastTid; - int i; - /* CurrentOfExpr could never appear OR'd with something else */ Assert(!tidstate->tss_isCurrentOf); qsort((void *) tidList, numTids, sizeof(ItemPointerData), itemptr_comparator); - lastTid = 0; - for (i = 1; i < numTids; i++) - { - if (!ItemPointerEquals(&tidList[lastTid], &tidList[i])) - tidList[++lastTid] = tidList[i]; - } - numTids = lastTid + 1; + numTids = qunique(tidList, numTids, sizeof(ItemPointerData), + itemptr_comparator); } tidstate->tss_TidList = tidList; diff --git a/src/backend/utils/adt/acl.c b/src/backend/utils/adt/acl.c index d7e6100ccbf..79bc750d775 100644 --- a/src/backend/utils/adt/acl.c +++ b/src/backend/utils/adt/acl.c @@ -28,6 +28,7 @@ #include "commands/tablespace.h" #include "foreign/foreign.h" #include "funcapi.h" +#include "lib/qunique.h" #include "miscadmin.h" #include "utils/acl.h" #include "utils/array.h" @@ -1475,8 +1476,7 @@ aclmembers(const Acl *acl, Oid **roleids) Oid *list; const AclItem *acldat; int i, - j, - k; + j; if (acl == NULL || ACL_NUM(acl) == 0) { @@ -1508,21 +1508,14 @@ aclmembers(const Acl *acl, Oid **roleids) /* Sort the array */ qsort(list, j, sizeof(Oid), oid_cmp); - /* Remove duplicates from the array */ - k = 0; - for (i = 1; i < j; i++) - { - if (list[k] != list[i]) - list[++k] = list[i]; - } - /* * We could repalloc the array down to minimum size, but it's hardly worth * it since it's only transient memory. */ *roleids = list; - return k + 1; + /* Remove duplicates from the array */ + return qunique(list, j, sizeof(Oid), oid_cmp); } diff --git a/src/backend/utils/adt/tsgistidx.c b/src/backend/utils/adt/tsgistidx.c index 6ff71a49b8f..af5b6809c50 100644 --- a/src/backend/utils/adt/tsgistidx.c +++ b/src/backend/utils/adt/tsgistidx.c @@ -16,6 +16,7 @@ #include "access/gist.h" #include "access/heaptoast.h" +#include "lib/qunique.h" #include "port/pg_bitutils.h" #include "tsearch/ts_utils.h" #include "utils/builtins.h" @@ -122,31 +123,6 @@ compareint(const void *va, const void *vb) return (a > b) ? 1 : -1; } -/* - * Removes duplicates from an array of int32. 'l' is - * size of the input array. Returns the new size of the array. - */ -static int -uniqueint(int32 *a, int32 l) -{ - int32 *ptr, - *res; - - if (l <= 1) - return l; - - ptr = res = a; - - qsort((void *) a, l, sizeof(int32), compareint); - - while (ptr - a < l) - if (*ptr != *res) - *(++res) = *ptr++; - else - ptr++; - return res + 1 - a; -} - static void makesign(BITVECP sign, SignTSVector *a) { @@ -193,7 +169,8 @@ gtsvector_compress(PG_FUNCTION_ARGS) ptr++; } - len = uniqueint(GETARR(res), val->size); + qsort(GETARR(res), val->size, sizeof(int), compareint); + len = qunique(GETARR(res), val->size, sizeof(int), compareint); if (len != val->size) { /* diff --git a/src/backend/utils/adt/tsquery_op.c b/src/backend/utils/adt/tsquery_op.c index 1f63d9b6a96..e6816940ad2 100644 --- a/src/backend/utils/adt/tsquery_op.c +++ b/src/backend/utils/adt/tsquery_op.c @@ -14,6 +14,7 @@ #include "postgres.h" +#include "lib/qunique.h" #include "tsearch/ts_utils.h" #include "utils/builtins.h" @@ -302,29 +303,6 @@ cmp_string(const void *a, const void *b) return strcmp(sa, sb); } -static int -remove_duplicates(char **strings, int n) -{ - if (n <= 1) - return n; - else - { - int i; - char *prev = strings[0]; - int new_n = 1; - - for (i = 1; i < n; i++) - { - if (strcmp(strings[i], prev) != 0) - { - strings[new_n++] = strings[i]; - prev = strings[i]; - } - } - return new_n; - } -} - Datum tsq_mcontains(PG_FUNCTION_ARGS) { @@ -342,9 +320,10 @@ tsq_mcontains(PG_FUNCTION_ARGS) /* Sort and remove duplicates from both arrays */ qsort(query_values, query_nvalues, sizeof(char *), cmp_string); - query_nvalues = remove_duplicates(query_values, query_nvalues); + query_nvalues = qunique(query_values, query_nvalues, sizeof(char *), + cmp_string); qsort(ex_values, ex_nvalues, sizeof(char *), cmp_string); - ex_nvalues = remove_duplicates(ex_values, ex_nvalues); + ex_nvalues = qunique(ex_values, ex_nvalues, sizeof(char *), cmp_string); if (ex_nvalues > query_nvalues) result = false; diff --git a/src/backend/utils/adt/tsvector.c b/src/backend/utils/adt/tsvector.c index ccfc4147fab..098eaed3e5e 100644 --- a/src/backend/utils/adt/tsvector.c +++ b/src/backend/utils/adt/tsvector.c @@ -41,8 +41,9 @@ compareWordEntryPos(const void *a, const void *b) } /* - * Removes duplicate pos entries. If there's two entries with same pos - * but different weight, the higher weight is retained. + * Removes duplicate pos entries. If there's two entries with same pos but + * different weight, the higher weight is retained, so we can't use + * qunique here. * * Returns new length. */ diff --git a/src/backend/utils/adt/tsvector_op.c b/src/backend/utils/adt/tsvector_op.c index 28d042273e3..f483c4b228b 100644 --- a/src/backend/utils/adt/tsvector_op.c +++ b/src/backend/utils/adt/tsvector_op.c @@ -21,6 +21,7 @@ #include "commands/trigger.h" #include "executor/spi.h" #include "funcapi.h" +#include "lib/qunique.h" #include "mb/pg_wchar.h" #include "miscadmin.h" #include "parser/parse_coerce.h" @@ -475,16 +476,9 @@ tsvector_delete_by_indices(TSVector tsv, int *indices_to_delete, */ if (indices_count > 1) { - int kp; - qsort(indices_to_delete, indices_count, sizeof(int), compare_int); - kp = 0; - for (k = 1; k < indices_count; k++) - { - if (indices_to_delete[k] != indices_to_delete[kp]) - indices_to_delete[++kp] = indices_to_delete[k]; - } - indices_count = ++kp; + indices_count = qunique(indices_to_delete, indices_count, sizeof(int), + compare_int); } /* @@ -761,7 +755,6 @@ array_to_tsvector(PG_FUNCTION_ARGS) bool *nulls; int nitems, i, - j, tslen, datalen = 0; char *cur; @@ -781,13 +774,8 @@ array_to_tsvector(PG_FUNCTION_ARGS) if (nitems > 1) { qsort(dlexemes, nitems, sizeof(Datum), compare_text_lexemes); - j = 0; - for (i = 1; i < nitems; i++) - { - if (compare_text_lexemes(&dlexemes[j], &dlexemes[i]) < 0) - dlexemes[++j] = dlexemes[i]; - } - nitems = ++j; + nitems = qunique(dlexemes, nitems, sizeof(Datum), + compare_text_lexemes); } /* Calculate space needed for surviving lexemes. */ @@ -1271,39 +1259,6 @@ checkclass_str(CHKVAL *chkval, WordEntry *entry, QueryOperand *val, } /* - * Removes duplicate pos entries. We can't use uniquePos() from - * tsvector.c because array might be longer than MAXENTRYPOS - * - * Returns new length. - */ -static int -uniqueLongPos(WordEntryPos *pos, int npos) -{ - WordEntryPos *pos_iter, - *result; - - if (npos <= 1) - return npos; - - qsort((void *) pos, npos, sizeof(WordEntryPos), compareWordEntryPos); - - result = pos; - pos_iter = pos + 1; - while (pos_iter < pos + npos) - { - if (WEP_GETPOS(*pos_iter) != WEP_GETPOS(*result)) - { - result++; - *result = WEP_GETPOS(*pos_iter); - } - - pos_iter++; - } - - return result + 1 - pos; -} - -/* * is there value 'val' in array or not ? */ static bool @@ -1397,7 +1352,9 @@ checkcondition_str(void *checkval, QueryOperand *val, ExecPhraseData *data) { /* Sort and make unique array of found positions */ data->pos = allpos; - data->npos = uniqueLongPos(allpos, npos); + qsort(data->pos, npos, sizeof(WordEntryPos), compareWordEntryPos); + data->npos = qunique(data->pos, npos, sizeof(WordEntryPos), + compareWordEntryPos); data->allocated = true; } } diff --git a/src/backend/utils/adt/txid.c b/src/backend/utils/adt/txid.c index 90b2c9b6948..e220c5f1364 100644 --- a/src/backend/utils/adt/txid.c +++ b/src/backend/utils/adt/txid.c @@ -27,6 +27,7 @@ #include "access/xlog.h" #include "funcapi.h" #include "miscadmin.h" +#include "lib/qunique.h" #include "libpq/pqformat.h" #include "postmaster/postmaster.h" #include "storage/lwlock.h" @@ -213,26 +214,10 @@ cmp_txid(const void *aa, const void *bb) static void sort_snapshot(TxidSnapshot *snap) { - txid last = 0; - int nxip, - idx1, - idx2; - if (snap->nxip > 1) { qsort(snap->xip, snap->nxip, sizeof(txid), cmp_txid); - - /* remove duplicates */ - nxip = snap->nxip; - idx1 = idx2 = 0; - while (idx1 < nxip) - { - if (snap->xip[idx1] != last) - last = snap->xip[idx2++] = snap->xip[idx1]; - else - snap->nxip--; - idx1++; - } + snap->nxip = qunique(snap->xip, snap->nxip, sizeof(txid), cmp_txid); } } diff --git a/src/backend/utils/cache/syscache.c b/src/backend/utils/cache/syscache.c index 16297a52a19..36aee74ab02 100644 --- a/src/backend/utils/cache/syscache.c +++ b/src/backend/utils/cache/syscache.c @@ -74,6 +74,7 @@ #include "catalog/pg_ts_template.h" #include "catalog/pg_type.h" #include "catalog/pg_user_mapping.h" +#include "lib/qunique.h" #include "utils/rel.h" #include "utils/catcache.h" #include "utils/syscache.h" @@ -1010,8 +1011,6 @@ void InitCatalogCache(void) { int cacheId; - int i, - j; StaticAssertStmt(SysCacheSize == (int) lengthof(cacheinfo), "SysCacheSize does not match syscache.c's array"); @@ -1048,21 +1047,15 @@ InitCatalogCache(void) /* Sort and de-dup OID arrays, so we can use binary search. */ pg_qsort(SysCacheRelationOid, SysCacheRelationOidSize, sizeof(Oid), oid_compare); - for (i = 1, j = 0; i < SysCacheRelationOidSize; i++) - { - if (SysCacheRelationOid[i] != SysCacheRelationOid[j]) - SysCacheRelationOid[++j] = SysCacheRelationOid[i]; - } - SysCacheRelationOidSize = j + 1; + SysCacheRelationOidSize = + qunique(SysCacheRelationOid, SysCacheRelationOidSize, sizeof(Oid), + oid_compare); pg_qsort(SysCacheSupportingRelOid, SysCacheSupportingRelOidSize, sizeof(Oid), oid_compare); - for (i = 1, j = 0; i < SysCacheSupportingRelOidSize; i++) - { - if (SysCacheSupportingRelOid[i] != SysCacheSupportingRelOid[j]) - SysCacheSupportingRelOid[++j] = SysCacheSupportingRelOid[i]; - } - SysCacheSupportingRelOidSize = j + 1; + SysCacheSupportingRelOidSize = + qunique(SysCacheSupportingRelOid, SysCacheSupportingRelOidSize, + sizeof(Oid), oid_compare); CacheInitialized = true; } diff --git a/src/include/lib/qunique.h b/src/include/lib/qunique.h new file mode 100644 index 00000000000..4d620f82ee6 --- /dev/null +++ b/src/include/lib/qunique.h @@ -0,0 +1,65 @@ +/*------------------------------------------------------------------------- + * + * qunique.h + * inline array unique functions + * Portions Copyright (c) 2019, PostgreSQL Global Development Group + * + * IDENTIFICATION + * src/include/lib/qunique.h + *------------------------------------------------------------------------- + */ + +#ifndef QUNIQUE_H +#define QUNIQUE_H + +/* + * Remove duplicates from a pre-sorted array, according to a user-supplied + * comparator. Usually the array should have been sorted with qsort() using + * the same arguments. Return the new size. + */ +static inline size_t +qunique(void *array, size_t elements, size_t width, + int (*compare) (const void *, const void *)) +{ + char *bytes = (char *) array; + size_t i, + j; + + if (elements <= 1) + return elements; + + for (i = 1, j = 0; i < elements; ++i) + { + if (compare(bytes + i * width, bytes + j * width) != 0) + memcpy(bytes + ++j * width, bytes + i * width, width); + } + + return j + 1; +} + +/* + * Like qunique(), but takes a comparator with an extra user data argument + * which is passed through, for compatibility with qsort_arg(). + */ +static inline size_t +qunique_arg(void *array, size_t elements, size_t width, + int (*compare) (const void *, const void *, void *), + void *arg) +{ + char *bytes = (char *) array; + size_t i, + j; + + if (elements <= 1) + return elements; + + for (i = 1, j = 0; i < elements; ++i) + { + if (compare(bytes + i * width, bytes + j * width, arg) != 0) + memcpy(bytes + ++j * width, bytes + i * width, width); + } + + return j + 1; +} + +#endif /* QUNIQUE_H */ |