Skip to content

Commit 7815e7e

Browse files
committed
Add reusable routine for making arrays unique.
Introduce qunique() and qunique_arg(), which can be used after qsort() and qsort_arg() respectively to remove duplicate values. Use it where appropriate. Author: Thomas Munro Reviewed-by: Tom Lane (in an earlier version) Discussion: https://postgr.es/m/CAEepm%3D2vmFTNpAmwbGGD2WaryM6T3hSDVKQPfUwjdD_5XY6vAA%40mail.gmail.com
1 parent 3feb6ac commit 7815e7e

File tree

13 files changed

+115
-208
lines changed

13 files changed

+115
-208
lines changed

contrib/hstore/hstore_io.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,11 @@ hstoreUniquePairs(Pairs *a, int32 l, int32 *buflen)
322322
}
323323

324324
qsort((void *) a, l, sizeof(Pairs), comparePairs);
325+
326+
/*
327+
* We can't use qunique here because we have some clean-up code to run on
328+
* removed elements.
329+
*/
325330
ptr = a + 1;
326331
res = a;
327332
while (ptr - a < l)

contrib/intarray/_int_tool.c

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
#include "_int.h"
99
#include "catalog/pg_type.h"
10+
#include "lib/qunique.h"
1011

1112
/* arguments are assumed sorted & unique-ified */
1213
bool
@@ -308,23 +309,13 @@ internal_size(int *a, int len)
308309
ArrayType *
309310
_int_unique(ArrayType *r)
310311
{
311-
int *tmp,
312-
*dr,
313-
*data;
314312
int num = ARRNELEMS(r);
313+
bool duplicates_found; /* not used */
315314

316-
if (num < 2)
317-
return r;
315+
num = qunique_arg(ARRPTR(r), num, sizeof(int), isort_cmp,
316+
&duplicates_found);
318317

319-
data = tmp = dr = ARRPTR(r);
320-
while (tmp - data < num)
321-
{
322-
if (*tmp != *dr)
323-
*(++dr) = *tmp++;
324-
else
325-
tmp++;
326-
}
327-
return resize_intArrayType(r, dr + 1 - ARRPTR(r));
318+
return resize_intArrayType(r, num);
328319
}
329320

330321
void

contrib/pg_trgm/trgm_op.c

Lines changed: 3 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include <ctype.h>
77

88
#include "catalog/pg_type.h"
9+
#include "lib/qunique.h"
910
#include "trgm.h"
1011
#include "tsearch/ts_locale.h"
1112
#include "utils/lsyscache.h"
@@ -162,26 +163,6 @@ comp_trgm(const void *a, const void *b)
162163
return CMPTRGM(a, b);
163164
}
164165

165-
static int
166-
unique_array(trgm *a, int len)
167-
{
168-
trgm *curend,
169-
*tmp;
170-
171-
curend = tmp = a;
172-
while (tmp - a < len)
173-
if (CMPTRGM(tmp, curend))
174-
{
175-
curend++;
176-
CPTRGM(curend, tmp);
177-
tmp++;
178-
}
179-
else
180-
tmp++;
181-
182-
return curend + 1 - a;
183-
}
184-
185166
/*
186167
* Finds first word in string, returns pointer to the word,
187168
* endword points to the character after word
@@ -394,7 +375,7 @@ generate_trgm(char *str, int slen)
394375
if (len > 1)
395376
{
396377
qsort((void *) GETARR(trg), len, sizeof(trgm), comp_trgm);
397-
len = unique_array(GETARR(trg), len);
378+
len = qunique(GETARR(trg), len, sizeof(trgm), comp_trgm);
398379
}
399380

400381
SET_VARSIZE(trg, CALCGTSIZE(ARRKEY, len));
@@ -942,7 +923,7 @@ generate_wildcard_trgm(const char *str, int slen)
942923
if (len > 1)
943924
{
944925
qsort((void *) GETARR(trg), len, sizeof(trgm), comp_trgm);
945-
len = unique_array(GETARR(trg), len);
926+
len = qunique(GETARR(trg), len, sizeof(trgm), comp_trgm);
946927
}
947928

948929
SET_VARSIZE(trg, CALCGTSIZE(ARRKEY, len));

src/backend/access/nbtree/nbtutils.c

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "access/reloptions.h"
2222
#include "access/relscan.h"
2323
#include "commands/progress.h"
24+
#include "lib/qunique.h"
2425
#include "miscadmin.h"
2526
#include "utils/array.h"
2627
#include "utils/datum.h"
@@ -435,8 +436,6 @@ _bt_sort_array_elements(IndexScanDesc scan, ScanKey skey,
435436
Oid elemtype;
436437
RegProcedure cmp_proc;
437438
BTSortArrayContext cxt;
438-
int last_non_dup;
439-
int i;
440439

441440
if (nelems <= 1)
442441
return nelems; /* no work to do */
@@ -475,20 +474,8 @@ _bt_sort_array_elements(IndexScanDesc scan, ScanKey skey,
475474
_bt_compare_array_elements, (void *) &cxt);
476475

477476
/* Now scan the sorted elements and remove duplicates */
478-
last_non_dup = 0;
479-
for (i = 1; i < nelems; i++)
480-
{
481-
int32 compare;
482-
483-
compare = DatumGetInt32(FunctionCall2Coll(&cxt.flinfo,
484-
cxt.collation,
485-
elems[last_non_dup],
486-
elems[i]));
487-
if (compare != 0)
488-
elems[++last_non_dup] = elems[i];
489-
}
490-
491-
return last_non_dup + 1;
477+
return qunique_arg(elems, nelems, sizeof(Datum),
478+
_bt_compare_array_elements, &cxt);
492479
}
493480

494481
/*

src/backend/executor/nodeTidscan.c

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include "catalog/pg_type.h"
2828
#include "executor/execdebug.h"
2929
#include "executor/nodeTidscan.h"
30+
#include "lib/qunique.h"
3031
#include "miscadmin.h"
3132
#include "nodes/nodeFuncs.h"
3233
#include "storage/bufmgr.h"
@@ -260,21 +261,13 @@ TidListEval(TidScanState *tidstate)
260261
*/
261262
if (numTids > 1)
262263
{
263-
int lastTid;
264-
int i;
265-
266264
/* CurrentOfExpr could never appear OR'd with something else */
267265
Assert(!tidstate->tss_isCurrentOf);
268266

269267
qsort((void *) tidList, numTids, sizeof(ItemPointerData),
270268
itemptr_comparator);
271-
lastTid = 0;
272-
for (i = 1; i < numTids; i++)
273-
{
274-
if (!ItemPointerEquals(&tidList[lastTid], &tidList[i]))
275-
tidList[++lastTid] = tidList[i];
276-
}
277-
numTids = lastTid + 1;
269+
numTids = qunique(tidList, numTids, sizeof(ItemPointerData),
270+
itemptr_comparator);
278271
}
279272

280273
tidstate->tss_TidList = tidList;

src/backend/utils/adt/acl.c

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include "commands/tablespace.h"
2929
#include "foreign/foreign.h"
3030
#include "funcapi.h"
31+
#include "lib/qunique.h"
3132
#include "miscadmin.h"
3233
#include "utils/acl.h"
3334
#include "utils/array.h"
@@ -1475,8 +1476,7 @@ aclmembers(const Acl *acl, Oid **roleids)
14751476
Oid *list;
14761477
const AclItem *acldat;
14771478
int i,
1478-
j,
1479-
k;
1479+
j;
14801480

14811481
if (acl == NULL || ACL_NUM(acl) == 0)
14821482
{
@@ -1508,21 +1508,14 @@ aclmembers(const Acl *acl, Oid **roleids)
15081508
/* Sort the array */
15091509
qsort(list, j, sizeof(Oid), oid_cmp);
15101510

1511-
/* Remove duplicates from the array */
1512-
k = 0;
1513-
for (i = 1; i < j; i++)
1514-
{
1515-
if (list[k] != list[i])
1516-
list[++k] = list[i];
1517-
}
1518-
15191511
/*
15201512
* We could repalloc the array down to minimum size, but it's hardly worth
15211513
* it since it's only transient memory.
15221514
*/
15231515
*roleids = list;
15241516

1525-
return k + 1;
1517+
/* Remove duplicates from the array */
1518+
return qunique(list, j, sizeof(Oid), oid_cmp);
15261519
}
15271520

15281521

src/backend/utils/adt/tsgistidx.c

Lines changed: 3 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
#include "access/gist.h"
1818
#include "access/heaptoast.h"
19+
#include "lib/qunique.h"
1920
#include "port/pg_bitutils.h"
2021
#include "tsearch/ts_utils.h"
2122
#include "utils/builtins.h"
@@ -122,31 +123,6 @@ compareint(const void *va, const void *vb)
122123
return (a > b) ? 1 : -1;
123124
}
124125

125-
/*
126-
* Removes duplicates from an array of int32. 'l' is
127-
* size of the input array. Returns the new size of the array.
128-
*/
129-
static int
130-
uniqueint(int32 *a, int32 l)
131-
{
132-
int32 *ptr,
133-
*res;
134-
135-
if (l <= 1)
136-
return l;
137-
138-
ptr = res = a;
139-
140-
qsort((void *) a, l, sizeof(int32), compareint);
141-
142-
while (ptr - a < l)
143-
if (*ptr != *res)
144-
*(++res) = *ptr++;
145-
else
146-
ptr++;
147-
return res + 1 - a;
148-
}
149-
150126
static void
151127
makesign(BITVECP sign, SignTSVector *a)
152128
{
@@ -193,7 +169,8 @@ gtsvector_compress(PG_FUNCTION_ARGS)
193169
ptr++;
194170
}
195171

196-
len = uniqueint(GETARR(res), val->size);
172+
qsort(GETARR(res), val->size, sizeof(int), compareint);
173+
len = qunique(GETARR(res), val->size, sizeof(int), compareint);
197174
if (len != val->size)
198175
{
199176
/*

src/backend/utils/adt/tsquery_op.c

Lines changed: 4 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
#include "postgres.h"
1616

17+
#include "lib/qunique.h"
1718
#include "tsearch/ts_utils.h"
1819
#include "utils/builtins.h"
1920

@@ -302,29 +303,6 @@ cmp_string(const void *a, const void *b)
302303
return strcmp(sa, sb);
303304
}
304305

305-
static int
306-
remove_duplicates(char **strings, int n)
307-
{
308-
if (n <= 1)
309-
return n;
310-
else
311-
{
312-
int i;
313-
char *prev = strings[0];
314-
int new_n = 1;
315-
316-
for (i = 1; i < n; i++)
317-
{
318-
if (strcmp(strings[i], prev) != 0)
319-
{
320-
strings[new_n++] = strings[i];
321-
prev = strings[i];
322-
}
323-
}
324-
return new_n;
325-
}
326-
}
327-
328306
Datum
329307
tsq_mcontains(PG_FUNCTION_ARGS)
330308
{
@@ -342,9 +320,10 @@ tsq_mcontains(PG_FUNCTION_ARGS)
342320

343321
/* Sort and remove duplicates from both arrays */
344322
qsort(query_values, query_nvalues, sizeof(char *), cmp_string);
345-
query_nvalues = remove_duplicates(query_values, query_nvalues);
323+
query_nvalues = qunique(query_values, query_nvalues, sizeof(char *),
324+
cmp_string);
346325
qsort(ex_values, ex_nvalues, sizeof(char *), cmp_string);
347-
ex_nvalues = remove_duplicates(ex_values, ex_nvalues);
326+
ex_nvalues = qunique(ex_values, ex_nvalues, sizeof(char *), cmp_string);
348327

349328
if (ex_nvalues > query_nvalues)
350329
result = false;

src/backend/utils/adt/tsvector.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,9 @@ compareWordEntryPos(const void *a, const void *b)
4141
}
4242

4343
/*
44-
* Removes duplicate pos entries. If there's two entries with same pos
45-
* but different weight, the higher weight is retained.
44+
* Removes duplicate pos entries. If there's two entries with same pos but
45+
* different weight, the higher weight is retained, so we can't use
46+
* qunique here.
4647
*
4748
* Returns new length.
4849
*/

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy