Merge remote-tracking branch 'piro/master'
This commit is contained in:
11
lib/Makefile
11
lib/Makefile
@ -6,7 +6,11 @@
|
||||
# Portions Copyright (c) 2012, The Reorg Development Team
|
||||
#
|
||||
|
||||
PG_CONFIG = pg_config
|
||||
PG_CONFIG ?= pg_config
|
||||
|
||||
# version as a number, e.g. 9.1.4 -> 901
|
||||
VERSION := $(shell $(PG_CONFIG) --version | awk '{print $$2}')
|
||||
INTVERSION := $(shell echo $$(($$(echo $(VERSION) | sed -E 's/([0-9]+)\.([0-9]+).*/\1*100+\2/'))))
|
||||
|
||||
EXTENSION = pg_repack
|
||||
MODULE_big = $(EXTENSION)
|
||||
@ -20,10 +24,7 @@ REPACK_VERSION = $(shell grep '"version":' ../META.json | head -1 \
|
||||
PG_CPPFLAGS = -DREPACK_VERSION=$(REPACK_VERSION)
|
||||
|
||||
# Support CREATE EXTENSION for PG >= 9.1 and a simple sql script for PG < 9.1
|
||||
HAVE_EXTENSION = $(shell $(PG_CONFIG) --version \
|
||||
| grep -qE " 8\.| 9\.0" && echo no || echo yes)
|
||||
|
||||
ifeq ($(HAVE_EXTENSION),yes)
|
||||
ifeq ($(shell echo $$(($(INTVERSION) >= 901))),1)
|
||||
DATA_built = pg_repack--$(REPACK_VERSION).sql pg_repack.control
|
||||
else
|
||||
DATA_built = pg_repack.sql
|
||||
|
@ -179,7 +179,9 @@ CREATE VIEW repack.tables AS
|
||||
'CREATE TABLE repack.log_' || R.oid || ' (id bigserial PRIMARY KEY, pk repack.pk_' || R.oid || ', row ' || repack.oid2text(R.oid) || ')' AS create_log,
|
||||
repack.get_create_trigger(R.oid, PK.indexrelid) AS create_trigger,
|
||||
repack.get_enable_trigger(R.oid) as enable_trigger,
|
||||
'CREATE TABLE repack.table_' || R.oid || ' WITH (' || array_to_string(array_append(R.reloptions, 'oids=' || CASE WHEN R.relhasoids THEN 'true' ELSE 'false' END), ',') || ') TABLESPACE ' || coalesce(quote_ident(S.spcname), 'pg_default') || ' AS SELECT ' || repack.get_columns_for_create_as(R.oid) || ' FROM ONLY ' || repack.oid2text(R.oid) AS create_table,
|
||||
'CREATE TABLE repack.table_' || R.oid || ' WITH (' || array_to_string(array_append(R.reloptions, 'oids=' || CASE WHEN R.relhasoids THEN 'true' ELSE 'false' END), ',') || ') TABLESPACE ' AS create_table_1,
|
||||
coalesce(quote_ident(S.spcname), 'pg_default') as tablespace_orig,
|
||||
' AS SELECT ' || repack.get_columns_for_create_as(R.oid) || ' FROM ONLY ' || repack.oid2text(R.oid) AS create_table_2,
|
||||
repack.get_drop_columns(R.oid, 'repack.table_' || R.oid) AS drop_columns,
|
||||
'DELETE FROM repack.log_' || R.oid AS delete_log,
|
||||
'LOCK TABLE ' || repack.oid2text(R.oid) || ' IN ACCESS EXCLUSIVE MODE' AS lock_table,
|
||||
@ -205,9 +207,9 @@ CREATE VIEW repack.tables AS
|
||||
AND N.nspname NOT IN ('pg_catalog', 'information_schema')
|
||||
AND N.nspname NOT LIKE E'pg\\_temp\\_%';
|
||||
|
||||
CREATE FUNCTION repack.repack_indexdef(oid, oid) RETURNS text AS
|
||||
CREATE FUNCTION repack.repack_indexdef(oid, oid, name) RETURNS text AS
|
||||
'MODULE_PATHNAME', 'repack_indexdef'
|
||||
LANGUAGE C STABLE STRICT;
|
||||
LANGUAGE C STABLE;
|
||||
|
||||
CREATE FUNCTION repack.repack_trigger() RETURNS trigger AS
|
||||
'MODULE_PATHNAME', 'repack_trigger'
|
||||
@ -217,6 +219,8 @@ CREATE FUNCTION repack.conflicted_triggers(oid) RETURNS SETOF name AS
|
||||
$$
|
||||
SELECT tgname FROM pg_trigger
|
||||
WHERE tgrelid = $1 AND tgname >= 'z_repack_trigger'
|
||||
AND (tgtype & 2) = 2 -- BEFORE trigger
|
||||
ORDER BY tgname;
|
||||
$$
|
||||
LANGUAGE sql STABLE STRICT;
|
||||
|
||||
|
81
lib/repack.c
81
lib/repack.c
@ -307,7 +307,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 *
|
||||
@ -348,6 +350,24 @@ skip_const(Oid index, char *sql, const char *arg1, const char *arg2)
|
||||
return parse_error(index);
|
||||
}
|
||||
|
||||
static char *
|
||||
skip_until_const(Oid index, char *sql, const char *what)
|
||||
{
|
||||
char *pos;
|
||||
|
||||
if ((pos = strstr(sql, what)))
|
||||
{
|
||||
size_t len;
|
||||
|
||||
len = strlen(what);
|
||||
pos[-1] = '\0';
|
||||
return pos + len + 1;
|
||||
}
|
||||
|
||||
/* error */
|
||||
return parse_error(index);
|
||||
}
|
||||
|
||||
static char *
|
||||
skip_ident(Oid index, char *sql)
|
||||
{
|
||||
@ -446,6 +466,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;
|
||||
@ -470,8 +491,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);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -530,12 +579,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
|
||||
@ -620,21 +663,41 @@ repack_get_order_by(PG_FUNCTION_ARGS)
|
||||
*
|
||||
* @param index Oid of target index.
|
||||
* @param table Oid of table of the index.
|
||||
* @param tablespace Namespace for the index. If NULL keep the original.
|
||||
* @retval Create index DDL for temp table.
|
||||
*/
|
||||
Datum
|
||||
repack_indexdef(PG_FUNCTION_ARGS)
|
||||
{
|
||||
Oid index = PG_GETARG_OID(0);
|
||||
Oid table = PG_GETARG_OID(1);
|
||||
Oid index;
|
||||
Oid table;
|
||||
Name tablespace = NULL;
|
||||
IndexDef stmt;
|
||||
StringInfoData str;
|
||||
|
||||
if (PG_ARGISNULL(0) || PG_ARGISNULL(1))
|
||||
PG_RETURN_NULL();
|
||||
|
||||
index = PG_GETARG_OID(0);
|
||||
table = PG_GETARG_OID(1);
|
||||
|
||||
if (!PG_ARGISNULL(2))
|
||||
tablespace = PG_GETARG_NAME(2);
|
||||
|
||||
parse_indexdef(&stmt, index, table);
|
||||
|
||||
initStringInfo(&str);
|
||||
appendStringInfo(&str, "%s index_%u ON repack.table_%u USING %s (%s)%s",
|
||||
stmt.create, index, table, stmt.type, stmt.columns, stmt.options);
|
||||
|
||||
/* 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));
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user