Added support for DESC and NULLS FIRST/LAST to index keys

Fixes issue #3
This commit is contained in:
Daniele Varrazzo 2012-12-09 01:11:39 +00:00
parent 1a0a28d3f8
commit a47686a7ee
3 changed files with 85 additions and 4 deletions

View File

@ -314,3 +314,35 @@ ERROR: relation "tbl_uk" must have a primary key or not-null unique keys
\! pg_repack --dbname=contrib_regression --no-order --table=tbl_nn_puk \! pg_repack --dbname=contrib_regression --no-order --table=tbl_nn_puk
ERROR: relation "tbl_nn_puk" must have a primary key or not-null unique keys ERROR: relation "tbl_nn_puk" must have a primary key or not-null unique keys
-- => ERROR -- => ERROR
--
-- pg_repack issue #3
--
CREATE TABLE issue3 (col1 int NOT NULL, col2 text NOT NULL);
CREATE UNIQUE INDEX issue3_idx1 ON issue3 (col1, col2 DESC);
CREATE UNIQUE INDEX issue3_idx2 ON issue3 (col1 DESC, col2 text_pattern_ops);
CREATE UNIQUE INDEX issue3_idx3 ON issue3 (col1 DESC, col2 DESC);
CREATE UNIQUE INDEX issue3_idx4 ON issue3 (col1 NULLS FIRST, col2 text_pattern_ops DESC NULLS LAST);
SELECT repack.get_index_keys('issue3_idx1'::regclass::oid, 'issue3'::regclass::oid);
get_index_keys
-----------------
col1, col2 DESC
(1 row)
SELECT repack.get_index_keys('issue3_idx2'::regclass::oid, 'issue3'::regclass::oid);
get_index_keys
---------------------------
col1 DESC, col2 USING ~<~
(1 row)
SELECT repack.get_index_keys('issue3_idx3'::regclass::oid, 'issue3'::regclass::oid);
get_index_keys
----------------------
col1 DESC, col2 DESC
(1 row)
SELECT repack.get_index_keys('issue3_idx4'::regclass::oid, 'issue3'::regclass::oid);
get_index_keys
--------------------------------------------------
col1 NULLS FIRST, col2 DESC USING ~<~ NULLS LAST
(1 row)

View File

@ -187,3 +187,17 @@ CREATE UNIQUE INDEX tbl_nn_puk_pcol1_idx ON tbl_nn_puk(col1) WHERE col1 < 10;
-- => OK -- => OK
\! pg_repack --dbname=contrib_regression --no-order --table=tbl_nn_puk \! pg_repack --dbname=contrib_regression --no-order --table=tbl_nn_puk
-- => ERROR -- => ERROR
--
-- pg_repack issue #3
--
CREATE TABLE issue3 (col1 int NOT NULL, col2 text NOT NULL);
CREATE UNIQUE INDEX issue3_idx1 ON issue3 (col1, col2 DESC);
CREATE UNIQUE INDEX issue3_idx2 ON issue3 (col1 DESC, col2 text_pattern_ops);
CREATE UNIQUE INDEX issue3_idx3 ON issue3 (col1 DESC, col2 DESC);
CREATE UNIQUE INDEX issue3_idx4 ON issue3 (col1 NULLS FIRST, col2 text_pattern_ops DESC NULLS LAST);
SELECT repack.get_index_keys('issue3_idx1'::regclass::oid, 'issue3'::regclass::oid);
SELECT repack.get_index_keys('issue3_idx2'::regclass::oid, 'issue3'::regclass::oid);
SELECT repack.get_index_keys('issue3_idx3'::regclass::oid, 'issue3'::regclass::oid);
SELECT repack.get_index_keys('issue3_idx4'::regclass::oid, 'issue3'::regclass::oid);

View File

@ -472,6 +472,36 @@ parse_indexdef(IndexDef *stmt, Oid index, Oid table)
stmt->options = sql; stmt->options = sql;
} }
/*
* Parse the trailing ... [ DESC ] [ NULLS { FIRST | LAST } ] from an index
* definition column.
* Returned values point to token. \0's are inserted to separate parsed parts.
*/
static void
parse_desc_nulls(char *token, char **desc, char **nulls)
{
#if PG_VERSION_NUM >= 80300
char *pos;
/* easier to walk backwards than to parse quotes and escapes... */
if (NULL != (pos = strstr(token, " NULLS FIRST")))
{
*nulls = pos + 1;
*pos = '\0';
}
else if (NULL != (pos = strstr(token, " NULLS LAST")))
{
*nulls = pos + 1;
*pos = '\0';
}
if (NULL != (pos = strstr(token, " DESC")))
{
*desc = pos + 1;
*pos = '\0';
}
#endif
}
/** /**
* @fn Datum repack_get_index_keys(PG_FUNCTION_ARGS) * @fn Datum repack_get_index_keys(PG_FUNCTION_ARGS)
* @brief Get key definition of the index. * @brief Get key definition of the index.
@ -514,12 +544,18 @@ repack_get_index_keys(PG_FUNCTION_ARGS)
for (nattr = 0, next = stmt.columns; next; nattr++) for (nattr = 0, next = stmt.columns; next; nattr++)
{ {
char *opcname; char *opcname;
char *coldesc = NULL;
char *colnulls = NULL;
token = next; token = next;
while (isspace((unsigned char) *token)) while (isspace((unsigned char) *token))
token++; token++;
next = skip_until(index, next, ','); next = skip_until(index, next, ',');
parse_desc_nulls(token, &coldesc, &colnulls);
opcname = skip_until(index, token, ' '); opcname = skip_until(index, token, ' ');
appendStringInfoString(&str, token);
if (coldesc)
appendStringInfo(&str, " %s", coldesc);
if (opcname) if (opcname)
{ {
/* lookup default operator name from operator class */ /* lookup default operator name from operator class */
@ -556,12 +592,11 @@ repack_get_index_keys(PG_FUNCTION_ARGS)
elog(ERROR, "missing operator %d(%u,%u) in opfamily %u", elog(ERROR, "missing operator %d(%u,%u) in opfamily %u",
strategy, opcintype, opcintype, opfamily); strategy, opcintype, opcintype, opfamily);
opcname[-1] = '\0'; opcname[-1] = '\0';
appendStringInfo(&str, "%s USING %s", token, get_opname(oprid)); appendStringInfo(&str, " USING %s", get_opname(oprid));
} }
else if (colnulls)
appendStringInfoString(&str, token); appendStringInfo(&str, " %s", colnulls);
if (next) if (next)
appendStringInfoString(&str, ", "); appendStringInfoString(&str, ", ");
} }