version 1.0.5.
- Disable autovacuum for working tables and update logs. - Do ANALYZE automatically after reorg unless -Z, --no-analyze option is specified.
This commit is contained in:
parent
9a8f2e9c33
commit
5fe3f037be
@ -8,7 +8,7 @@
|
|||||||
* @brief Client Modules
|
* @brief Client Modules
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const char *PROGRAM_VERSION = "1.0.4";
|
const char *PROGRAM_VERSION = "1.0.5";
|
||||||
const char *PROGRAM_URL = "http://reorg.projects.postgresql.org/";
|
const char *PROGRAM_URL = "http://reorg.projects.postgresql.org/";
|
||||||
const char *PROGRAM_EMAIL = "reorg-general@lists.pgfoundry.org";
|
const char *PROGRAM_EMAIL = "reorg-general@lists.pgfoundry.org";
|
||||||
|
|
||||||
@ -92,9 +92,9 @@ static bool sqlstate_equals(PGresult *res, const char *state)
|
|||||||
return strcmp(PQresultErrorField(res, PG_DIAG_SQLSTATE), state) == 0;
|
return strcmp(PQresultErrorField(res, PG_DIAG_SQLSTATE), state) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool echo = false;
|
|
||||||
static bool verbose = false;
|
static bool verbose = false;
|
||||||
static bool quiet = false;
|
static bool quiet = false;
|
||||||
|
static bool analyze = true;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The table begin re-organized. If not null, we need to cleanup temp
|
* The table begin re-organized. If not null, we need to cleanup temp
|
||||||
@ -110,16 +110,14 @@ utoa(unsigned int value, char *buffer)
|
|||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *pgut_optstring = "eqvat:no:";
|
const struct option pgut_options[] = {
|
||||||
|
|
||||||
const struct option pgut_longopts[] = {
|
|
||||||
{"echo", no_argument, NULL, 'e'},
|
|
||||||
{"quiet", no_argument, NULL, 'q'},
|
{"quiet", no_argument, NULL, 'q'},
|
||||||
{"verbose", no_argument, NULL, 'v'},
|
{"verbose", no_argument, NULL, 'v'},
|
||||||
{"all", no_argument, NULL, 'a'},
|
{"all", no_argument, NULL, 'a'},
|
||||||
{"table", required_argument, NULL, 't'},
|
{"table", required_argument, NULL, 't'},
|
||||||
{"no-order", no_argument, NULL, 'n'},
|
{"no-order", no_argument, NULL, 'n'},
|
||||||
{"order-by", required_argument, NULL, 'o'},
|
{"order-by", required_argument, NULL, 'o'},
|
||||||
|
{"no-analyze", no_argument, NULL, 'Z'},
|
||||||
{NULL, 0, NULL, 0}
|
{NULL, 0, NULL, 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -132,9 +130,6 @@ pgut_argument(int c, const char *arg)
|
|||||||
{
|
{
|
||||||
switch (c)
|
switch (c)
|
||||||
{
|
{
|
||||||
case 'e':
|
|
||||||
echo = true;
|
|
||||||
break;
|
|
||||||
case 'q':
|
case 'q':
|
||||||
quiet = true;
|
quiet = true;
|
||||||
break;
|
break;
|
||||||
@ -153,6 +148,9 @@ pgut_argument(int c, const char *arg)
|
|||||||
case 'o':
|
case 'o':
|
||||||
assign_option(&orderby, c, arg);
|
assign_option(&orderby, c, arg);
|
||||||
break;
|
break;
|
||||||
|
case 'Z':
|
||||||
|
analyze = false;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -249,9 +247,9 @@ reorg_one_database(const char *orderby, const char *table)
|
|||||||
PGresult *res;
|
PGresult *res;
|
||||||
int i;
|
int i;
|
||||||
int num;
|
int num;
|
||||||
PQExpBufferData sql;
|
StringInfoData sql;
|
||||||
|
|
||||||
initPQExpBuffer(&sql);
|
initStringInfo(&sql);
|
||||||
|
|
||||||
reconnect();
|
reconnect();
|
||||||
|
|
||||||
@ -262,18 +260,18 @@ reorg_one_database(const char *orderby, const char *table)
|
|||||||
command("SET client_min_messages = warning", 0, NULL);
|
command("SET client_min_messages = warning", 0, NULL);
|
||||||
|
|
||||||
/* acquire target tables */
|
/* acquire target tables */
|
||||||
appendPQExpBufferStr(&sql, "SELECT * FROM reorg.tables WHERE ");
|
appendStringInfoString(&sql, "SELECT * FROM reorg.tables WHERE ");
|
||||||
if (table)
|
if (table)
|
||||||
{
|
{
|
||||||
appendPQExpBufferStr(&sql, "relid = $1::regclass");
|
appendStringInfoString(&sql, "relid = $1::regclass");
|
||||||
res = execute_nothrow(sql.data, 1, &table);
|
res = execute_elevel(sql.data, 1, &table, LOG);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
appendPQExpBufferStr(&sql, "pkid IS NOT NULL");
|
appendStringInfoString(&sql, "pkid IS NOT NULL");
|
||||||
if (!orderby)
|
if (!orderby)
|
||||||
appendPQExpBufferStr(&sql, " AND ckid IS NOT NULL");
|
appendStringInfoString(&sql, " AND ckid IS NOT NULL");
|
||||||
res = execute_nothrow(sql.data, 0, NULL);
|
res = execute_elevel(sql.data, 0, NULL, LOG);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (PQresultStatus(res) != PGRES_TUPLES_OK)
|
if (PQresultStatus(res) != PGRES_TUPLES_OK)
|
||||||
@ -321,13 +319,13 @@ reorg_one_database(const char *orderby, const char *table)
|
|||||||
table.lock_table = getstr(res, i, c++);
|
table.lock_table = getstr(res, i, c++);
|
||||||
ckey = getstr(res, i, c++);
|
ckey = getstr(res, i, c++);
|
||||||
|
|
||||||
resetPQExpBuffer(&sql);
|
resetStringInfo(&sql);
|
||||||
if (!orderby)
|
if (!orderby)
|
||||||
{
|
{
|
||||||
/* CLUSTER mode */
|
/* CLUSTER mode */
|
||||||
if (ckey == NULL)
|
if (ckey == NULL)
|
||||||
elog(ERROR, "relation \"%s\" has no cluster key", table.target_name);
|
elog(ERROR, "relation \"%s\" has no cluster key", table.target_name);
|
||||||
appendPQExpBuffer(&sql, "%s ORDER BY %s", create_table, ckey);
|
appendStringInfo(&sql, "%s ORDER BY %s", create_table, ckey);
|
||||||
table.create_table = sql.data;
|
table.create_table = sql.data;
|
||||||
}
|
}
|
||||||
else if (!orderby[0])
|
else if (!orderby[0])
|
||||||
@ -338,7 +336,7 @@ reorg_one_database(const char *orderby, const char *table)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* User specified ORDER BY */
|
/* User specified ORDER BY */
|
||||||
appendPQExpBuffer(&sql, "%s ORDER BY %s", create_table, orderby);
|
appendStringInfo(&sql, "%s ORDER BY %s", create_table, orderby);
|
||||||
table.create_table = sql.data;
|
table.create_table = sql.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -354,7 +352,7 @@ reorg_one_database(const char *orderby, const char *table)
|
|||||||
cleanup:
|
cleanup:
|
||||||
PQclear(res);
|
PQclear(res);
|
||||||
disconnect();
|
disconnect();
|
||||||
termPQExpBuffer(&sql);
|
termStringInfo(&sql);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -393,6 +391,9 @@ reorg_one_table(const reorg_table *table, const char *orderby)
|
|||||||
int i;
|
int i;
|
||||||
char *vxid;
|
char *vxid;
|
||||||
char buffer[12];
|
char buffer[12];
|
||||||
|
StringInfoData sql;
|
||||||
|
|
||||||
|
initStringInfo(&sql);
|
||||||
|
|
||||||
if (verbose)
|
if (verbose)
|
||||||
{
|
{
|
||||||
@ -430,16 +431,16 @@ reorg_one_table(const reorg_table *table, const char *orderby)
|
|||||||
*/
|
*/
|
||||||
params[0] = utoa(table->target_oid, buffer);
|
params[0] = utoa(table->target_oid, buffer);
|
||||||
|
|
||||||
res = execute(
|
res = execute("SELECT reorg.conflicted_triggers($1)", 1, params);
|
||||||
"SELECT 1 FROM pg_trigger"
|
|
||||||
" WHERE tgrelid = $1 AND tgname >= 'z_reorg_trigger' LIMIT 1",
|
|
||||||
1, params);
|
|
||||||
if (PQntuples(res) > 0)
|
if (PQntuples(res) > 0)
|
||||||
elog(ERROR, "trigger conflicted for %s", table->target_name);
|
elog(ERROR, "trigger %s conflicted for %s",
|
||||||
|
PQgetvalue(res, 0, 0), table->target_name);
|
||||||
|
|
||||||
command(table->create_pktype, 0, NULL);
|
command(table->create_pktype, 0, NULL);
|
||||||
command(table->create_log, 0, NULL);
|
command(table->create_log, 0, NULL);
|
||||||
command(table->create_trigger, 0, NULL);
|
command(table->create_trigger, 0, NULL);
|
||||||
|
printfStringInfo(&sql, "SELECT reorg.disable_autovacuum('reorg.log_%u')", table->target_oid);
|
||||||
|
command(sql.data, 0, NULL);
|
||||||
command("COMMIT", 0, NULL);
|
command("COMMIT", 0, NULL);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -465,6 +466,8 @@ reorg_one_table(const reorg_table *table, const char *orderby)
|
|||||||
PQclear(res);
|
PQclear(res);
|
||||||
command(table->delete_log, 0, NULL);
|
command(table->delete_log, 0, NULL);
|
||||||
command(table->create_table, 0, NULL);
|
command(table->create_table, 0, NULL);
|
||||||
|
printfStringInfo(&sql, "SELECT reorg.disable_autovacuum('reorg.table_%u')", table->target_oid);
|
||||||
|
command(sql.data, 0, NULL);
|
||||||
command("COMMIT", 0, NULL);
|
command("COMMIT", 0, NULL);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -537,7 +540,7 @@ reorg_one_table(const reorg_table *table, const char *orderby)
|
|||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
command("BEGIN ISOLATION LEVEL READ COMMITTED", 0, NULL);
|
command("BEGIN ISOLATION LEVEL READ COMMITTED", 0, NULL);
|
||||||
res = execute_nothrow(table->lock_table, 0, NULL);
|
res = execute_elevel(table->lock_table, 0, NULL, NOTICE);
|
||||||
if (PQresultStatus(res) == PGRES_COMMAND_OK)
|
if (PQresultStatus(res) == PGRES_COMMAND_OK)
|
||||||
{
|
{
|
||||||
PQclear(res);
|
PQclear(res);
|
||||||
@ -577,8 +580,23 @@ reorg_one_table(const reorg_table *table, const char *orderby)
|
|||||||
command("COMMIT", 0, NULL);
|
command("COMMIT", 0, NULL);
|
||||||
|
|
||||||
current_table = NULL;
|
current_table = NULL;
|
||||||
|
|
||||||
free(vxid);
|
free(vxid);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 7. Analyze.
|
||||||
|
* Note that current_table is already set to NULL here because analyze
|
||||||
|
* is an unimportant operation; No clean up even if failed.
|
||||||
|
*/
|
||||||
|
if (verbose)
|
||||||
|
fprintf(stderr, "---- analyze ----\n");
|
||||||
|
|
||||||
|
command("BEGIN ISOLATION LEVEL READ COMMITTED", 0, NULL);
|
||||||
|
printfStringInfo(&sql, "ANALYZE %s%s",
|
||||||
|
(verbose ? "VERBOSE " : ""), table->target_name);
|
||||||
|
command(sql.data, 0, NULL);
|
||||||
|
command("COMMIT", 0, NULL);
|
||||||
|
|
||||||
|
termStringInfo(&sql);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -624,7 +642,7 @@ pgut_help(void)
|
|||||||
" -t, --table=TABLE reorg specific table only\n"
|
" -t, --table=TABLE reorg specific table only\n"
|
||||||
" -n, --no-order do vacuum full instead of cluster\n"
|
" -n, --no-order do vacuum full instead of cluster\n"
|
||||||
" -o, --order-by=columns order by columns instead of cluster keys\n"
|
" -o, --order-by=columns order by columns instead of cluster keys\n"
|
||||||
" -e, --echo show the commands being sent to the server\n"
|
" -Z, --no-analyze don't analyze at end\n"
|
||||||
" -q, --quiet don't write any messages\n"
|
" -q, --quiet don't write any messages\n"
|
||||||
" -v, --verbose display detailed information during processing\n",
|
" -v, --verbose display detailed information during processing\n",
|
||||||
PROGRAM_NAME, PROGRAM_NAME);
|
PROGRAM_NAME, PROGRAM_NAME);
|
||||||
|
110
bin/pgut/pgut.c
110
bin/pgut/pgut.c
@ -21,13 +21,14 @@ const char *host = NULL;
|
|||||||
const char *port = NULL;
|
const char *port = NULL;
|
||||||
const char *username = NULL;
|
const char *username = NULL;
|
||||||
bool password = false;
|
bool password = false;
|
||||||
|
bool debug = false;
|
||||||
|
|
||||||
/* Database connections */
|
/* Database connections */
|
||||||
PGconn *connection = NULL;
|
PGconn *connection = NULL;
|
||||||
static PGcancel *volatile cancel_conn = NULL;
|
static PGcancel *volatile cancel_conn = NULL;
|
||||||
|
|
||||||
/* Interrupted by SIGINT (Ctrl+C) ? */
|
/* Interrupted by SIGINT (Ctrl+C) ? */
|
||||||
static bool interrupted = false;
|
bool interrupted = false;
|
||||||
|
|
||||||
/* Connection routines */
|
/* Connection routines */
|
||||||
static void init_cancel_handler(void);
|
static void init_cancel_handler(void);
|
||||||
@ -39,40 +40,19 @@ static void exit_or_abort(int exitcode);
|
|||||||
static void help(void);
|
static void help(void);
|
||||||
static const char *get_user_name(const char *PROGRAM_NAME);
|
static const char *get_user_name(const char *PROGRAM_NAME);
|
||||||
|
|
||||||
const char default_optstring[] = "d:h:p:U:W";
|
const struct option default_options[] =
|
||||||
|
|
||||||
const struct option default_longopts[] =
|
|
||||||
{
|
{
|
||||||
{"dbname", required_argument, NULL, 'd'},
|
{"dbname", required_argument, NULL, 'd'},
|
||||||
{"host", required_argument, NULL, 'h'},
|
{"host", required_argument, NULL, 'h'},
|
||||||
{"port", required_argument, NULL, 'p'},
|
{"port", required_argument, NULL, 'p'},
|
||||||
{"username", required_argument, NULL, 'U'},
|
{"username", required_argument, NULL, 'U'},
|
||||||
{"password", no_argument, NULL, 'W'},
|
{"password", no_argument, NULL, 'W'},
|
||||||
|
{"debug", no_argument, NULL, '!'},
|
||||||
{NULL, 0, NULL, 0}
|
{NULL, 0, NULL, 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char *optstring = NULL;
|
|
||||||
static const struct option *longopts = NULL;;
|
static const struct option *longopts = NULL;;
|
||||||
|
|
||||||
static const char *
|
|
||||||
merge_optstring(const char *opts)
|
|
||||||
{
|
|
||||||
size_t len;
|
|
||||||
char *result;
|
|
||||||
|
|
||||||
if (opts == NULL)
|
|
||||||
return default_optstring;
|
|
||||||
|
|
||||||
len = strlen(opts);
|
|
||||||
if (len == 0)
|
|
||||||
return default_optstring;
|
|
||||||
|
|
||||||
result = malloc(len + lengthof(default_optstring));
|
|
||||||
memcpy(&result[0], opts, len);
|
|
||||||
memcpy(&result[len], default_optstring, lengthof(default_optstring));
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct option *
|
static const struct option *
|
||||||
merge_longopts(const struct option *opts)
|
merge_longopts(const struct option *opts)
|
||||||
{
|
{
|
||||||
@ -80,15 +60,37 @@ merge_longopts(const struct option *opts)
|
|||||||
struct option *result;
|
struct option *result;
|
||||||
|
|
||||||
if (opts == NULL)
|
if (opts == NULL)
|
||||||
return default_longopts;
|
return default_options;
|
||||||
|
|
||||||
for (len = 0; opts[len].name; len++) { }
|
for (len = 0; opts[len].name; len++) { }
|
||||||
if (len == 0)
|
if (len == 0)
|
||||||
return default_longopts;
|
return default_options;
|
||||||
|
|
||||||
result = (struct option *) malloc((len + lengthof(default_longopts)) * sizeof(struct option));
|
result = (struct option *) malloc((len + lengthof(default_options)) * sizeof(struct option));
|
||||||
memcpy(&result[0], opts, len * sizeof(struct option));
|
memcpy(&result[0], opts, len * sizeof(struct option));
|
||||||
memcpy(&result[len], default_longopts, lengthof(default_longopts) * sizeof(struct option));
|
memcpy(&result[len], default_options, lengthof(default_options) * sizeof(struct option));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *
|
||||||
|
longopts_to_optstring(const struct option *opts)
|
||||||
|
{
|
||||||
|
size_t len;
|
||||||
|
char *result;
|
||||||
|
char *s;
|
||||||
|
|
||||||
|
for (len = 0; opts[len].name; len++) { }
|
||||||
|
result = malloc(len * 2 + 1);
|
||||||
|
|
||||||
|
s = result;
|
||||||
|
for (len = 0; opts[len].name; len++)
|
||||||
|
{
|
||||||
|
*s++ = opts[len].val;
|
||||||
|
if (opts[len].has_arg == required_argument)
|
||||||
|
*s++ = ':';
|
||||||
|
}
|
||||||
|
*s = '\0';
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -97,6 +99,7 @@ parse_options(int argc, char **argv)
|
|||||||
{
|
{
|
||||||
int c;
|
int c;
|
||||||
int optindex = 0;
|
int optindex = 0;
|
||||||
|
const char *optstring;
|
||||||
|
|
||||||
PROGRAM_NAME = get_progname(argv[0]);
|
PROGRAM_NAME = get_progname(argv[0]);
|
||||||
set_pglocale_pgservice(argv[0], "pgscripts");
|
set_pglocale_pgservice(argv[0], "pgscripts");
|
||||||
@ -117,8 +120,8 @@ parse_options(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Merge default and user options. */
|
/* Merge default and user options. */
|
||||||
optstring = merge_optstring(pgut_optstring);
|
longopts = merge_longopts(pgut_options);
|
||||||
longopts = merge_longopts(pgut_longopts);
|
optstring = longopts_to_optstring(longopts);
|
||||||
|
|
||||||
while ((c = getopt_long(argc, argv, optstring, longopts, &optindex)) != -1)
|
while ((c = getopt_long(argc, argv, optstring, longopts, &optindex)) != -1)
|
||||||
{
|
{
|
||||||
@ -139,6 +142,9 @@ parse_options(int argc, char **argv)
|
|||||||
case 'W':
|
case 'W':
|
||||||
password = true;
|
password = true;
|
||||||
break;
|
break;
|
||||||
|
case '!':
|
||||||
|
debug = true;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
if (!pgut_argument(c, optarg))
|
if (!pgut_argument(c, optarg))
|
||||||
{
|
{
|
||||||
@ -250,7 +256,7 @@ disconnect(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
PGresult *
|
PGresult *
|
||||||
execute_nothrow(const char *query, int nParams, const char **params)
|
execute_elevel(const char *query, int nParams, const char **params, int elevel)
|
||||||
{
|
{
|
||||||
PGresult *res;
|
PGresult *res;
|
||||||
|
|
||||||
@ -260,6 +266,19 @@ execute_nothrow(const char *query, int nParams, const char **params)
|
|||||||
elog(ERROR, "%s: interrupted", PROGRAM_NAME);
|
elog(ERROR, "%s: interrupted", PROGRAM_NAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* write query to elog if debug */
|
||||||
|
if (debug)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (strchr(query, '\n'))
|
||||||
|
elog(LOG, "(query)\n%s", query);
|
||||||
|
else
|
||||||
|
elog(LOG, "(query) %s", query);
|
||||||
|
for (i = 0; i < nParams; i++)
|
||||||
|
elog(LOG, "\t(param:%d) = %s", i, params[i] ? params[i] : "(null)");
|
||||||
|
}
|
||||||
|
|
||||||
on_before_exec(connection);
|
on_before_exec(connection);
|
||||||
if (nParams == 0)
|
if (nParams == 0)
|
||||||
res = PQexec(connection, query);
|
res = PQexec(connection, query);
|
||||||
@ -267,6 +286,17 @@ execute_nothrow(const char *query, int nParams, const char **params)
|
|||||||
res = PQexecParams(connection, query, nParams, NULL, params, NULL, NULL, 0);
|
res = PQexecParams(connection, query, nParams, NULL, params, NULL, NULL, 0);
|
||||||
on_after_exec();
|
on_after_exec();
|
||||||
|
|
||||||
|
switch (PQresultStatus(res))
|
||||||
|
{
|
||||||
|
case PGRES_TUPLES_OK:
|
||||||
|
case PGRES_COMMAND_OK:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
elog(elevel, "query failed: %squery was: %s",
|
||||||
|
PQerrorMessage(connection), query);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -276,17 +306,7 @@ execute_nothrow(const char *query, int nParams, const char **params)
|
|||||||
PGresult *
|
PGresult *
|
||||||
execute(const char *query, int nParams, const char **params)
|
execute(const char *query, int nParams, const char **params)
|
||||||
{
|
{
|
||||||
PGresult *res = execute_nothrow(query, nParams, params);
|
return execute_elevel(query, nParams, params, ERROR);
|
||||||
|
|
||||||
if (PQresultStatus(res) == PGRES_TUPLES_OK ||
|
|
||||||
PQresultStatus(res) == PGRES_COMMAND_OK)
|
|
||||||
return res;
|
|
||||||
|
|
||||||
fprintf(stderr, "%s: query failed: %s", PROGRAM_NAME, PQerrorMessage(connection));
|
|
||||||
fprintf(stderr, "%s: query was: %s\n", PROGRAM_NAME, query);
|
|
||||||
PQclear(res);
|
|
||||||
exit_or_abort(ERROR);
|
|
||||||
return NULL; /* keep compiler quiet */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -307,6 +327,9 @@ elog(int elevel, const char *fmt, ...)
|
|||||||
{
|
{
|
||||||
va_list args;
|
va_list args;
|
||||||
|
|
||||||
|
if (!debug && elevel <= LOG)
|
||||||
|
return;
|
||||||
|
|
||||||
switch (elevel)
|
switch (elevel)
|
||||||
{
|
{
|
||||||
case LOG:
|
case LOG:
|
||||||
@ -457,7 +480,8 @@ static void help(void)
|
|||||||
fprintf(stderr, " -p, --port=PORT database server port\n");
|
fprintf(stderr, " -p, --port=PORT database server port\n");
|
||||||
fprintf(stderr, " -U, --username=USERNAME user name to connect as\n");
|
fprintf(stderr, " -U, --username=USERNAME user name to connect as\n");
|
||||||
fprintf(stderr, " -W, --password force password prompt\n");
|
fprintf(stderr, " -W, --password force password prompt\n");
|
||||||
fprintf(stderr, "\nGeneric Options:\n");
|
fprintf(stderr, "\nGeneric options:\n");
|
||||||
|
fprintf(stderr, " --debug debug mode\n");
|
||||||
fprintf(stderr, " --help show this help, then exit\n");
|
fprintf(stderr, " --help show this help, then exit\n");
|
||||||
fprintf(stderr, " --version output version information, then exit\n\n");
|
fprintf(stderr, " --version output version information, then exit\n\n");
|
||||||
if (PROGRAM_URL)
|
if (PROGRAM_URL)
|
||||||
|
@ -30,8 +30,7 @@ typedef char bool;
|
|||||||
/*
|
/*
|
||||||
* pgut client variables and functions
|
* pgut client variables and functions
|
||||||
*/
|
*/
|
||||||
extern const char *pgut_optstring;
|
extern const struct option pgut_options[];
|
||||||
extern const struct option pgut_longopts[];
|
|
||||||
|
|
||||||
extern bool pgut_argument(int c, const char *arg);
|
extern bool pgut_argument(int c, const char *arg);
|
||||||
extern void pgut_help(void);
|
extern void pgut_help(void);
|
||||||
@ -51,15 +50,17 @@ extern const char *host;
|
|||||||
extern const char *port;
|
extern const char *port;
|
||||||
extern const char *username;
|
extern const char *username;
|
||||||
extern bool password;
|
extern bool password;
|
||||||
|
extern bool debug;
|
||||||
|
|
||||||
extern PGconn *connection;
|
extern PGconn *connection;
|
||||||
|
extern bool interrupted;
|
||||||
|
|
||||||
extern void parse_options(int argc, char **argv);
|
extern void parse_options(int argc, char **argv);
|
||||||
extern bool assign_option(const char **value, int c, const char *arg);
|
extern bool assign_option(const char **value, int c, const char *arg);
|
||||||
|
|
||||||
extern void reconnect(void);
|
extern void reconnect(void);
|
||||||
extern void disconnect(void);
|
extern void disconnect(void);
|
||||||
extern PGresult *execute_nothrow(const char *query, int nParams, const char **params);
|
extern PGresult *execute_elevel(const char *query, int nParams, const char **params, int elevel);
|
||||||
extern PGresult *execute(const char *query, int nParams, const char **params);
|
extern PGresult *execute(const char *query, int nParams, const char **params);
|
||||||
extern void command(const char *query, int nParams, const char **params);
|
extern void command(const char *query, int nParams, const char **params);
|
||||||
|
|
||||||
@ -87,6 +88,8 @@ __attribute__((format(printf, 2, 3)));
|
|||||||
/*
|
/*
|
||||||
* StringInfo
|
* StringInfo
|
||||||
*/
|
*/
|
||||||
|
#define STRINGINFO_H
|
||||||
|
|
||||||
#define StringInfoData PQExpBufferData
|
#define StringInfoData PQExpBufferData
|
||||||
#define StringInfo PQExpBuffer
|
#define StringInfo PQExpBuffer
|
||||||
#define makeStringInfo createPQExpBuffer
|
#define makeStringInfo createPQExpBuffer
|
||||||
@ -95,12 +98,29 @@ __attribute__((format(printf, 2, 3)));
|
|||||||
#define termStringInfo termPQExpBuffer
|
#define termStringInfo termPQExpBuffer
|
||||||
#define resetStringInfo resetPQExpBuffer
|
#define resetStringInfo resetPQExpBuffer
|
||||||
#define enlargeStringInfo enlargePQExpBuffer
|
#define enlargeStringInfo enlargePQExpBuffer
|
||||||
/*
|
#define printfStringInfo printfPQExpBuffer /* reset + append */
|
||||||
#define printfPQExpBuffer = resetStringInfo + appendStringInfo
|
|
||||||
*/
|
|
||||||
#define appendStringInfo appendPQExpBuffer
|
#define appendStringInfo appendPQExpBuffer
|
||||||
#define appendStringInfoString appendPQExpBufferStr
|
#define appendStringInfoString appendPQExpBufferStr
|
||||||
#define appendStringInfoChar appendPQExpBufferChar
|
#define appendStringInfoChar appendPQExpBufferChar
|
||||||
#define appendBinaryStringInfo appendBinaryPQExpBuffer
|
#define appendBinaryStringInfo appendBinaryPQExpBuffer
|
||||||
|
|
||||||
|
/*
|
||||||
|
* import from postgres.h and catalog/genbki.h in 8.4
|
||||||
|
*/
|
||||||
|
#if PG_VERSION_NUM < 80400
|
||||||
|
|
||||||
|
typedef unsigned long Datum;
|
||||||
|
typedef struct MemoryContextData *MemoryContext;
|
||||||
|
|
||||||
|
#define CATALOG(name,oid) typedef struct CppConcat(FormData_,name)
|
||||||
|
#define BKI_BOOTSTRAP
|
||||||
|
#define BKI_SHARED_RELATION
|
||||||
|
#define BKI_WITHOUT_OIDS
|
||||||
|
#define DATA(x) extern int no_such_variable
|
||||||
|
#define DESCR(x) extern int no_such_variable
|
||||||
|
#define SHDESCR(x) extern int no_such_variable
|
||||||
|
typedef int aclitem;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* PGUT_H */
|
#endif /* PGUT_H */
|
||||||
|
@ -30,7 +30,6 @@ pg_reorg -- PostgreSQLデータベース内のテーブルに対して、参照/
|
|||||||
<dd><tt>-U</tt> [<tt>--username</tt>] <tt><i>username</i></tt></dd>
|
<dd><tt>-U</tt> [<tt>--username</tt>] <tt><i>username</i></tt></dd>
|
||||||
<dd><tt>-W</tt> [<tt>--password</tt>]</dd>
|
<dd><tt>-W</tt> [<tt>--password</tt>]</dd>
|
||||||
<dt><tt>message-options</tt> : 出力メッセージ</dt>
|
<dt><tt>message-options</tt> : 出力メッセージ</dt>
|
||||||
<dd><tt>-e</tt> [<tt>--echo</tt>]</dd>
|
|
||||||
<dd><tt>-q</tt> [<tt>--quiet</tt>]</dd>
|
<dd><tt>-q</tt> [<tt>--quiet</tt>]</dd>
|
||||||
<dd><tt>-v</tt> [<tt>--verbose</tt>]</dd>
|
<dd><tt>-v</tt> [<tt>--verbose</tt>]</dd>
|
||||||
<dt><tt>order-options</tt> : 並び替えの基準</dt>
|
<dt><tt>order-options</tt> : 並び替えの基準</dt>
|
||||||
@ -40,6 +39,7 @@ pg_reorg -- PostgreSQLデータベース内のテーブルに対して、参照/
|
|||||||
<dd><tt>-a</tt> [<tt>--all</tt>]</dd>
|
<dd><tt>-a</tt> [<tt>--all</tt>]</dd>
|
||||||
<dd><tt>-d</tt> [<tt>--dbname</tt>] <tt><i>dbname</i></tt></dd>
|
<dd><tt>-d</tt> [<tt>--dbname</tt>] <tt><i>dbname</i></tt></dd>
|
||||||
<dd><tt>-t</tt> [<tt>--table</tt>] <tt><i>table</i></tt></dd>
|
<dd><tt>-t</tt> [<tt>--table</tt>] <tt><i>table</i></tt></dd>
|
||||||
|
<dd><tt>-Z</tt> [<tt>--no-analyze</tt>]</dd>
|
||||||
</dl>
|
</dl>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -57,7 +57,6 @@ pg_reorg -- PostgreSQLデータベース内のテーブルに対して、参照/
|
|||||||
<ul>
|
<ul>
|
||||||
<li>このユーティリティは、スーパーユーザのみが実行することができます。</li>
|
<li>このユーティリティは、スーパーユーザのみが実行することができます。</li>
|
||||||
<li>対象のテーブルはPRIMARY KEYを持っている必要があります。</li>
|
<li>対象のテーブルはPRIMARY KEYを持っている必要があります。</li>
|
||||||
<li>pg_reorg 実行後のデータの状態は、統計情報に反映されていません。統計情報を最新化するため、pg_reorg 実行後に<tt><a href="http://www.postgresql.jp/document/current/html/sql-analyze.html">ANALYZE</a></tt>を実行してください。</li>
|
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -108,8 +107,6 @@ pg_reorg を実行した際に任意のメッセージを出力するための
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
<dl>
|
<dl>
|
||||||
<dt><tt>-e</tt><br /><tt>--echo</tt></dt>
|
|
||||||
<dd>pg_reorg が生成し、サーバに送るコマンドをエコー表示します。</dd>
|
|
||||||
<dt><tt>-q</tt><br /><tt>--quiet</tt></dt>
|
<dt><tt>-q</tt><br /><tt>--quiet</tt></dt>
|
||||||
<dd>進行メッセージを表示しません。</dd>
|
<dd>進行メッセージを表示しません。</dd>
|
||||||
<dt><tt>-v</tt><br /><tt>--verbose</tt></dt>
|
<dt><tt>-v</tt><br /><tt>--verbose</tt></dt>
|
||||||
@ -157,6 +154,11 @@ pg_reorg を実行する対象を指定するパラメータです。
|
|||||||
<dd>オンライン CLUSTER 、または、オンライン VACUUM FULL を行うテーブルを指定します。
|
<dd>オンライン CLUSTER 、または、オンライン VACUUM FULL を行うテーブルを指定します。
|
||||||
このオプションが指定されていない場合は、対象となったデータベースに存在する全ての対象テーブルに対して処理を行います。
|
このオプションが指定されていない場合は、対象となったデータベースに存在する全ての対象テーブルに対して処理を行います。
|
||||||
</dd>
|
</dd>
|
||||||
|
|
||||||
|
<dt><tt>-Z</tt><br /><tt>--no-analyze</tt></dt>
|
||||||
|
<dd>再編成後に ANALYZE を行いません。
|
||||||
|
このオプションが指定されていない場合は、再編成後に ANALYZE します。</dd>
|
||||||
|
|
||||||
</dl>
|
</dl>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -29,7 +29,6 @@ See also <a href="#options">options</a> for details.</p>
|
|||||||
<dd><tt>-U</tt> [<tt>--username</tt>] <tt><i>username</i></tt></dd>
|
<dd><tt>-U</tt> [<tt>--username</tt>] <tt><i>username</i></tt></dd>
|
||||||
<dd><tt>-W</tt> [<tt>--password</tt>]</dd>
|
<dd><tt>-W</tt> [<tt>--password</tt>]</dd>
|
||||||
<dt><tt>message-options</tt></dt>
|
<dt><tt>message-options</tt></dt>
|
||||||
<dd><tt>-e</tt> [<tt>--echo</tt>]</dd>
|
|
||||||
<dd><tt>-q</tt> [<tt>--quiet</tt>]</dd>
|
<dd><tt>-q</tt> [<tt>--quiet</tt>]</dd>
|
||||||
<dd><tt>-v</tt> [<tt>--verbose</tt>]</dd>
|
<dd><tt>-v</tt> [<tt>--verbose</tt>]</dd>
|
||||||
<dt><tt>order-options</tt></dt>
|
<dt><tt>order-options</tt></dt>
|
||||||
@ -39,6 +38,7 @@ See also <a href="#options">options</a> for details.</p>
|
|||||||
<dd><tt>-a</tt> [<tt>--all</tt>]</dd>
|
<dd><tt>-a</tt> [<tt>--all</tt>]</dd>
|
||||||
<dd><tt>-d</tt> [<tt>--dbname</tt>] <tt><i>dbname</i></tt></dd>
|
<dd><tt>-d</tt> [<tt>--dbname</tt>] <tt><i>dbname</i></tt></dd>
|
||||||
<dd><tt>-t</tt> [<tt>--table</tt>] <tt><i>table</i></tt></dd>
|
<dd><tt>-t</tt> [<tt>--table</tt>] <tt><i>table</i></tt></dd>
|
||||||
|
<dd><tt>-Z</tt> [<tt>--no-analyze</tt>]</dd>
|
||||||
</dl>
|
</dl>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -57,7 +57,6 @@ You can choose one of the following methods to reorganize.</p>
|
|||||||
<ul>
|
<ul>
|
||||||
<li>Only superusers can use the utility.</li>
|
<li>Only superusers can use the utility.</li>
|
||||||
<li>Target table must have PRIMARY KEY.</li>
|
<li>Target table must have PRIMARY KEY.</li>
|
||||||
<li>You'd better to do <tt><a href="http://www.postgresql.jp/document/current/html/sql-analyze.html">ANALYZE</a></tt> after pg_reorg is completed.</li>
|
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -103,8 +102,6 @@ You can choose one of the following methods to reorganize.</p>
|
|||||||
<tt>--quiet</tt> is ignored if some of the other options are specified.</p>
|
<tt>--quiet</tt> is ignored if some of the other options are specified.</p>
|
||||||
|
|
||||||
<dl>
|
<dl>
|
||||||
<dt><tt>-e</tt><br /><tt>--echo</tt></dt>
|
|
||||||
<dd>Echo the commands that pg_reorg generates and sends to the server.</dd>
|
|
||||||
<dt><tt>-q</tt><br /><tt>--quiet</tt></dt>
|
<dt><tt>-q</tt><br /><tt>--quiet</tt></dt>
|
||||||
<dd>Do not display progress messages. </dd>
|
<dd>Do not display progress messages. </dd>
|
||||||
<dt><tt>-v</tt><br /><tt>--verbose</tt></dt>
|
<dt><tt>-v</tt><br /><tt>--verbose</tt></dt>
|
||||||
@ -148,6 +145,10 @@ You cannot use <tt>--all</tt> and <tt>--dbname</tt> or <tt>--table</tt> together
|
|||||||
<tt>--table</tt> <tt><i>table</i></tt>
|
<tt>--table</tt> <tt><i>table</i></tt>
|
||||||
</dt>
|
</dt>
|
||||||
<dd>Reorganize <tt><i>table</i></tt> only. If you don't specify this option, all tables in specified databases are reorganized.</dd>
|
<dd>Reorganize <tt><i>table</i></tt> only. If you don't specify this option, all tables in specified databases are reorganized.</dd>
|
||||||
|
|
||||||
|
<dt><tt>-Z</tt><br /><tt>--no-analyze</tt></dt>
|
||||||
|
<dd>Do ANALYZE after reorganization. If you don't specify this option, ANALYZE is performed automatically after reorg.</dd>
|
||||||
|
|
||||||
</dl>
|
</dl>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -11,6 +11,10 @@ BEGIN;
|
|||||||
|
|
||||||
CREATE SCHEMA reorg;
|
CREATE SCHEMA reorg;
|
||||||
|
|
||||||
|
CREATE FUNCTION reorg.version() RETURNS text AS
|
||||||
|
'MODULE_PATHNAME', 'reorg_version'
|
||||||
|
LANGUAGE 'C' IMMUTABLE STRICT;
|
||||||
|
|
||||||
CREATE AGGREGATE reorg.array_accum (
|
CREATE AGGREGATE reorg.array_accum (
|
||||||
sfunc = array_append,
|
sfunc = array_append,
|
||||||
basetype = anyelement,
|
basetype = anyelement,
|
||||||
@ -142,6 +146,17 @@ CREATE FUNCTION reorg.reorg_trigger() RETURNS trigger AS
|
|||||||
'MODULE_PATHNAME', 'reorg_trigger'
|
'MODULE_PATHNAME', 'reorg_trigger'
|
||||||
LANGUAGE 'C' VOLATILE STRICT SECURITY DEFINER;
|
LANGUAGE 'C' VOLATILE STRICT SECURITY DEFINER;
|
||||||
|
|
||||||
|
CREATE FUNCTION reorg.conflicted_triggers(oid) RETURNS SETOF name AS
|
||||||
|
$$
|
||||||
|
SELECT tgname FROM pg_trigger
|
||||||
|
WHERE tgrelid = $1 AND tgname >= 'z_reorg_trigger'
|
||||||
|
$$
|
||||||
|
LANGUAGE sql STABLE STRICT;
|
||||||
|
|
||||||
|
CREATE FUNCTION reorg.disable_autovacuum(regclass) RETURNS void AS
|
||||||
|
'MODULE_PATHNAME', 'reorg_disable_autovacuum'
|
||||||
|
LANGUAGE 'C' VOLATILE STRICT;
|
||||||
|
|
||||||
CREATE FUNCTION reorg.reorg_apply(
|
CREATE FUNCTION reorg.reorg_apply(
|
||||||
sql_peek cstring,
|
sql_peek cstring,
|
||||||
sql_insert cstring,
|
sql_insert cstring,
|
||||||
|
@ -67,6 +67,9 @@ extern text *cstring_to_text(const char *s);
|
|||||||
extern int SPI_execute_with_args(const char *src, int nargs, Oid *argtypes,
|
extern int SPI_execute_with_args(const char *src, int nargs, Oid *argtypes,
|
||||||
Datum *values, const char *nulls, bool read_only, long tcount);
|
Datum *values, const char *nulls, bool read_only, long tcount);
|
||||||
|
|
||||||
|
#define CStringGetTextDatum(s) PointerGetDatum(cstring_to_text(s))
|
||||||
|
#define TextDatumGetCString(d) text_to_cstring((text *) DatumGetPointer(d))
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* PGUT_BE_H */
|
#endif /* PGUT_BE_H */
|
||||||
|
52
lib/reorg.c
52
lib/reorg.c
@ -31,19 +31,23 @@
|
|||||||
|
|
||||||
PG_MODULE_MAGIC;
|
PG_MODULE_MAGIC;
|
||||||
|
|
||||||
|
Datum reorg_version(PG_FUNCTION_ARGS);
|
||||||
Datum reorg_trigger(PG_FUNCTION_ARGS);
|
Datum reorg_trigger(PG_FUNCTION_ARGS);
|
||||||
Datum reorg_apply(PG_FUNCTION_ARGS);
|
Datum reorg_apply(PG_FUNCTION_ARGS);
|
||||||
Datum reorg_get_index_keys(PG_FUNCTION_ARGS);
|
Datum reorg_get_index_keys(PG_FUNCTION_ARGS);
|
||||||
Datum reorg_indexdef(PG_FUNCTION_ARGS);
|
Datum reorg_indexdef(PG_FUNCTION_ARGS);
|
||||||
Datum reorg_swap(PG_FUNCTION_ARGS);
|
Datum reorg_swap(PG_FUNCTION_ARGS);
|
||||||
Datum reorg_drop(PG_FUNCTION_ARGS);
|
Datum reorg_drop(PG_FUNCTION_ARGS);
|
||||||
|
Datum reorg_disable_autovacuum(PG_FUNCTION_ARGS);
|
||||||
|
|
||||||
|
PG_FUNCTION_INFO_V1(reorg_version);
|
||||||
PG_FUNCTION_INFO_V1(reorg_trigger);
|
PG_FUNCTION_INFO_V1(reorg_trigger);
|
||||||
PG_FUNCTION_INFO_V1(reorg_apply);
|
PG_FUNCTION_INFO_V1(reorg_apply);
|
||||||
PG_FUNCTION_INFO_V1(reorg_get_index_keys);
|
PG_FUNCTION_INFO_V1(reorg_get_index_keys);
|
||||||
PG_FUNCTION_INFO_V1(reorg_indexdef);
|
PG_FUNCTION_INFO_V1(reorg_indexdef);
|
||||||
PG_FUNCTION_INFO_V1(reorg_swap);
|
PG_FUNCTION_INFO_V1(reorg_swap);
|
||||||
PG_FUNCTION_INFO_V1(reorg_drop);
|
PG_FUNCTION_INFO_V1(reorg_drop);
|
||||||
|
PG_FUNCTION_INFO_V1(reorg_disable_autovacuum);
|
||||||
|
|
||||||
static void reorg_init(void);
|
static void reorg_init(void);
|
||||||
static SPIPlanPtr reorg_prepare(const char *src, int nargs, Oid *argtypes);
|
static SPIPlanPtr reorg_prepare(const char *src, int nargs, Oid *argtypes);
|
||||||
@ -70,6 +74,12 @@ must_be_superuser(const char *func)
|
|||||||
static void RenameRelationInternal(Oid myrelid, const char *newrelname, Oid namespaceId);
|
static void RenameRelationInternal(Oid myrelid, const char *newrelname, Oid namespaceId);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
Datum
|
||||||
|
reorg_version(PG_FUNCTION_ARGS)
|
||||||
|
{
|
||||||
|
return CStringGetTextDatum("pg_reorg 1.0.5");
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @fn Datum reorg_trigger(PG_FUNCTION_ARGS)
|
* @fn Datum reorg_trigger(PG_FUNCTION_ARGS)
|
||||||
* @brief Insert a operation log into log-table.
|
* @brief Insert a operation log into log-table.
|
||||||
@ -274,7 +284,7 @@ typedef struct IndexDef
|
|||||||
} IndexDef;
|
} IndexDef;
|
||||||
|
|
||||||
static char *
|
static char *
|
||||||
generate_relation_name(Oid relid)
|
get_relation_name(Oid relid)
|
||||||
{
|
{
|
||||||
Oid nsp = get_rel_namespace(relid);
|
Oid nsp = get_rel_namespace(relid);
|
||||||
char *nspname;
|
char *nspname;
|
||||||
@ -380,7 +390,7 @@ parse_indexdef(IndexDef *stmt, Oid index, Oid table)
|
|||||||
{
|
{
|
||||||
char *sql = pg_get_indexdef_string(index);
|
char *sql = pg_get_indexdef_string(index);
|
||||||
const char *idxname = get_quoted_relname(index);
|
const char *idxname = get_quoted_relname(index);
|
||||||
const char *tblname = generate_relation_name(table);
|
const char *tblname = get_relation_name(table);
|
||||||
|
|
||||||
/* CREATE [UNIQUE] INDEX */
|
/* CREATE [UNIQUE] INDEX */
|
||||||
stmt->create = sql;
|
stmt->create = sql;
|
||||||
@ -646,6 +656,19 @@ reorg_drop(PG_FUNCTION_ARGS)
|
|||||||
"DROP TRIGGER IF EXISTS z_reorg_trigger ON %s.%s CASCADE",
|
"DROP TRIGGER IF EXISTS z_reorg_trigger ON %s.%s CASCADE",
|
||||||
nspname, relname);
|
nspname, relname);
|
||||||
|
|
||||||
|
#if PG_VERSION_NUM < 80400
|
||||||
|
/* delete autovacuum settings */
|
||||||
|
reorg_execf(
|
||||||
|
SPI_OK_DELETE,
|
||||||
|
"DELETE FROM pg_catalog.pg_autovacuum v"
|
||||||
|
" USING pg_class c, pg_namespace n"
|
||||||
|
" WHERE relname IN ('log_%u', 'table_%u')"
|
||||||
|
" AND n.nspname = 'reorg'"
|
||||||
|
" AND c.relnamespace = n.oid"
|
||||||
|
" AND v.vacrelid = c.oid",
|
||||||
|
oid, oid);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* drop log table */
|
/* drop log table */
|
||||||
reorg_execf(
|
reorg_execf(
|
||||||
SPI_OK_UTILITY,
|
SPI_OK_UTILITY,
|
||||||
@ -669,6 +692,31 @@ reorg_drop(PG_FUNCTION_ARGS)
|
|||||||
PG_RETURN_VOID();
|
PG_RETURN_VOID();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Datum
|
||||||
|
reorg_disable_autovacuum(PG_FUNCTION_ARGS)
|
||||||
|
{
|
||||||
|
Oid oid = PG_GETARG_OID(0);
|
||||||
|
|
||||||
|
/* connect to SPI manager */
|
||||||
|
reorg_init();
|
||||||
|
|
||||||
|
#if PG_VERSION_NUM >= 80400
|
||||||
|
reorg_execf(
|
||||||
|
SPI_OK_UTILITY,
|
||||||
|
"ALTER TABLE %s SET (autovacuum_enabled = off)",
|
||||||
|
get_relation_name(oid));
|
||||||
|
#else
|
||||||
|
reorg_execf(
|
||||||
|
SPI_OK_INSERT,
|
||||||
|
"INSERT INTO pg_catalog.pg_autovacuum VALUES (%u, false, -1, -1, -1, -1, -1, -1, -1, -1)",
|
||||||
|
oid);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
SPI_finish();
|
||||||
|
|
||||||
|
PG_RETURN_VOID();
|
||||||
|
}
|
||||||
|
|
||||||
/* init SPI */
|
/* init SPI */
|
||||||
static void
|
static void
|
||||||
reorg_init(void)
|
reorg_init(void)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user