Skip to content

Commit a47686a

Browse files
committed
Added support for DESC and NULLS FIRST/LAST to index keys
Fixes issue #3
1 parent 1a0a28d commit a47686a

File tree

3 files changed

+85
-4
lines changed

3 files changed

+85
-4
lines changed

bin/expected/repack.out

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,3 +314,35 @@ ERROR: relation "tbl_uk" must have a primary key or not-null unique keys
314314
\! pg_repack --dbname=contrib_regression --no-order --table=tbl_nn_puk
315315
ERROR: relation "tbl_nn_puk" must have a primary key or not-null unique keys
316316
-- => ERROR
317+
--
318+
-- pg_repack issue #3
319+
--
320+
CREATE TABLE issue3 (col1 int NOT NULL, col2 text NOT NULL);
321+
CREATE UNIQUE INDEX issue3_idx1 ON issue3 (col1, col2 DESC);
322+
CREATE UNIQUE INDEX issue3_idx2 ON issue3 (col1 DESC, col2 text_pattern_ops);
323+
CREATE UNIQUE INDEX issue3_idx3 ON issue3 (col1 DESC, col2 DESC);
324+
CREATE UNIQUE INDEX issue3_idx4 ON issue3 (col1 NULLS FIRST, col2 text_pattern_ops DESC NULLS LAST);
325+
SELECT repack.get_index_keys('issue3_idx1'::regclass::oid, 'issue3'::regclass::oid);
326+
get_index_keys
327+
-----------------
328+
col1, col2 DESC
329+
(1 row)
330+
331+
SELECT repack.get_index_keys('issue3_idx2'::regclass::oid, 'issue3'::regclass::oid);
332+
get_index_keys
333+
---------------------------
334+
col1 DESC, col2 USING ~<~
335+
(1 row)
336+
337+
SELECT repack.get_index_keys('issue3_idx3'::regclass::oid, 'issue3'::regclass::oid);
338+
get_index_keys
339+
----------------------
340+
col1 DESC, col2 DESC
341+
(1 row)
342+
343+
SELECT repack.get_index_keys('issue3_idx4'::regclass::oid, 'issue3'::regclass::oid);
344+
get_index_keys
345+
--------------------------------------------------
346+
col1 NULLS FIRST, col2 DESC USING ~<~ NULLS LAST
347+
(1 row)
348+

bin/sql/repack.sql

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,3 +187,17 @@ CREATE UNIQUE INDEX tbl_nn_puk_pcol1_idx ON tbl_nn_puk(col1) WHERE col1 < 10;
187187
-- => OK
188188
\! pg_repack --dbname=contrib_regression --no-order --table=tbl_nn_puk
189189
-- => ERROR
190+
191+
--
192+
-- pg_repack issue #3
193+
--
194+
CREATE TABLE issue3 (col1 int NOT NULL, col2 text NOT NULL);
195+
CREATE UNIQUE INDEX issue3_idx1 ON issue3 (col1, col2 DESC);
196+
CREATE UNIQUE INDEX issue3_idx2 ON issue3 (col1 DESC, col2 text_pattern_ops);
197+
CREATE UNIQUE INDEX issue3_idx3 ON issue3 (col1 DESC, col2 DESC);
198+
CREATE UNIQUE INDEX issue3_idx4 ON issue3 (col1 NULLS FIRST, col2 text_pattern_ops DESC NULLS LAST);
199+
200+
SELECT repack.get_index_keys('issue3_idx1'::regclass::oid, 'issue3'::regclass::oid);
201+
SELECT repack.get_index_keys('issue3_idx2'::regclass::oid, 'issue3'::regclass::oid);
202+
SELECT repack.get_index_keys('issue3_idx3'::regclass::oid, 'issue3'::regclass::oid);
203+
SELECT repack.get_index_keys('issue3_idx4'::regclass::oid, 'issue3'::regclass::oid);

lib/repack.c

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -472,6 +472,36 @@ parse_indexdef(IndexDef *stmt, Oid index, Oid table)
472472
stmt->options = sql;
473473
}
474474

475+
/*
476+
* Parse the trailing ... [ DESC ] [ NULLS { FIRST | LAST } ] from an index
477+
* definition column.
478+
* Returned values point to token. \0's are inserted to separate parsed parts.
479+
*/
480+
static void
481+
parse_desc_nulls(char *token, char **desc, char **nulls)
482+
{
483+
#if PG_VERSION_NUM >= 80300
484+
char *pos;
485+
486+
/* easier to walk backwards than to parse quotes and escapes... */
487+
if (NULL != (pos = strstr(token, " NULLS FIRST")))
488+
{
489+
*nulls = pos + 1;
490+
*pos = '\0';
491+
}
492+
else if (NULL != (pos = strstr(token, " NULLS LAST")))
493+
{
494+
*nulls = pos + 1;
495+
*pos = '\0';
496+
}
497+
if (NULL != (pos = strstr(token, " DESC")))
498+
{
499+
*desc = pos + 1;
500+
*pos = '\0';
501+
}
502+
#endif
503+
}
504+
475505
/**
476506
* @fn Datum repack_get_index_keys(PG_FUNCTION_ARGS)
477507
* @brief Get key definition of the index.
@@ -514,12 +544,18 @@ repack_get_index_keys(PG_FUNCTION_ARGS)
514544
for (nattr = 0, next = stmt.columns; next; nattr++)
515545
{
516546
char *opcname;
547+
char *coldesc = NULL;
548+
char *colnulls = NULL;
517549

518550
token = next;
519551
while (isspace((unsigned char) *token))
520552
token++;
521553
next = skip_until(index, next, ',');
554+
parse_desc_nulls(token, &coldesc, &colnulls);
522555
opcname = skip_until(index, token, ' ');
556+
appendStringInfoString(&str, token);
557+
if (coldesc)
558+
appendStringInfo(&str, " %s", coldesc);
523559
if (opcname)
524560
{
525561
/* lookup default operator name from operator class */
@@ -556,12 +592,11 @@ repack_get_index_keys(PG_FUNCTION_ARGS)
556592
elog(ERROR, "missing operator %d(%u,%u) in opfamily %u",
557593
strategy, opcintype, opcintype, opfamily);
558594

559-
560595
opcname[-1] = '\0';
561-
appendStringInfo(&str, "%s USING %s", token, get_opname(oprid));
596+
appendStringInfo(&str, " USING %s", get_opname(oprid));
562597
}
563-
else
564-
appendStringInfoString(&str, token);
598+
if (colnulls)
599+
appendStringInfo(&str, " %s", colnulls);
565600
if (next)
566601
appendStringInfoString(&str, ", ");
567602
}

0 commit comments

Comments
 (0)