Parse tablespace/where in parse_indexdef

Makes injecting the target tablespace much easier and fixes interaction
between tablespace and WITH/WHERE clauses.

Added tests to check the correct indexes definition.
This commit is contained in:
Daniele Varrazzo 2013-05-04 23:59:01 +01:00
parent 2b7e1b2f0c
commit a561c924f7
3 changed files with 83 additions and 40 deletions

View File

@ -17,6 +17,31 @@ CREATE INDEX testts1_with_idx on testts1 (id) with (fillfactor=80);
INSERT INTO testts1 (data) values ('a');
INSERT INTO testts1 (data) values ('b');
INSERT INTO testts1 (data) values ('c');
-- check the indexes definitions
SELECT regexp_replace(
repack.repack_indexdef(indexrelid, 'testts1'::regclass, NULL),
'_[0-9]+', '_OID', 'g')
FROM pg_index i join pg_class c ON c.oid = indexrelid
WHERE indrelid = 'testts1'::regclass ORDER BY relname;
regexp_replace
----------------------------------------------------------------------------------
CREATE INDEX index_OID ON repack.table_OID USING btree (id) WHERE (id > 0)
CREATE UNIQUE INDEX index_OID ON repack.table_OID USING btree (id)
CREATE INDEX index_OID ON repack.table_OID USING btree (id) WITH (fillfactor=80)
(3 rows)
SELECT regexp_replace(
repack.repack_indexdef(indexrelid, 'testts1'::regclass, 'foo'),
'_[0-9]+', '_OID', 'g')
FROM pg_index i join pg_class c ON c.oid = indexrelid
WHERE indrelid = 'testts1'::regclass ORDER BY relname;
regexp_replace
-------------------------------------------------------------------------------------------------
CREATE INDEX index_OID ON repack.table_OID USING btree (id) TABLESPACE foo WHERE (id > 0)
CREATE UNIQUE INDEX index_OID ON repack.table_OID USING btree (id) TABLESPACE foo
CREATE INDEX index_OID ON repack.table_OID USING btree (id) WITH (fillfactor=80) TABLESPACE foo
(3 rows)
-- can move the tablespace from default
\! pg_repack --dbname=contrib_regression --no-order --table=testts1 --tablespace testts
INFO: repacking table "testts1"

View File

@ -16,6 +16,19 @@ INSERT INTO testts1 (data) values ('a');
INSERT INTO testts1 (data) values ('b');
INSERT INTO testts1 (data) values ('c');
-- check the indexes definitions
SELECT regexp_replace(
repack.repack_indexdef(indexrelid, 'testts1'::regclass, NULL),
'_[0-9]+', '_OID', 'g')
FROM pg_index i join pg_class c ON c.oid = indexrelid
WHERE indrelid = 'testts1'::regclass ORDER BY relname;
SELECT regexp_replace(
repack.repack_indexdef(indexrelid, 'testts1'::regclass, 'foo'),
'_[0-9]+', '_OID', 'g')
FROM pg_index i join pg_class c ON c.oid = indexrelid
WHERE indrelid = 'testts1'::regclass ORDER BY relname;
-- can move the tablespace from default
\! pg_repack --dbname=contrib_regression --no-order --table=testts1 --tablespace testts

View File

@ -305,7 +305,9 @@ typedef struct IndexDef
char *table; /* table name including schema */
char *type; /* btree, hash, gist or gin */
char *columns; /* column definition */
char *options; /* options after columns. WITH, TABLESPACE and WHERE */
char *options; /* options after columns, before TABLESPACE (e.g. COLLATE) */
char *tablespace; /* tablespace if specified */
char *where; /* WHERE content if specified */
} IndexDef;
static char *
@ -349,14 +351,14 @@ skip_const(Oid index, char *sql, const char *arg1, const char *arg2)
static char *
skip_until_const(Oid index, char *sql, const char *what)
{
char *pos;
char *pos;
if ((pos = strstr(sql, what)))
{
size_t len;
size_t len;
len = strlen(what);
pos[len] = '\0';
len = strlen(what);
pos[-1] = '\0';
return pos + len + 1;
}
@ -462,6 +464,7 @@ parse_indexdef(IndexDef *stmt, Oid index, Oid table)
char *sql = pg_get_indexdef_string(index);
const char *idxname = get_quoted_relname(index);
const char *tblname = get_relation_name(table);
const char *limit = strchr(sql, '\0');
/* CREATE [UNIQUE] INDEX */
stmt->create = sql;
@ -486,8 +489,36 @@ parse_indexdef(IndexDef *stmt, Oid index, Oid table)
stmt->columns = sql;
if ((sql = skip_until(index, sql, ')')) == NULL)
parse_error(index);
/* options */
stmt->options = sql;
stmt->tablespace = NULL;
stmt->where = NULL;
/* Is there a tablespace? Note that apparently there is never, but
* if there was one it would appear here. */
if (sql < limit && strstr(sql, "TABLESPACE"))
{
sql = skip_until_const(index, sql, "TABLESPACE");
stmt->tablespace = sql;
sql = skip_ident(index, sql);
}
/* Note: assuming WHERE is the only clause allowed after TABLESPACE */
if (sql < limit && strstr(sql, "WHERE"))
{
sql = skip_until_const(index, sql, "WHERE");
stmt->where = sql;
}
elog(DEBUG2, "indexdef.create = %s", stmt->create);
elog(DEBUG2, "indexdef.index = %s", stmt->index);
elog(DEBUG2, "indexdef.table = %s", stmt->table);
elog(DEBUG2, "indexdef.type = %s", stmt->type);
elog(DEBUG2, "indexdef.columns = %s", stmt->columns);
elog(DEBUG2, "indexdef.options = %s", stmt->options);
elog(DEBUG2, "indexdef.tspace = %s", stmt->tablespace);
elog(DEBUG2, "indexdef.where = %s", stmt->where);
}
/*
@ -546,12 +577,6 @@ repack_get_order_by(PG_FUNCTION_ARGS)
int nattr;
parse_indexdef(&stmt, index, table);
elog(DEBUG2, "indexdef.create = %s", stmt.create);
elog(DEBUG2, "indexdef.index = %s", stmt.index);
elog(DEBUG2, "indexdef.table = %s", stmt.table);
elog(DEBUG2, "indexdef.type = %s", stmt.type);
elog(DEBUG2, "indexdef.columns = %s", stmt.columns);
elog(DEBUG2, "indexdef.options = %s", stmt.options);
/*
* FIXME: this is very unreliable implementation but I don't want to
@ -660,36 +685,16 @@ repack_indexdef(PG_FUNCTION_ARGS)
parse_indexdef(&stmt, index, table);
initStringInfo(&str);
appendStringInfo(&str, "%s index_%u ON repack.table_%u USING %s (%s)",
stmt.create, index, table, stmt.type, stmt.columns);
appendStringInfo(&str, "%s index_%u ON repack.table_%u USING %s (%s)%s",
stmt.create, index, table, stmt.type, stmt.columns, stmt.options);
/* Replace the tablespace in the index options */
if (tablespace == NULL)
{
/* tablespace is just fine */
appendStringInfoString(&str, stmt.options);
}
else
{
if (NULL == strstr(stmt.options, "TABLESPACE"))
{
/* tablespace is to append */
appendStringInfoString(&str, " TABLESPACE ");
appendStringInfoString(&str, NameStr(*tablespace));
}
else
{
/* tablespace is to replace */
char *tmp, *limit;
limit = strchr(stmt.options, '\0');
tmp = skip_until_const(index, stmt.options, " TABLESPACE");
appendStringInfoString(&str, stmt.options);
appendStringInfo(&str, " %s", NameStr(*tablespace));
tmp = skip_ident(index, tmp);
if (tmp < limit)
appendStringInfo(&str, " %s", tmp);
}
}
/* specify the new tablespace or the original one if any */
if (tablespace || stmt.tablespace)
appendStringInfo(&str, " TABLESPACE %s",
(tablespace ? NameStr(*tablespace) : stmt.tablespace));
if (stmt.where)
appendStringInfo(&str, " WHERE %s", stmt.where);
PG_RETURN_TEXT_P(cstring_to_text(str.data));
}