pg_reorg version 1.1.0.
- Add wait-timeout option and use SET statement_timeout instead of NOWAIT. This can avoid infinite NOWAIT loops to reorganize heavily accessed tables. - Support native build with MSVC on Windows.
This commit is contained in:
parent
8392b9462a
commit
f3873ff55b
@ -3,7 +3,7 @@
|
|||||||
#
|
#
|
||||||
# Copyright (c) 2008-2010, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
# Copyright (c) 2008-2010, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
||||||
#
|
#
|
||||||
SRCS = pg_reorg.c pgut/pgut.c
|
SRCS = pg_reorg.c pgut/pgut.c pgut/pgut-fe.c
|
||||||
OBJS = $(SRCS:.c=.o)
|
OBJS = $(SRCS:.c=.o)
|
||||||
PROGRAM = pg_reorg
|
PROGRAM = pg_reorg
|
||||||
REGRESS = init reorg
|
REGRESS = init reorg
|
||||||
|
230
bin/pg_reorg.c
230
bin/pg_reorg.c
@ -8,15 +8,16 @@
|
|||||||
* @brief Client Modules
|
* @brief Client Modules
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const char *PROGRAM_VERSION = "1.0.8";
|
const char *PROGRAM_VERSION = "1.1.0";
|
||||||
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";
|
||||||
|
|
||||||
#include "pgut/pgut.h"
|
#include "pgut/pgut-fe.h"
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
#define APPLY_COUNT 1000
|
#define APPLY_COUNT 1000
|
||||||
|
|
||||||
@ -84,21 +85,22 @@ static void reorg_cleanup(bool fatal, void *userdata);
|
|||||||
|
|
||||||
static char *getstr(PGresult *res, int row, int col);
|
static char *getstr(PGresult *res, int row, int col);
|
||||||
static Oid getoid(PGresult *res, int row, int col);
|
static Oid getoid(PGresult *res, int row, int col);
|
||||||
|
static void lock_exclusive(const char *relid, const char *lock_query);
|
||||||
|
|
||||||
#define SQLSTATE_INVALID_SCHEMA_NAME "3F000"
|
#define SQLSTATE_INVALID_SCHEMA_NAME "3F000"
|
||||||
#define SQLSTATE_LOCK_NOT_AVAILABLE "55P03"
|
#define SQLSTATE_QUERY_CANCELED "57014"
|
||||||
|
|
||||||
static bool sqlstate_equals(PGresult *res, const char *state)
|
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 verbose = false;
|
|
||||||
static bool analyze = true;
|
static bool analyze = true;
|
||||||
static bool alldb = false;
|
static bool alldb = false;
|
||||||
static bool noorder = false;
|
static bool noorder = false;
|
||||||
static char *table = NULL;
|
static char *table = NULL;
|
||||||
static char *orderby = NULL;
|
static char *orderby = NULL;
|
||||||
|
static int wait_timeout = 60; /* in seconds */
|
||||||
|
|
||||||
/* buffer should have at least 11 bytes */
|
/* buffer should have at least 11 bytes */
|
||||||
static char *
|
static char *
|
||||||
@ -110,11 +112,11 @@ utoa(unsigned int value, char *buffer)
|
|||||||
|
|
||||||
static pgut_option options[] =
|
static pgut_option options[] =
|
||||||
{
|
{
|
||||||
{ 'b', 'v', "verbose", &verbose },
|
|
||||||
{ 'b', 'a', "all", &alldb },
|
{ 'b', 'a', "all", &alldb },
|
||||||
{ 's', 't', "table", &table },
|
{ 's', 't', "table", &table },
|
||||||
{ 'b', 'n', "no-order", &noorder },
|
{ 'b', 'n', "no-order", &noorder },
|
||||||
{ 's', 'o', "order-by", &orderby },
|
{ 's', 'o', "order-by", &orderby },
|
||||||
|
{ 'i', 'T', "wait-timeout", &wait_timeout },
|
||||||
{ 'B', 'Z', "no-analyze", &analyze },
|
{ 'B', 'Z', "no-analyze", &analyze },
|
||||||
{ 0 },
|
{ 0 },
|
||||||
};
|
};
|
||||||
@ -129,7 +131,9 @@ main(int argc, char *argv[])
|
|||||||
if (i == argc - 1)
|
if (i == argc - 1)
|
||||||
dbname = argv[i];
|
dbname = argv[i];
|
||||||
else if (i < argc)
|
else if (i < argc)
|
||||||
elog(ERROR_ARGS, "too many arguments");
|
ereport(ERROR,
|
||||||
|
(errcode(EINVAL),
|
||||||
|
errmsg("too many arguments")));
|
||||||
|
|
||||||
if (noorder)
|
if (noorder)
|
||||||
orderby = "";
|
orderby = "";
|
||||||
@ -137,13 +141,17 @@ main(int argc, char *argv[])
|
|||||||
if (alldb)
|
if (alldb)
|
||||||
{
|
{
|
||||||
if (table)
|
if (table)
|
||||||
elog(ERROR, "cannot reorg a specific table in all databases");
|
ereport(ERROR,
|
||||||
|
(errcode(EINVAL),
|
||||||
|
errmsg("cannot reorg a specific table in all databases")));
|
||||||
reorg_all_databases(orderby);
|
reorg_all_databases(orderby);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!reorg_one_database(orderby, table))
|
if (!reorg_one_database(orderby, table))
|
||||||
elog(ERROR, "%s is not installed", PROGRAM_NAME);
|
ereport(ERROR,
|
||||||
|
(errcode(ENOENT),
|
||||||
|
errmsg("%s is not installed", PROGRAM_NAME)));
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -159,7 +167,7 @@ reorg_all_databases(const char *orderby)
|
|||||||
int i;
|
int i;
|
||||||
|
|
||||||
dbname = "postgres";
|
dbname = "postgres";
|
||||||
reconnect();
|
reconnect(ERROR);
|
||||||
result = execute("SELECT datname FROM pg_database WHERE datallowconn ORDER BY 1;", 0, NULL);
|
result = execute("SELECT datname FROM pg_database WHERE datallowconn ORDER BY 1;", 0, NULL);
|
||||||
disconnect();
|
disconnect();
|
||||||
|
|
||||||
@ -169,7 +177,7 @@ reorg_all_databases(const char *orderby)
|
|||||||
|
|
||||||
dbname = PQgetvalue(result, i, 0);
|
dbname = PQgetvalue(result, i, 0);
|
||||||
|
|
||||||
if (!quiet)
|
if (pgut_log_level >= INFO)
|
||||||
{
|
{
|
||||||
printf("%s: reorg database \"%s\"", PROGRAM_NAME, dbname);
|
printf("%s: reorg database \"%s\"", PROGRAM_NAME, dbname);
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
@ -177,7 +185,7 @@ reorg_all_databases(const char *orderby)
|
|||||||
|
|
||||||
ret = reorg_one_database(orderby, NULL);
|
ret = reorg_one_database(orderby, NULL);
|
||||||
|
|
||||||
if (!quiet)
|
if (pgut_log_level >= INFO)
|
||||||
{
|
{
|
||||||
if (ret)
|
if (ret)
|
||||||
printf("\n");
|
printf("\n");
|
||||||
@ -223,7 +231,10 @@ reorg_one_database(const char *orderby, const char *table)
|
|||||||
|
|
||||||
initStringInfo(&sql);
|
initStringInfo(&sql);
|
||||||
|
|
||||||
reconnect();
|
reconnect(ERROR);
|
||||||
|
|
||||||
|
/* Disable statement timeout. */
|
||||||
|
command("SET statement_timeout = 0", 0, NULL);
|
||||||
|
|
||||||
/* Restrict search_path to system catalog. */
|
/* Restrict search_path to system catalog. */
|
||||||
command("SET search_path = pg_catalog, pg_temp, public", 0, NULL);
|
command("SET search_path = pg_catalog, pg_temp, public", 0, NULL);
|
||||||
@ -236,14 +247,14 @@ reorg_one_database(const char *orderby, const char *table)
|
|||||||
if (table)
|
if (table)
|
||||||
{
|
{
|
||||||
appendStringInfoString(&sql, "relid = $1::regclass");
|
appendStringInfoString(&sql, "relid = $1::regclass");
|
||||||
res = execute_elevel(sql.data, 1, &table, LOG);
|
res = execute_elevel(sql.data, 1, &table, DEBUG2);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
appendStringInfoString(&sql, "pkid IS NOT NULL");
|
appendStringInfoString(&sql, "pkid IS NOT NULL");
|
||||||
if (!orderby)
|
if (!orderby)
|
||||||
appendStringInfoString(&sql, " AND ckid IS NOT NULL");
|
appendStringInfoString(&sql, " AND ckid IS NOT NULL");
|
||||||
res = execute_elevel(sql.data, 0, NULL, LOG);
|
res = execute_elevel(sql.data, 0, NULL, DEBUG2);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (PQresultStatus(res) != PGRES_TUPLES_OK)
|
if (PQresultStatus(res) != PGRES_TUPLES_OK)
|
||||||
@ -280,7 +291,9 @@ reorg_one_database(const char *orderby, const char *table)
|
|||||||
table.ckid = getoid(res, i, c++);
|
table.ckid = getoid(res, i, c++);
|
||||||
|
|
||||||
if (table.pkid == 0)
|
if (table.pkid == 0)
|
||||||
elog(ERROR, "relation \"%s\" has no primary key", table.target_name);
|
ereport(ERROR,
|
||||||
|
(errcode(E_PG_COMMAND),
|
||||||
|
errmsg("relation \"%s\" has no primary key", table.target_name)));
|
||||||
|
|
||||||
table.create_pktype = getstr(res, i, c++);
|
table.create_pktype = getstr(res, i, c++);
|
||||||
table.create_log = getstr(res, i, c++);
|
table.create_log = getstr(res, i, c++);
|
||||||
@ -296,7 +309,9 @@ reorg_one_database(const char *orderby, const char *table)
|
|||||||
{
|
{
|
||||||
/* CLUSTER mode */
|
/* CLUSTER mode */
|
||||||
if (ckey == NULL)
|
if (ckey == NULL)
|
||||||
elog(ERROR, "relation \"%s\" has no cluster key", table.target_name);
|
ereport(ERROR,
|
||||||
|
(errcode(E_PG_COMMAND),
|
||||||
|
errmsg("relation \"%s\" has no cluster key", table.target_name)));
|
||||||
appendStringInfo(&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;
|
||||||
}
|
}
|
||||||
@ -367,35 +382,30 @@ reorg_one_table(const reorg_table *table, const char *orderby)
|
|||||||
|
|
||||||
initStringInfo(&sql);
|
initStringInfo(&sql);
|
||||||
|
|
||||||
if (verbose)
|
elog(DEBUG2, "---- reorg_one_table ----");
|
||||||
{
|
elog(DEBUG2, "target_name : %s", table->target_name);
|
||||||
fprintf(stderr, "---- reorg_one_table ----\n");
|
elog(DEBUG2, "target_oid : %u", table->target_oid);
|
||||||
fprintf(stderr, "target_name : %s\n", table->target_name);
|
elog(DEBUG2, "target_toast : %u", table->target_toast);
|
||||||
fprintf(stderr, "target_oid : %u\n", table->target_oid);
|
elog(DEBUG2, "target_tidx : %u", table->target_tidx);
|
||||||
fprintf(stderr, "target_toast : %u\n", table->target_toast);
|
elog(DEBUG2, "pkid : %u", table->pkid);
|
||||||
fprintf(stderr, "target_tidx : %u\n", table->target_tidx);
|
elog(DEBUG2, "ckid : %u", table->ckid);
|
||||||
fprintf(stderr, "pkid : %u\n", table->pkid);
|
elog(DEBUG2, "create_pktype : %s", table->create_pktype);
|
||||||
fprintf(stderr, "ckid : %u\n", table->ckid);
|
elog(DEBUG2, "create_log : %s", table->create_log);
|
||||||
fprintf(stderr, "create_pktype : %s\n", table->create_pktype);
|
elog(DEBUG2, "create_trigger : %s", table->create_trigger);
|
||||||
fprintf(stderr, "create_log : %s\n", table->create_log);
|
elog(DEBUG2, "create_table : %s", table->create_table);
|
||||||
fprintf(stderr, "create_trigger : %s\n", table->create_trigger);
|
elog(DEBUG2, "delete_log : %s", table->delete_log);
|
||||||
fprintf(stderr, "create_table : %s\n", table->create_table);
|
elog(DEBUG2, "lock_table : %s", table->lock_table);
|
||||||
fprintf(stderr, "delete_log : %s\n", table->delete_log);
|
elog(DEBUG2, "sql_peek : %s", table->sql_peek);
|
||||||
fprintf(stderr, "lock_table : %s\n", table->lock_table);
|
elog(DEBUG2, "sql_insert : %s", table->sql_insert);
|
||||||
fprintf(stderr, "sql_peek : %s\n", table->sql_peek);
|
elog(DEBUG2, "sql_delete : %s", table->sql_delete);
|
||||||
fprintf(stderr, "sql_insert : %s\n", table->sql_insert);
|
elog(DEBUG2, "sql_update : %s", table->sql_update);
|
||||||
fprintf(stderr, "sql_delete : %s\n", table->sql_delete);
|
elog(DEBUG2, "sql_pop : %s", table->sql_pop);
|
||||||
fprintf(stderr, "sql_update : %s\n", table->sql_update);
|
|
||||||
fprintf(stderr, "sql_pop : %s\n", table->sql_pop);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 1. Setup workspaces and a trigger.
|
* 1. Setup workspaces and a trigger.
|
||||||
*/
|
*/
|
||||||
if (verbose)
|
elog(DEBUG2, "---- setup ----");
|
||||||
fprintf(stderr, "---- setup ----\n");
|
lock_exclusive(utoa(table->target_oid, buffer), table->lock_table);
|
||||||
|
|
||||||
command("BEGIN ISOLATION LEVEL READ COMMITTED", 0, NULL);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check z_reorg_trigger is the trigger executed at last so that
|
* Check z_reorg_trigger is the trigger executed at last so that
|
||||||
@ -405,8 +415,10 @@ reorg_one_table(const reorg_table *table, const char *orderby)
|
|||||||
|
|
||||||
res = execute("SELECT reorg.conflicted_triggers($1)", 1, params);
|
res = execute("SELECT reorg.conflicted_triggers($1)", 1, params);
|
||||||
if (PQntuples(res) > 0)
|
if (PQntuples(res) > 0)
|
||||||
elog(ERROR, "trigger %s conflicted for %s",
|
ereport(ERROR,
|
||||||
PQgetvalue(res, 0, 0), table->target_name);
|
(errcode(E_PG_COMMAND),
|
||||||
|
errmsg("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);
|
||||||
@ -425,8 +437,7 @@ reorg_one_table(const reorg_table *table, const char *orderby)
|
|||||||
/*
|
/*
|
||||||
* 2. Copy tuples into temp table.
|
* 2. Copy tuples into temp table.
|
||||||
*/
|
*/
|
||||||
if (verbose)
|
elog(DEBUG2, "---- copy tuples ----");
|
||||||
fprintf(stderr, "---- copy tuples ----\n");
|
|
||||||
|
|
||||||
command("BEGIN ISOLATION LEVEL SERIALIZABLE", 0, NULL);
|
command("BEGIN ISOLATION LEVEL SERIALIZABLE", 0, NULL);
|
||||||
/* SET work_mem = maintenance_work_mem */
|
/* SET work_mem = maintenance_work_mem */
|
||||||
@ -445,8 +456,7 @@ reorg_one_table(const reorg_table *table, const char *orderby)
|
|||||||
/*
|
/*
|
||||||
* 3. Create indexes on temp table.
|
* 3. Create indexes on temp table.
|
||||||
*/
|
*/
|
||||||
if (verbose)
|
elog(DEBUG2, "---- create indexes ----");
|
||||||
fprintf(stderr, "---- create indexes ----\n");
|
|
||||||
|
|
||||||
params[0] = utoa(table->target_oid, buffer);
|
params[0] = utoa(table->target_oid, buffer);
|
||||||
res = execute("SELECT indexrelid,"
|
res = execute("SELECT indexrelid,"
|
||||||
@ -462,12 +472,9 @@ reorg_one_table(const reorg_table *table, const char *orderby)
|
|||||||
index.target_oid = getoid(res, i, c++);
|
index.target_oid = getoid(res, i, c++);
|
||||||
index.create_index = getstr(res, i, c++);
|
index.create_index = getstr(res, i, c++);
|
||||||
|
|
||||||
if (verbose)
|
elog(DEBUG2, "[%d]", i);
|
||||||
{
|
elog(DEBUG2, "target_oid : %u", index.target_oid);
|
||||||
fprintf(stderr, "[%d]\n", i);
|
elog(DEBUG2, "create_index : %s", index.create_index);
|
||||||
fprintf(stderr, "target_oid : %u\n", index.target_oid);
|
|
||||||
fprintf(stderr, "create_index : %s\n", index.create_index);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* NOTE: If we want to create multiple indexes in parallel,
|
* NOTE: If we want to create multiple indexes in parallel,
|
||||||
@ -506,35 +513,8 @@ reorg_one_table(const reorg_table *table, const char *orderby)
|
|||||||
/*
|
/*
|
||||||
* 5. Swap.
|
* 5. Swap.
|
||||||
*/
|
*/
|
||||||
if (verbose)
|
elog(DEBUG2, "---- swap ----");
|
||||||
fprintf(stderr, "---- swap ----\n");
|
lock_exclusive(utoa(table->target_oid, buffer), table->lock_table);
|
||||||
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
command("BEGIN ISOLATION LEVEL READ COMMITTED", 0, NULL);
|
|
||||||
res = execute_elevel(table->lock_table, 0, NULL, NOTICE);
|
|
||||||
if (PQresultStatus(res) == PGRES_COMMAND_OK)
|
|
||||||
{
|
|
||||||
PQclear(res);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else if (sqlstate_equals(res, SQLSTATE_LOCK_NOT_AVAILABLE))
|
|
||||||
{
|
|
||||||
/* retry if lock conflicted */
|
|
||||||
PQclear(res);
|
|
||||||
command("ROLLBACK", 0, NULL);
|
|
||||||
sleep(1);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* exit otherwise */
|
|
||||||
printf("%s", PQerrorMessage(connection));
|
|
||||||
PQclear(res);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
apply_log(table, 0);
|
apply_log(table, 0);
|
||||||
params[0] = utoa(table->target_oid, buffer);
|
params[0] = utoa(table->target_oid, buffer);
|
||||||
command("SELECT reorg.reorg_swap($1)", 1, params);
|
command("SELECT reorg.reorg_swap($1)", 1, params);
|
||||||
@ -543,8 +523,7 @@ reorg_one_table(const reorg_table *table, const char *orderby)
|
|||||||
/*
|
/*
|
||||||
* 6. Drop.
|
* 6. Drop.
|
||||||
*/
|
*/
|
||||||
if (verbose)
|
elog(DEBUG2, "---- drop ----");
|
||||||
fprintf(stderr, "---- drop ----\n");
|
|
||||||
|
|
||||||
command("BEGIN ISOLATION LEVEL READ COMMITTED", 0, NULL);
|
command("BEGIN ISOLATION LEVEL READ COMMITTED", 0, NULL);
|
||||||
params[0] = utoa(table->target_oid, buffer);
|
params[0] = utoa(table->target_oid, buffer);
|
||||||
@ -561,12 +540,10 @@ reorg_one_table(const reorg_table *table, const char *orderby)
|
|||||||
*/
|
*/
|
||||||
if (analyze)
|
if (analyze)
|
||||||
{
|
{
|
||||||
if (verbose)
|
elog(DEBUG2, "---- analyze ----");
|
||||||
fprintf(stderr, "---- analyze ----\n");
|
|
||||||
|
|
||||||
command("BEGIN ISOLATION LEVEL READ COMMITTED", 0, NULL);
|
command("BEGIN ISOLATION LEVEL READ COMMITTED", 0, NULL);
|
||||||
printfStringInfo(&sql, "ANALYZE %s%s",
|
printfStringInfo(&sql, "ANALYZE %s", table->target_name);
|
||||||
(verbose ? "VERBOSE " : ""), table->target_name);
|
|
||||||
command(sql.data, 0, NULL);
|
command(sql.data, 0, NULL);
|
||||||
command("COMMIT", 0, NULL);
|
command("COMMIT", 0, NULL);
|
||||||
}
|
}
|
||||||
@ -574,6 +551,79 @@ reorg_one_table(const reorg_table *table, const char *orderby)
|
|||||||
termStringInfo(&sql);
|
termStringInfo(&sql);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Try acquire a table lock but avoid long time locks when conflict.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
lock_exclusive(const char *relid, const char *lock_query)
|
||||||
|
{
|
||||||
|
time_t start = time(NULL);
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 1; ; i++)
|
||||||
|
{
|
||||||
|
time_t duration;
|
||||||
|
char sql[1024];
|
||||||
|
PGresult *res;
|
||||||
|
int wait_msec;
|
||||||
|
|
||||||
|
command("BEGIN ISOLATION LEVEL READ COMMITTED", 0, NULL);
|
||||||
|
|
||||||
|
duration = time(NULL) - start;
|
||||||
|
if (duration > wait_timeout)
|
||||||
|
{
|
||||||
|
const char *cancel_query;
|
||||||
|
if (PQserverVersion(connection) >= 80400 &&
|
||||||
|
duration > wait_timeout * 2)
|
||||||
|
{
|
||||||
|
elog(WARNING, "terminating conflicted backends");
|
||||||
|
cancel_query =
|
||||||
|
"SELECT pg_terminate_backend(pid) FROM pg_locks"
|
||||||
|
" WHERE locktype = 'relation'"
|
||||||
|
" AND relation = $1 AND pid <> pg_backend_pid()";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
elog(WARNING, "canceling conflicted backends");
|
||||||
|
cancel_query =
|
||||||
|
"SELECT pg_cancel_backend(pid) FROM pg_locks"
|
||||||
|
" WHERE locktype = 'relation'"
|
||||||
|
" AND relation = $1 AND pid <> pg_backend_pid()";
|
||||||
|
}
|
||||||
|
|
||||||
|
command(cancel_query, 1, &relid);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* wait for a while to lock the table. */
|
||||||
|
wait_msec = Min(1000, i * 100);
|
||||||
|
snprintf(sql, lengthof(sql), "SET LOCAL statement_timeout = %d", wait_msec);
|
||||||
|
command(sql, 0, NULL);
|
||||||
|
|
||||||
|
res = execute_elevel(lock_query, 0, NULL, DEBUG2);
|
||||||
|
if (PQresultStatus(res) == PGRES_COMMAND_OK)
|
||||||
|
{
|
||||||
|
PQclear(res);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (sqlstate_equals(res, SQLSTATE_QUERY_CANCELED))
|
||||||
|
{
|
||||||
|
/* retry if lock conflicted */
|
||||||
|
PQclear(res);
|
||||||
|
command("ROLLBACK", 0, NULL);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* exit otherwise */
|
||||||
|
printf("%s", PQerrorMessage(connection));
|
||||||
|
PQclear(res);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
command("RESET statement_timeout", 0, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The userdata pointing a table being re-organized. We need to cleanup temp
|
* The userdata pointing a table being re-organized. We need to cleanup temp
|
||||||
* objects before the program exits.
|
* objects before the program exits.
|
||||||
@ -598,7 +648,7 @@ reorg_cleanup(bool fatal, void *userdata)
|
|||||||
|
|
||||||
/* Try reconnection if not available. */
|
/* Try reconnection if not available. */
|
||||||
if (PQstatus(connection) != CONNECTION_OK)
|
if (PQstatus(connection) != CONNECTION_OK)
|
||||||
reconnect();
|
reconnect(ERROR);
|
||||||
|
|
||||||
/* do cleanup */
|
/* do cleanup */
|
||||||
params[0] = utoa(table->target_oid, buffer);
|
params[0] = utoa(table->target_oid, buffer);
|
||||||
@ -621,6 +671,6 @@ pgut_help(bool details)
|
|||||||
printf(" -t, --table=TABLE reorg specific table only\n");
|
printf(" -t, --table=TABLE reorg specific table only\n");
|
||||||
printf(" -n, --no-order do vacuum full instead of cluster\n");
|
printf(" -n, --no-order do vacuum full instead of cluster\n");
|
||||||
printf(" -o, --order-by=columns order by columns instead of cluster keys\n");
|
printf(" -o, --order-by=columns order by columns instead of cluster keys\n");
|
||||||
|
printf(" -T, --wait-timeout=secs timeout to cancel other backends on conflict.\n");
|
||||||
printf(" -Z, --no-analyze don't analyze at end\n");
|
printf(" -Z, --no-analyze don't analyze at end\n");
|
||||||
printf(" -v, --verbose display detailed information during processing\n");
|
|
||||||
}
|
}
|
||||||
|
687
bin/pgut/pgut-fe.c
Executable file
687
bin/pgut/pgut-fe.c
Executable file
@ -0,0 +1,687 @@
|
|||||||
|
/*-------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* pgut-fe.c
|
||||||
|
*
|
||||||
|
* Copyright (c) 2009-2010, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
||||||
|
*
|
||||||
|
*-------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define FRONTEND
|
||||||
|
#include "pgut-fe.h"
|
||||||
|
|
||||||
|
#ifdef HAVE_GETOPT_H
|
||||||
|
#include <getopt.h>
|
||||||
|
#else
|
||||||
|
#include <getopt_long.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
char *dbname = NULL;
|
||||||
|
char *host = NULL;
|
||||||
|
char *port = NULL;
|
||||||
|
char *username = NULL;
|
||||||
|
char *password = NULL;
|
||||||
|
YesNo prompt_password = DEFAULT;
|
||||||
|
|
||||||
|
PGconn *connection = NULL;
|
||||||
|
|
||||||
|
static bool parse_pair(const char buffer[], char key[], char value[]);
|
||||||
|
static char *get_username(void);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* the result is also available with the global variable 'connection'.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
reconnect(int elevel)
|
||||||
|
{
|
||||||
|
StringInfoData buf;
|
||||||
|
char *new_password;
|
||||||
|
|
||||||
|
disconnect();
|
||||||
|
initStringInfo(&buf);
|
||||||
|
if (dbname && dbname[0])
|
||||||
|
appendStringInfo(&buf, "dbname=%s ", dbname);
|
||||||
|
if (host && host[0])
|
||||||
|
appendStringInfo(&buf, "host=%s ", host);
|
||||||
|
if (port && port[0])
|
||||||
|
appendStringInfo(&buf, "port=%s ", port);
|
||||||
|
if (username && username[0])
|
||||||
|
appendStringInfo(&buf, "username=%s ", username);
|
||||||
|
if (password && password[0])
|
||||||
|
appendStringInfo(&buf, "password=%s ", password);
|
||||||
|
|
||||||
|
connection = pgut_connect(buf.data, prompt_password, elevel);
|
||||||
|
|
||||||
|
/* update password */
|
||||||
|
if (connection)
|
||||||
|
{
|
||||||
|
new_password = PQpass(connection);
|
||||||
|
if (new_password && (!password || strcmp(new_password, password)))
|
||||||
|
{
|
||||||
|
free(password);
|
||||||
|
password = new_password;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
termStringInfo(&buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
disconnect(void)
|
||||||
|
{
|
||||||
|
if (connection)
|
||||||
|
{
|
||||||
|
pgut_disconnect(connection);
|
||||||
|
connection = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
option_from_env(pgut_option options[])
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
for (i = 0; options && options[i].type; i++)
|
||||||
|
{
|
||||||
|
pgut_option *opt = &options[i];
|
||||||
|
char name[256];
|
||||||
|
size_t j;
|
||||||
|
const char *s;
|
||||||
|
const char *value;
|
||||||
|
|
||||||
|
if (opt->source > SOURCE_ENV ||
|
||||||
|
opt->allowed == SOURCE_DEFAULT || opt->allowed > SOURCE_ENV)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for (s = opt->lname, j = 0; *s && j < lengthof(name) - 1; s++, j++)
|
||||||
|
{
|
||||||
|
if (strchr("-_ ", *s))
|
||||||
|
name[j] = '_'; /* - to _ */
|
||||||
|
else
|
||||||
|
name[j] = toupper(*s);
|
||||||
|
}
|
||||||
|
name[j] = '\0';
|
||||||
|
|
||||||
|
if ((value = getenv(name)) != NULL)
|
||||||
|
pgut_setopt(opt, value, SOURCE_ENV);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* compare two strings ignore cases and ignore -_ */
|
||||||
|
bool
|
||||||
|
pgut_keyeq(const char *lhs, const char *rhs)
|
||||||
|
{
|
||||||
|
for (; *lhs && *rhs; lhs++, rhs++)
|
||||||
|
{
|
||||||
|
if (strchr("-_ ", *lhs))
|
||||||
|
{
|
||||||
|
if (!strchr("-_ ", *rhs))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else if (ToLower(*lhs) != ToLower(*rhs))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return *lhs == '\0' && *rhs == '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
pgut_setopt(pgut_option *opt, const char *optarg, pgut_optsrc src)
|
||||||
|
{
|
||||||
|
const char *message;
|
||||||
|
|
||||||
|
if (opt == NULL)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Try \"%s --help\" for more information.\n", PROGRAM_NAME);
|
||||||
|
exit(EINVAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opt->source > src)
|
||||||
|
{
|
||||||
|
/* high prior value has been set already. */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (src >= SOURCE_CMDLINE && opt->source >= src)
|
||||||
|
{
|
||||||
|
/* duplicated option in command line */
|
||||||
|
message = "specified only once";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* can be overwritten if non-command line source */
|
||||||
|
opt->source = src;
|
||||||
|
|
||||||
|
switch (opt->type)
|
||||||
|
{
|
||||||
|
case 'b':
|
||||||
|
case 'B':
|
||||||
|
if (optarg == NULL)
|
||||||
|
{
|
||||||
|
*((bool *) opt->var) = (opt->type == 'b');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (parse_bool(optarg, (bool *) opt->var))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
message = "a boolean";
|
||||||
|
break;
|
||||||
|
case 'f':
|
||||||
|
((pgut_optfn) opt->var)(opt, optarg);
|
||||||
|
return;
|
||||||
|
case 'i':
|
||||||
|
if (parse_int32(optarg, opt->var))
|
||||||
|
return;
|
||||||
|
message = "a 32bit signed integer";
|
||||||
|
break;
|
||||||
|
case 'u':
|
||||||
|
if (parse_uint32(optarg, opt->var))
|
||||||
|
return;
|
||||||
|
message = "a 32bit unsigned integer";
|
||||||
|
break;
|
||||||
|
case 'I':
|
||||||
|
if (parse_int64(optarg, opt->var))
|
||||||
|
return;
|
||||||
|
message = "a 64bit signed integer";
|
||||||
|
break;
|
||||||
|
case 'U':
|
||||||
|
if (parse_uint64(optarg, opt->var))
|
||||||
|
return;
|
||||||
|
message = "a 64bit unsigned integer";
|
||||||
|
break;
|
||||||
|
case 's':
|
||||||
|
if (opt->source != SOURCE_DEFAULT)
|
||||||
|
free(*(char **) opt->var);
|
||||||
|
*(char **) opt->var = pgut_strdup(optarg);
|
||||||
|
return;
|
||||||
|
case 't':
|
||||||
|
if (parse_time(optarg, opt->var))
|
||||||
|
return;
|
||||||
|
message = "a time";
|
||||||
|
break;
|
||||||
|
case 'y':
|
||||||
|
case 'Y':
|
||||||
|
if (optarg == NULL)
|
||||||
|
{
|
||||||
|
*(YesNo *) opt->var = (opt->type == 'y' ? YES : NO);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bool value;
|
||||||
|
if (parse_bool(optarg, &value))
|
||||||
|
{
|
||||||
|
*(YesNo *) opt->var = (value ? YES : NO);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
message = "a boolean";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ereport(ERROR,
|
||||||
|
(errcode(EINVAL),
|
||||||
|
errmsg("invalid option type: %c", opt->type)));
|
||||||
|
return; /* keep compiler quiet */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isprint(opt->sname))
|
||||||
|
ereport(ERROR,
|
||||||
|
(errcode(EINVAL),
|
||||||
|
errmsg("option -%c, --%s should be %s: '%s'",
|
||||||
|
opt->sname, opt->lname, message, optarg)));
|
||||||
|
else
|
||||||
|
ereport(ERROR,
|
||||||
|
(errcode(EINVAL),
|
||||||
|
errmsg("option --%s should be %s: '%s'",
|
||||||
|
opt->lname, message, optarg)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get configuration from configuration file.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
pgut_readopt(const char *path, pgut_option options[], int elevel)
|
||||||
|
{
|
||||||
|
FILE *fp;
|
||||||
|
char buf[1024];
|
||||||
|
char key[1024];
|
||||||
|
char value[1024];
|
||||||
|
|
||||||
|
if (!options)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if ((fp = pgut_fopen(path, "Rt")) == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
while (fgets(buf, lengthof(buf), fp))
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
for (i = strlen(buf); i > 0 && IsSpace(buf[i - 1]); i--)
|
||||||
|
buf[i - 1] = '\0';
|
||||||
|
|
||||||
|
if (parse_pair(buf, key, value))
|
||||||
|
{
|
||||||
|
for (i = 0; options[i].type; i++)
|
||||||
|
{
|
||||||
|
pgut_option *opt = &options[i];
|
||||||
|
|
||||||
|
if (pgut_keyeq(key, opt->lname))
|
||||||
|
{
|
||||||
|
if (opt->allowed == SOURCE_DEFAULT ||
|
||||||
|
opt->allowed > SOURCE_FILE)
|
||||||
|
elog(elevel, "option %s cannot specified in file", opt->lname);
|
||||||
|
else if (opt->source <= SOURCE_FILE)
|
||||||
|
pgut_setopt(opt, value, SOURCE_FILE);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!options[i].type)
|
||||||
|
elog(elevel, "invalid option \"%s\"", key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(fp);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *
|
||||||
|
skip_space(const char *str, const char *line)
|
||||||
|
{
|
||||||
|
while (IsSpace(*str)) { str++; }
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *
|
||||||
|
get_next_token(const char *src, char *dst, const char *line)
|
||||||
|
{
|
||||||
|
const char *s;
|
||||||
|
size_t i;
|
||||||
|
size_t j;
|
||||||
|
|
||||||
|
if ((s = skip_space(src, line)) == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/* parse quoted string */
|
||||||
|
if (*s == '\'')
|
||||||
|
{
|
||||||
|
s++;
|
||||||
|
for (i = 0, j = 0; s[i] != '\0'; i++)
|
||||||
|
{
|
||||||
|
if (s[i] == '\\')
|
||||||
|
{
|
||||||
|
i++;
|
||||||
|
switch (s[i])
|
||||||
|
{
|
||||||
|
case 'b':
|
||||||
|
dst[j] = '\b';
|
||||||
|
break;
|
||||||
|
case 'f':
|
||||||
|
dst[j] = '\f';
|
||||||
|
break;
|
||||||
|
case 'n':
|
||||||
|
dst[j] = '\n';
|
||||||
|
break;
|
||||||
|
case 'r':
|
||||||
|
dst[j] = '\r';
|
||||||
|
break;
|
||||||
|
case 't':
|
||||||
|
dst[j] = '\t';
|
||||||
|
break;
|
||||||
|
case '0':
|
||||||
|
case '1':
|
||||||
|
case '2':
|
||||||
|
case '3':
|
||||||
|
case '4':
|
||||||
|
case '5':
|
||||||
|
case '6':
|
||||||
|
case '7':
|
||||||
|
{
|
||||||
|
int k;
|
||||||
|
long octVal = 0;
|
||||||
|
|
||||||
|
for (k = 0;
|
||||||
|
s[i + k] >= '0' && s[i + k] <= '7' && k < 3;
|
||||||
|
k++)
|
||||||
|
octVal = (octVal << 3) + (s[i + k] - '0');
|
||||||
|
i += k - 1;
|
||||||
|
dst[j] = ((char) octVal);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
dst[j] = s[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (s[i] == '\'')
|
||||||
|
{
|
||||||
|
i++;
|
||||||
|
/* doubled quote becomes just one quote */
|
||||||
|
if (s[i] == '\'')
|
||||||
|
dst[j] = s[i];
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
dst[j] = s[i];
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
i = j = strcspn(s, "# \n\r\t\v");
|
||||||
|
memcpy(dst, s, j);
|
||||||
|
}
|
||||||
|
|
||||||
|
dst[j] = '\0';
|
||||||
|
return s + i;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
parse_pair(const char buffer[], char key[], char value[])
|
||||||
|
{
|
||||||
|
const char *start;
|
||||||
|
const char *end;
|
||||||
|
|
||||||
|
key[0] = value[0] = '\0';
|
||||||
|
|
||||||
|
/*
|
||||||
|
* parse key
|
||||||
|
*/
|
||||||
|
start = buffer;
|
||||||
|
if ((start = skip_space(start, buffer)) == NULL)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
end = start + strcspn(start, "=# \n\r\t\v");
|
||||||
|
|
||||||
|
/* skip blank buffer */
|
||||||
|
if (end - start <= 0)
|
||||||
|
{
|
||||||
|
if (*start == '=')
|
||||||
|
elog(WARNING, "syntax error in \"%s\"", buffer);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* key found */
|
||||||
|
strncpy(key, start, end - start);
|
||||||
|
key[end - start] = '\0';
|
||||||
|
|
||||||
|
/* find key and value split char */
|
||||||
|
if ((start = skip_space(end, buffer)) == NULL)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (*start != '=')
|
||||||
|
{
|
||||||
|
elog(WARNING, "syntax error in \"%s\"", buffer);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
start++;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* parse value
|
||||||
|
*/
|
||||||
|
if ((end = get_next_token(start, value, buffer)) == NULL)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if ((start = skip_space(end, buffer)) == NULL)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (*start != '\0' && *start != '#')
|
||||||
|
{
|
||||||
|
elog(WARNING, "syntax error in \"%s\"", buffer);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* execute - Execute a SQL and return the result.
|
||||||
|
*/
|
||||||
|
PGresult *
|
||||||
|
execute(const char *query, int nParams, const char **params)
|
||||||
|
{
|
||||||
|
return pgut_execute(connection, query, nParams, params);
|
||||||
|
}
|
||||||
|
|
||||||
|
PGresult *
|
||||||
|
execute_elevel(const char *query, int nParams, const char **params, int elevel)
|
||||||
|
{
|
||||||
|
return pgut_execute_elevel(connection, query, nParams, params, elevel);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* command - Execute a SQL and discard the result.
|
||||||
|
*/
|
||||||
|
ExecStatusType
|
||||||
|
command(const char *query, int nParams, const char **params)
|
||||||
|
{
|
||||||
|
return pgut_command(connection, query, nParams, params);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
set_elevel(pgut_option *opt, const char *arg)
|
||||||
|
{
|
||||||
|
pgut_log_level = parse_elevel(arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static pgut_option default_options[] =
|
||||||
|
{
|
||||||
|
{ 'b', 'e', "echo" , &pgut_echo },
|
||||||
|
{ 'f', 'E', "elevel" , set_elevel },
|
||||||
|
{ 's', 'd', "dbname" , &dbname },
|
||||||
|
{ 's', 'h', "host" , &host },
|
||||||
|
{ 's', 'p', "port" , &port },
|
||||||
|
{ 's', 'U', "username" , &username },
|
||||||
|
{ 'y', 'w', "no-password" , &prompt_password },
|
||||||
|
{ 'Y', 'W', "password" , &prompt_password },
|
||||||
|
{ 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
static size_t
|
||||||
|
option_length(const pgut_option opts[])
|
||||||
|
{
|
||||||
|
size_t len;
|
||||||
|
for (len = 0; opts && opts[len].type; len++) { }
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
static pgut_option *
|
||||||
|
option_find(int c, pgut_option opts1[], pgut_option opts2[])
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
for (i = 0; opts1 && opts1[i].type; i++)
|
||||||
|
if (opts1[i].sname == c)
|
||||||
|
return &opts1[i];
|
||||||
|
for (i = 0; opts2 && opts2[i].type; i++)
|
||||||
|
if (opts2[i].sname == c)
|
||||||
|
return &opts2[i];
|
||||||
|
|
||||||
|
return NULL; /* not found */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns the current user name.
|
||||||
|
*/
|
||||||
|
static char *
|
||||||
|
get_username(void)
|
||||||
|
{
|
||||||
|
char *ret;
|
||||||
|
|
||||||
|
#ifndef WIN32
|
||||||
|
struct passwd *pw;
|
||||||
|
|
||||||
|
pw = getpwuid(geteuid());
|
||||||
|
ret = (pw ? pw->pw_name : NULL);
|
||||||
|
#else
|
||||||
|
static char username[128]; /* remains after function execute */
|
||||||
|
DWORD len = sizeof(username) - 1;
|
||||||
|
|
||||||
|
if (GetUserNameA(username, &len))
|
||||||
|
ret = username;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_dosmaperr(GetLastError());
|
||||||
|
ret = NULL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (ret == NULL)
|
||||||
|
ereport(ERROR,
|
||||||
|
(errcode_errno(),
|
||||||
|
errmsg("could not get current user name: ")));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
option_has_arg(char type)
|
||||||
|
{
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case 'b':
|
||||||
|
case 'B':
|
||||||
|
case 'y':
|
||||||
|
case 'Y':
|
||||||
|
return no_argument;
|
||||||
|
default:
|
||||||
|
return required_argument;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
option_copy(struct option dst[], const pgut_option opts[], size_t len)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
for (i = 0; i < len; i++)
|
||||||
|
{
|
||||||
|
dst[i].name = opts[i].lname;
|
||||||
|
dst[i].has_arg = option_has_arg(opts[i].type);
|
||||||
|
dst[i].flag = NULL;
|
||||||
|
dst[i].val = opts[i].sname;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct option *
|
||||||
|
option_merge(const pgut_option opts1[], const pgut_option opts2[])
|
||||||
|
{
|
||||||
|
struct option *result;
|
||||||
|
size_t len1 = option_length(opts1);
|
||||||
|
size_t len2 = option_length(opts2);
|
||||||
|
size_t n = len1 + len2;
|
||||||
|
|
||||||
|
result = pgut_newarray(struct option, n + 1);
|
||||||
|
option_copy(result, opts1, len1);
|
||||||
|
option_copy(result + len1, opts2, len2);
|
||||||
|
memset(&result[n], 0, sizeof(pgut_option));
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *
|
||||||
|
longopts_to_optstring(const struct option opts[])
|
||||||
|
{
|
||||||
|
size_t len;
|
||||||
|
char *result;
|
||||||
|
char *s;
|
||||||
|
|
||||||
|
for (len = 0; opts[len].name; len++) { }
|
||||||
|
result = pgut_malloc(len * 2 + 1);
|
||||||
|
|
||||||
|
s = result;
|
||||||
|
for (len = 0; opts[len].name; len++)
|
||||||
|
{
|
||||||
|
if (!isprint(opts[len].val))
|
||||||
|
continue;
|
||||||
|
*s++ = opts[len].val;
|
||||||
|
if (opts[len].has_arg != no_argument)
|
||||||
|
*s++ = ':';
|
||||||
|
}
|
||||||
|
*s = '\0';
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
pgut_getopt(int argc, char **argv, pgut_option options[])
|
||||||
|
{
|
||||||
|
int c;
|
||||||
|
int optindex = 0;
|
||||||
|
char *optstring;
|
||||||
|
struct option *longopts;
|
||||||
|
pgut_option *opt;
|
||||||
|
|
||||||
|
pgut_init(argc, argv);
|
||||||
|
|
||||||
|
/* Help message and version are handled at first. */
|
||||||
|
if (argc > 1)
|
||||||
|
{
|
||||||
|
if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") == 0)
|
||||||
|
{
|
||||||
|
help(true);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
if (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-V") == 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "%s %s\n", PROGRAM_NAME, PROGRAM_VERSION);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Merge default and user options. */
|
||||||
|
longopts = option_merge(default_options, options);
|
||||||
|
optstring = longopts_to_optstring(longopts);
|
||||||
|
|
||||||
|
/* Assign named options */
|
||||||
|
while ((c = getopt_long(argc, argv, optstring, longopts, &optindex)) != -1)
|
||||||
|
{
|
||||||
|
opt = option_find(c, default_options, options);
|
||||||
|
pgut_setopt(opt, optarg, SOURCE_CMDLINE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read environment variables */
|
||||||
|
option_from_env(options);
|
||||||
|
(void) (dbname ||
|
||||||
|
(dbname = getenv("PGDATABASE")) ||
|
||||||
|
(dbname = getenv("PGUSER")) ||
|
||||||
|
(dbname = get_username()));
|
||||||
|
|
||||||
|
return optind;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
help(bool details)
|
||||||
|
{
|
||||||
|
pgut_help(details);
|
||||||
|
|
||||||
|
if (details)
|
||||||
|
{
|
||||||
|
printf("\nConnection options:\n");
|
||||||
|
printf(" -d, --dbname=DBNAME database to connect\n");
|
||||||
|
printf(" -h, --host=HOSTNAME database server host or socket directory\n");
|
||||||
|
printf(" -p, --port=PORT database server port\n");
|
||||||
|
printf(" -U, --username=USERNAME user name to connect as\n");
|
||||||
|
printf(" -w, --no-password never prompt for password\n");
|
||||||
|
printf(" -W, --password force password prompt\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\nGeneric options:\n");
|
||||||
|
if (details)
|
||||||
|
{
|
||||||
|
printf(" -e, --echo echo queries\n");
|
||||||
|
printf(" -E, --elevel=LEVEL set output message level\n");
|
||||||
|
}
|
||||||
|
printf(" --help show this help, then exit\n");
|
||||||
|
printf(" --version output version information, then exit\n");
|
||||||
|
|
||||||
|
if (details && (PROGRAM_URL || PROGRAM_EMAIL))
|
||||||
|
{
|
||||||
|
printf("\n");
|
||||||
|
if (PROGRAM_URL)
|
||||||
|
printf("Read the website for details. <%s>\n", PROGRAM_URL);
|
||||||
|
if (PROGRAM_EMAIL)
|
||||||
|
printf("Report bugs to <%s>.\n", PROGRAM_EMAIL);
|
||||||
|
}
|
||||||
|
}
|
74
bin/pgut/pgut-fe.h
Executable file
74
bin/pgut/pgut-fe.h
Executable file
@ -0,0 +1,74 @@
|
|||||||
|
/*-------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* pgut-fe.h
|
||||||
|
*
|
||||||
|
* Copyright (c) 2009-2010, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
||||||
|
*
|
||||||
|
*-------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef PGUT_FE_H
|
||||||
|
#define PGUT_FE_H
|
||||||
|
|
||||||
|
#include "pgut.h"
|
||||||
|
|
||||||
|
typedef enum pgut_optsrc
|
||||||
|
{
|
||||||
|
SOURCE_DEFAULT,
|
||||||
|
SOURCE_ENV,
|
||||||
|
SOURCE_FILE,
|
||||||
|
SOURCE_CMDLINE,
|
||||||
|
SOURCE_CONST
|
||||||
|
} pgut_optsrc;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* type:
|
||||||
|
* b: bool (true)
|
||||||
|
* B: bool (false)
|
||||||
|
* f: pgut_optfn
|
||||||
|
* i: 32bit signed integer
|
||||||
|
* u: 32bit unsigned integer
|
||||||
|
* I: 64bit signed integer
|
||||||
|
* U: 64bit unsigned integer
|
||||||
|
* s: string
|
||||||
|
* t: time_t
|
||||||
|
* y: YesNo (YES)
|
||||||
|
* Y: YesNo (NO)
|
||||||
|
*/
|
||||||
|
typedef struct pgut_option
|
||||||
|
{
|
||||||
|
char type;
|
||||||
|
char sname; /* short name */
|
||||||
|
const char *lname; /* long name */
|
||||||
|
void *var; /* pointer to variable */
|
||||||
|
pgut_optsrc allowed; /* allowed source */
|
||||||
|
pgut_optsrc source; /* actual source */
|
||||||
|
} pgut_option;
|
||||||
|
|
||||||
|
typedef void (*pgut_optfn) (pgut_option *opt, const char *arg);
|
||||||
|
|
||||||
|
|
||||||
|
extern char *dbname;
|
||||||
|
extern char *host;
|
||||||
|
extern char *port;
|
||||||
|
extern char *username;
|
||||||
|
extern char *password;
|
||||||
|
extern YesNo prompt_password;
|
||||||
|
|
||||||
|
extern PGconn *connection;
|
||||||
|
|
||||||
|
extern void pgut_help(bool details);
|
||||||
|
extern void help(bool details);
|
||||||
|
|
||||||
|
extern void disconnect(void);
|
||||||
|
extern void reconnect(int elevel);
|
||||||
|
extern PGresult *execute(const char *query, int nParams, const char **params);
|
||||||
|
extern PGresult *execute_elevel(const char *query, int nParams, const char **params, int elevel);
|
||||||
|
extern ExecStatusType command(const char *query, int nParams, const char **params);
|
||||||
|
|
||||||
|
extern int pgut_getopt(int argc, char **argv, pgut_option options[]);
|
||||||
|
extern void pgut_readopt(const char *path, pgut_option options[], int elevel);
|
||||||
|
extern void pgut_setopt(pgut_option *opt, const char *optarg, pgut_optsrc src);
|
||||||
|
extern bool pgut_keyeq(const char *lhs, const char *rhs);
|
||||||
|
|
||||||
|
#endif /* PGUT_FE_H */
|
1394
bin/pgut/pgut.c
1394
bin/pgut/pgut.c
File diff suppressed because it is too large
Load Diff
146
bin/pgut/pgut.h
146
bin/pgut/pgut.h
@ -11,23 +11,16 @@
|
|||||||
#define PGUT_H
|
#define PGUT_H
|
||||||
|
|
||||||
#include "c.h"
|
#include "c.h"
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#ifndef WIN32
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "libpq-fe.h"
|
#include "libpq-fe.h"
|
||||||
#include "pqexpbuffer.h"
|
#include "pqexpbuffer.h"
|
||||||
|
#include "utils/elog.h"
|
||||||
#include <assert.h>
|
|
||||||
#include <sys/time.h>
|
|
||||||
|
|
||||||
#if !defined(C_H) && !defined(__cplusplus)
|
|
||||||
#ifndef bool
|
|
||||||
typedef char bool;
|
|
||||||
#endif
|
|
||||||
#ifndef true
|
|
||||||
#define true ((bool) 1)
|
|
||||||
#endif
|
|
||||||
#ifndef false
|
|
||||||
#define false ((bool) 0)
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define INFINITE_STR "INFINITE"
|
#define INFINITE_STR "INFINITE"
|
||||||
|
|
||||||
@ -38,40 +31,6 @@ typedef enum YesNo
|
|||||||
YES
|
YES
|
||||||
} YesNo;
|
} YesNo;
|
||||||
|
|
||||||
typedef enum pgut_optsrc
|
|
||||||
{
|
|
||||||
SOURCE_DEFAULT,
|
|
||||||
SOURCE_ENV,
|
|
||||||
SOURCE_FILE,
|
|
||||||
SOURCE_CMDLINE,
|
|
||||||
SOURCE_CONST
|
|
||||||
} pgut_optsrc;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* type:
|
|
||||||
* b: bool (true)
|
|
||||||
* B: bool (false)
|
|
||||||
* f: pgut_optfn
|
|
||||||
* i: 32bit signed integer
|
|
||||||
* u: 32bit unsigned integer
|
|
||||||
* I: 64bit signed integer
|
|
||||||
* U: 64bit unsigned integer
|
|
||||||
* s: string
|
|
||||||
* t: time_t
|
|
||||||
* y: YesNo (YES)
|
|
||||||
* Y: YesNo (NO)
|
|
||||||
*/
|
|
||||||
typedef struct pgut_option
|
|
||||||
{
|
|
||||||
char type;
|
|
||||||
char sname; /* short name */
|
|
||||||
const char *lname; /* long name */
|
|
||||||
void *var; /* pointer to variable */
|
|
||||||
pgut_optsrc allowed; /* allowed source */
|
|
||||||
pgut_optsrc source; /* actual source */
|
|
||||||
} pgut_option;
|
|
||||||
|
|
||||||
typedef void (*pgut_optfn) (pgut_option *opt, const char *arg);
|
|
||||||
typedef void (*pgut_atexit_callback)(bool fatal, void *userdata);
|
typedef void (*pgut_atexit_callback)(bool fatal, void *userdata);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -82,52 +41,33 @@ extern const char *PROGRAM_VERSION;
|
|||||||
extern const char *PROGRAM_URL;
|
extern const char *PROGRAM_URL;
|
||||||
extern const char *PROGRAM_EMAIL;
|
extern const char *PROGRAM_EMAIL;
|
||||||
|
|
||||||
extern void pgut_help(bool details);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* pgut framework variables and functions
|
* pgut framework variables and functions
|
||||||
*/
|
*/
|
||||||
extern const char *dbname;
|
extern bool interrupted;
|
||||||
extern const char *host;
|
extern int pgut_log_level;
|
||||||
extern const char *port;
|
extern int pgut_abort_level;
|
||||||
extern const char *username;
|
extern bool pgut_echo;
|
||||||
extern char *password;
|
|
||||||
extern bool debug;
|
|
||||||
extern bool quiet;
|
|
||||||
|
|
||||||
#ifndef PGUT_NO_PROMPT
|
extern void pgut_init(int argc, char **argv);
|
||||||
extern YesNo prompt_password;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
extern PGconn *connection;
|
|
||||||
extern bool interrupted;
|
|
||||||
|
|
||||||
extern void help(bool details);
|
|
||||||
extern int pgut_getopt(int argc, char **argv, pgut_option options[]);
|
|
||||||
extern void pgut_readopt(const char *path, pgut_option options[], int elevel);
|
|
||||||
extern void pgut_setopt(pgut_option *opt, const char *optarg, pgut_optsrc src);
|
|
||||||
extern bool pgut_keyeq(const char *lhs, const char *rhs);
|
|
||||||
extern void pgut_atexit_push(pgut_atexit_callback callback, void *userdata);
|
extern void pgut_atexit_push(pgut_atexit_callback callback, void *userdata);
|
||||||
extern void pgut_atexit_pop(pgut_atexit_callback callback, void *userdata);
|
extern void pgut_atexit_pop(pgut_atexit_callback callback, void *userdata);
|
||||||
|
extern void pgut_putenv(const char *key, const char *value);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Database connections
|
* Database connections
|
||||||
*/
|
*/
|
||||||
extern PGconn *pgut_connect(int elevel);
|
extern PGconn *pgut_connect(const char *info, YesNo prompt, int elevel);
|
||||||
extern PGconn *pgut_connectdb(const char *conninfo, int elevel);
|
|
||||||
extern void pgut_disconnect(PGconn *conn);
|
extern void pgut_disconnect(PGconn *conn);
|
||||||
extern PGresult *pgut_execute(PGconn* conn, const char *query, int nParams, const char **params, int elevel);
|
extern void pgut_disconnect_all(void);
|
||||||
extern ExecStatusType pgut_command(PGconn* conn, const char *query, int nParams, const char **params, int elevel);
|
extern PGresult *pgut_execute(PGconn* conn, const char *query, int nParams, const char **params);
|
||||||
extern bool pgut_send(PGconn* conn, const char *query, int nParams, const char **params, int elevel);
|
PGresult *pgut_execute_elevel(PGconn* conn, const char *query, int nParams, const char **params, int elevel);
|
||||||
|
extern ExecStatusType pgut_command(PGconn* conn, const char *query, int nParams, const char **params);
|
||||||
|
extern bool pgut_commit(PGconn *conn);
|
||||||
|
extern void pgut_rollback(PGconn *conn);
|
||||||
|
extern bool pgut_send(PGconn* conn, const char *query, int nParams, const char **params);
|
||||||
extern int pgut_wait(int num, PGconn *connections[], struct timeval *timeout);
|
extern int pgut_wait(int num, PGconn *connections[], struct timeval *timeout);
|
||||||
|
|
||||||
extern PGconn *reconnect_elevel(int elevel);
|
|
||||||
extern void reconnect(void);
|
|
||||||
extern void disconnect(void);
|
|
||||||
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 void command(const char *query, int nParams, const char **params);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* memory allocators
|
* memory allocators
|
||||||
*/
|
*/
|
||||||
@ -139,37 +79,38 @@ extern char *strdup_trim(const char *str);
|
|||||||
|
|
||||||
#define pgut_new(type) ((type *) pgut_malloc(sizeof(type)))
|
#define pgut_new(type) ((type *) pgut_malloc(sizeof(type)))
|
||||||
#define pgut_newarray(type, n) ((type *) pgut_malloc(sizeof(type) * (n)))
|
#define pgut_newarray(type, n) ((type *) pgut_malloc(sizeof(type) * (n)))
|
||||||
|
#define pgut_newvar(type, m, n) ((type *) pgut_malloc(offsetof(type, m) + (n)))
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* file operations
|
* file operations
|
||||||
*/
|
*/
|
||||||
extern FILE *pgut_fopen(const char *path, const char *mode, bool missing_ok);
|
extern FILE *pgut_fopen(const char *path, const char *mode);
|
||||||
extern void pgut_mkdir(const char *path);
|
extern bool pgut_mkdir(const char *path);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* elog
|
* elog
|
||||||
*/
|
*/
|
||||||
#define LOG (-4)
|
#define E_PG_CONNECT (-1) /* PostgreSQL connection error */
|
||||||
#define INFO (-3)
|
#define E_PG_COMMAND (-2) /* PostgreSQL query or command error */
|
||||||
#define NOTICE (-2)
|
|
||||||
#define WARNING (-1)
|
|
||||||
#define HELP 1
|
|
||||||
#define ERROR 2
|
|
||||||
#define FATAL 3
|
|
||||||
#define PANIC 4
|
|
||||||
|
|
||||||
#define ERROR_SYSTEM 10 /* I/O or system error */
|
|
||||||
#define ERROR_NOMEM 11 /* memory exhausted */
|
|
||||||
#define ERROR_ARGS 12 /* some configurations are invalid */
|
|
||||||
#define ERROR_INTERRUPTED 13 /* interrupted by signal */
|
|
||||||
#define ERROR_PG_COMMAND 14 /* PostgreSQL query or command error */
|
|
||||||
#define ERROR_PG_CONNECT 15 /* PostgreSQL connection error */
|
|
||||||
|
|
||||||
#undef elog
|
#undef elog
|
||||||
extern void
|
#undef ereport
|
||||||
elog(int elevel, const char *fmt, ...)
|
#define ereport(elevel, rest) \
|
||||||
__attribute__((format(printf, 2, 3)));
|
(pgut_errstart(elevel) ? (pgut_errfinish rest) : (void) 0)
|
||||||
|
|
||||||
|
extern void elog(int elevel, const char *fmt, ...)
|
||||||
|
__attribute__((format(printf, 2, 3)));
|
||||||
|
extern const char *format_elevel(int elevel);
|
||||||
|
extern int parse_elevel(const char *value);
|
||||||
|
extern int errcode_errno(void);
|
||||||
|
extern bool log_required(int elevel, int log_min_level);
|
||||||
|
extern bool pgut_errstart(int elevel);
|
||||||
|
extern void pgut_errfinish(int dummy, ...);
|
||||||
|
extern void pgut_error(int elevel, int code, const char *msg, const char *detail);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* CHECK_FOR_INTERRUPTS
|
||||||
|
*/
|
||||||
#undef CHECK_FOR_INTERRUPTS
|
#undef CHECK_FOR_INTERRUPTS
|
||||||
extern void CHECK_FOR_INTERRUPTS(void);
|
extern void CHECK_FOR_INTERRUPTS(void);
|
||||||
|
|
||||||
@ -209,6 +150,7 @@ extern void CHECK_FOR_INTERRUPTS(void);
|
|||||||
#define appendStringInfoChar appendPQExpBufferChar
|
#define appendStringInfoChar appendPQExpBufferChar
|
||||||
#define appendBinaryStringInfo appendBinaryPQExpBuffer
|
#define appendBinaryStringInfo appendBinaryPQExpBuffer
|
||||||
|
|
||||||
|
extern bool appendStringInfoVA(StringInfo str, const char *fmt, va_list args);
|
||||||
extern int appendStringInfoFile(StringInfo str, FILE *fp);
|
extern int appendStringInfoFile(StringInfo str, FILE *fp);
|
||||||
extern int appendStringInfoFd(StringInfo str, int fd);
|
extern int appendStringInfoFd(StringInfo str, int fd);
|
||||||
|
|
||||||
|
@ -17,11 +17,21 @@
|
|||||||
<h1>pg_reorg ホームページへようこそ</h1>
|
<h1>pg_reorg ホームページへようこそ</h1>
|
||||||
<hr />
|
<hr />
|
||||||
</center>
|
</center>
|
||||||
|
|
||||||
|
<p>このプロジェクトでは <strong>pg_reorg</strong> と <strong>pg_batch</strong> の2つのツールを頒布しています。</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
pg_reorg は PostgreSQL のテーブルを再編成するシェルコマンドです。
|
<strong>pg_reorg</strong> は PostgreSQL のテーブルを再編成するシェルコマンドです。
|
||||||
共有ロックや排他ロックを取得しないため、再編成中であっても行の参照や更新を行うことができます。
|
共有ロックや排他ロックを取得しないため、再編成中であっても行の参照や更新を行うことができます。
|
||||||
このモジュールは CLUSTER や VACUUM FULL コマンドのより良い代替になります。
|
このモジュールは CLUSTER や VACUUM FULL コマンドのより良い代替になります。
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<strong>pg_batch</strong> は PostgreSQL のためのSQLジョブ実行プログラムです。
|
||||||
|
ジョブ一覧生成するスクリプトを SQL として外部から与え、その出力 SQL をジョブとしてシリアルまたはパラレルに実行します。
|
||||||
|
VACUUM を行うスクリプトが付属しており、"より良い vacuumdb" として利用できます。
|
||||||
|
</p>
|
||||||
|
|
||||||
<p>この pg_reorg プロジェクトは <a href="http://www.postgresql.org">PostgreSQL</a> コミュニティによる <a href="http://pgfoundry.org">pgFoundry</a> の中の<a href="http://pgfoundry.org/projects/reorg">プロジェクト</a>です。</p>
|
<p>この pg_reorg プロジェクトは <a href="http://www.postgresql.org">PostgreSQL</a> コミュニティによる <a href="http://pgfoundry.org">pgFoundry</a> の中の<a href="http://pgfoundry.org/projects/reorg">プロジェクト</a>です。</p>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="http://pgfoundry.org/frs/?group_id=1000411">ダウンロード</a> : ソースコードのほか、Windows 用バイナリもダウンロードできます。</li>
|
<li><a href="http://pgfoundry.org/frs/?group_id=1000411">ダウンロード</a> : ソースコードのほか、Windows 用バイナリもダウンロードできます。</li>
|
||||||
@ -34,9 +44,11 @@ pg_reorg は PostgreSQL のテーブルを再編成するシェルコマンド
|
|||||||
<hr />
|
<hr />
|
||||||
|
|
||||||
<h2>ドキュメント</h2>
|
<h2>ドキュメント</h2>
|
||||||
<p>
|
|
||||||
<a href="pg_reorg-ja.html">ドキュメントはこちら</a>。
|
<ul>
|
||||||
</p>
|
<li><a href="pg_reorg-ja.html">pg_reorg 1.1.0 ドキュメント</a></li>
|
||||||
|
<li><a href="pg_batch-ja.html">pg_batch 1.2.0 ドキュメント</a></li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
<h2>実行時間</h2>
|
<h2>実行時間</h2>
|
||||||
<p>
|
<p>
|
||||||
|
@ -17,10 +17,22 @@
|
|||||||
<h1>Welcome to the pg_reorg Project Home Page</h1>
|
<h1>Welcome to the pg_reorg Project Home Page</h1>
|
||||||
<hr />
|
<hr />
|
||||||
</center>
|
</center>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
pg_reorg can re-organize tables on a postgres database without any locks so that you can retrieve or update rows in tables being reorganized.
|
This project provides two tools for PostgreSQL; <strong>pg_reorg</strong> and <strong>pg_batch</strong>.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<strong>pg_reorg</strong> can re-organize tables on a postgres database without any locks so that you can retrieve or update rows in tables being reorganized.
|
||||||
The module is developed to be a better alternative of CLUSTER and VACUUM FULL.
|
The module is developed to be a better alternative of CLUSTER and VACUUM FULL.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<strong>pg_batch</strong> is a SQL job executor program for PostgreSQL.
|
||||||
|
It generates job list from an external SQL script file, and execute the jobs in serial or parallel.
|
||||||
|
It can be used as "a better vacuumdb" with the attached script to run VACUUM.
|
||||||
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
The pg_reorg project is a <a href="http://www.postgresql.org">PostgreSQL</a> Community project that is a part of the <a href="http://pgfoundry.org">pgFoundry</a>.
|
The pg_reorg project is a <a href="http://www.postgresql.org">PostgreSQL</a> Community project that is a part of the <a href="http://pgfoundry.org">pgFoundry</a>.
|
||||||
</p>
|
</p>
|
||||||
@ -34,9 +46,11 @@ where you can find <a href="http://pgfoundry.org/frs/?group_id=1000411">download
|
|||||||
<hr />
|
<hr />
|
||||||
|
|
||||||
<h2>Documentation</h2>
|
<h2>Documentation</h2>
|
||||||
<p>
|
|
||||||
<a href="pg_reorg.html">Documentations here</a>.
|
<ul>
|
||||||
</p>
|
<li><a href="pg_reorg.html">pg_reorg 1.1.0 documentation</a></li>
|
||||||
|
<li><a href="pg_batch-ja.html">pg_batch 1.2.0 documentation</a> (ja)</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
<h2>Execution time</h2>
|
<h2>Execution time</h2>
|
||||||
<p>
|
<p>
|
||||||
|
@ -8,7 +8,12 @@
|
|||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<h1 id="pg_reorg">pg_reorg</h1>
|
<h1 id="pg_reorg">pg_reorg 1.1.0</h1>
|
||||||
|
<div class="navigation">
|
||||||
|
<a href="index-ja.html">Top</a> >
|
||||||
|
<a href="pg_reorg-ja.html">pg_reorg</a>
|
||||||
|
<div>
|
||||||
|
<hr />
|
||||||
|
|
||||||
<div class="index">
|
<div class="index">
|
||||||
<ol>
|
<ol>
|
||||||
@ -31,28 +36,34 @@ pg_reorg -- PostgreSQLデータベース内のテーブルに対して、参照/
|
|||||||
|
|
||||||
<h2 id="synopsis">概要</h2>
|
<h2 id="synopsis">概要</h2>
|
||||||
<p>
|
<p>
|
||||||
pg_reorg [connection-options...] [message-options...] [order-options...] [target-options...]
|
pg_reorg [OPTIONS]
|
||||||
</p>
|
</p>
|
||||||
<p>指定できるオプションには4つのカテゴリがあります。
|
|
||||||
|
<p>オプション OPTIONS には以下を指定できます。
|
||||||
詳細は<a href="#options">オプション</a>を参照してください。</p>
|
詳細は<a href="#options">オプション</a>を参照してください。</p>
|
||||||
<dl>
|
<ul>
|
||||||
<dt>connection-options : 接続パラメータ</dt>
|
<li>固有オプション<ul>
|
||||||
<dd>-h [--host] host</dd>
|
<li>-o [--order-by] columns [,...]</li>
|
||||||
<dd>-p [--port] port</dd>
|
<li>-n [--no-order]</li>
|
||||||
<dd>-U [--username] username</dd>
|
<li>-t [--table] table</li>
|
||||||
<dd>-W [--password]</dd>
|
<li>-T [--wait-timeout] seconds</li>
|
||||||
<dt>message-options : 出力メッセージ</dt>
|
<li>-Z [--no-analyze]</li>
|
||||||
<dd>-q [--quiet]</dd>
|
</ul></li>
|
||||||
<dd>-v [--verbose]</dd>
|
<li>接続オプション<ul>
|
||||||
<dt>order-options : 並び替えの基準</dt>
|
<li>-a, --all : 全てのデータベースに対して実行します</li>
|
||||||
<dd>-o [--order-by] columns [,...]</dd>
|
<li>-d, --dbname=DBNAME : 接続するデータベース</li>
|
||||||
<dd>-n [--no-order]</dd>
|
<li>-h, --host=HOSTNAME : データベースサーバホスト、またはソケットディレクトリ</li>
|
||||||
<dt>target-options : 処理対象</dt>
|
<li>-p, --port=PORT : データベースサーバのポート</li>
|
||||||
<dd>-a [--all]</dd>
|
<li>-U, --username=USERNAME : このユーザとして接続します</li>
|
||||||
<dd>-d [--dbname] dbname</dd>
|
<li>-W, --password : パスワード入力を強制します</li>
|
||||||
<dd>-t [--table] table</dd>
|
</ul></li>
|
||||||
<dd>-Z [--no-analyze]</dd>
|
<li>一般オプション<ul>
|
||||||
</dl>
|
<li>-e, --echo : サーバに送信するSQLを表示します</li>
|
||||||
|
<li>-E, --elevel=LEVEL : ログ出力レベルを設定します</li>
|
||||||
|
<li>--help : ヘルプを表示し、終了します</li>
|
||||||
|
<li>--version : バージョン情報を出力し、終了します</li>
|
||||||
|
</ul></li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
<h2 id="description">説明</h2>
|
<h2 id="description">説明</h2>
|
||||||
<p>pg_reorg は、PostgreSQLデータベース内のテーブルを再編成(行の並び替え)するユーティリティです。
|
<p>pg_reorg は、PostgreSQLデータベース内のテーブルを再編成(行の並び替え)するユーティリティです。
|
||||||
@ -77,47 +88,11 @@ pg_reorg [connection-options...] [message-options...] [order-options...] [tar
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
<h2 id="options">オプション</h2>
|
<h2 id="options">オプション</h2>
|
||||||
<p>pg_reorg では、下記の4種類のコマンドライン引数を指定できます。</p>
|
<p>pg_reorg では、下記のコマンドライン引数を指定できます。</p>
|
||||||
<dl>
|
<dl>
|
||||||
|
|
||||||
<h3>connection-options</h3>
|
<h3>固有オプション</h3>
|
||||||
<p>PostgreSQLに接続するためのパラメータです。</p>
|
<p>pg_reorg を実行する対象と並び替えの基準を指定するパラメータです。
|
||||||
|
|
||||||
<dl>
|
|
||||||
<dt>-h host<br />
|
|
||||||
--host host</dt>
|
|
||||||
<dd>サーバが稼働しているマシンのホスト名を指定します。ホスト名がスラッシュから始まる場合、Unixドメインソケット用のディレクトリとして使用されます。</dd>
|
|
||||||
|
|
||||||
<dt>-p port<br />
|
|
||||||
--port port</dt>
|
|
||||||
<dd>サーバが接続を監視するTCPポートもしくはUnixドメインソケットファイルの拡張子を指定します。</dd>
|
|
||||||
|
|
||||||
<dt>-U username<br />
|
|
||||||
--username username</dt>
|
|
||||||
<dd>接続するユーザ名を指定します。</dd>
|
|
||||||
|
|
||||||
<dt>-W<br />--password</dt>
|
|
||||||
<dd>データベースに接続する前に、pg_reorg は強制的にパスワード入力を促します。</dd>
|
|
||||||
<dd>サーバがパスワード認証を要求する場合 pg_reorg は自動的にパスワード入力を促しますので、これが重要になることはありません。
|
|
||||||
しかし、pg_reorg は、サーバにパスワードが必要かどうかを判断するための接続試行を無駄に行います。
|
|
||||||
こうした余計な接続試行を防ぐために-Wの入力が有意となる場合もあります。</dd>
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
<h3>message-options</h3>
|
|
||||||
<p>
|
|
||||||
pg_reorg を実行した際に任意のメッセージを出力するためのパラメータです。
|
|
||||||
--quietと他の2つのオプションを同時に指定した場合は、--quietのオプションは無視されます。
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<dl>
|
|
||||||
<dt>-q<br />--quiet</dt>
|
|
||||||
<dd>進行メッセージを表示しません。</dd>
|
|
||||||
<dt>-v<br />--verbose</dt>
|
|
||||||
<dd>処理中に詳細な情報を表示します。</dd>
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
<h3>order-options</h3>
|
|
||||||
<p>pg_reorg を実行する際の並び替えの基準を指定するパラメータです。
|
|
||||||
何も指定されていない場合は、cluster index順にオンライン CLUSTER を行います。
|
何も指定されていない場合は、cluster index順にオンライン CLUSTER を行います。
|
||||||
この2つを同時に指定することはできません。
|
この2つを同時に指定することはできません。
|
||||||
</p>
|
</p>
|
||||||
@ -131,9 +106,34 @@ pg_reorg を実行した際に任意のメッセージを出力するための
|
|||||||
<dd>指定したカラムをキーにオンライン CLUSTER を行います。</dd>
|
<dd>指定したカラムをキーにオンライン CLUSTER を行います。</dd>
|
||||||
</dl>
|
</dl>
|
||||||
|
|
||||||
<h3>target-options</h3>
|
<dt>
|
||||||
|
-t table<br />
|
||||||
|
--table=table
|
||||||
|
</dt>
|
||||||
|
<dd>オンライン CLUSTER 、または、オンライン VACUUM FULL を行うテーブルを指定します。
|
||||||
|
このオプションが指定されていない場合は、対象となったデータベースに存在する全ての対象テーブルに対して処理を行います。
|
||||||
|
</dd>
|
||||||
|
|
||||||
|
<dt>
|
||||||
|
-T seconds<br />
|
||||||
|
--wait-timeout=seconds
|
||||||
|
</dt>
|
||||||
|
<dd>
|
||||||
|
再編成完了直前に一瞬だけ排他ロックを取得しますが、この排他ロックが取得できるまで待機する秒数を指定します。
|
||||||
|
この秒数が経過してもロックが取得できない場合には、対象のテーブルにアクセスしている他の全てのクエリを取り消します。
|
||||||
|
また、サーバのバージョンが 8.4 またはそれ以降の場合には、指定した秒数の2倍経過してもロックを取得できない場合には、強制的に切断します。
|
||||||
|
デフォルトは60秒です。
|
||||||
|
</dd>
|
||||||
|
|
||||||
|
<dt>-Z<br />--no-analyze</dt>
|
||||||
|
<dd>再編成後に ANALYZE を行いません。
|
||||||
|
このオプションが指定されていない場合は、再編成後に ANALYZE します。</dd>
|
||||||
|
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
<h3>接続オプション</h3>
|
||||||
<p>
|
<p>
|
||||||
pg_reorg を実行する対象を指定するパラメータです。
|
PostgreSQLに接続するためのパラメータです。
|
||||||
--allと--dbnameまたは--tableを同時に指定することはできません。
|
--allと--dbnameまたは--tableを同時に指定することはできません。
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
@ -142,26 +142,46 @@ pg_reorg を実行する対象を指定するパラメータです。
|
|||||||
<dd>対象となる全てのデータベースに対してオンライン CLUSTER、または、オンラインVACUUM FULLを行います。</dd>
|
<dd>対象となる全てのデータベースに対してオンライン CLUSTER、または、オンラインVACUUM FULLを行います。</dd>
|
||||||
|
|
||||||
<dt>
|
<dt>
|
||||||
-d dbname<br />
|
-d DBNAME<br />
|
||||||
--dbname dbname
|
--dbname=DBNAME
|
||||||
</dt>
|
</dt>
|
||||||
<dd>オンライン CLUSTER、または、オンライン VACUUM FULL を行うデータベース名を指定します。
|
<dd>オンライン CLUSTER、または、オンライン VACUUM FULL を行うデータベース名を指定します。
|
||||||
データベース名が指定されておらず、-a(または--all)も指定されていない場合、
|
データベース名が指定されておらず、-a(または--all)も指定されていない場合、
|
||||||
データベース名はPGDATABASE環境変数から読み取られます。この変数も設定されていない場合は、接続時に指定したユーザ名が使用されます。
|
データベース名はPGDATABASE環境変数から読み取られます。
|
||||||
</dd>
|
この変数も設定されていない場合は、接続時に指定したユーザ名が使用されます。</dd>
|
||||||
|
|
||||||
<dt>
|
<dt>-h HOSTNAME<br />
|
||||||
-t table<br />
|
--host=HOSTNAME</dt>
|
||||||
--table table
|
<dd>サーバが稼働しているマシンのホスト名を指定します。ホスト名がスラッシュから始まる場合、Unixドメインソケット用のディレクトリとして使用されます。</dd>
|
||||||
</dt>
|
|
||||||
<dd>オンライン CLUSTER 、または、オンライン VACUUM FULL を行うテーブルを指定します。
|
|
||||||
このオプションが指定されていない場合は、対象となったデータベースに存在する全ての対象テーブルに対して処理を行います。
|
|
||||||
</dd>
|
|
||||||
|
|
||||||
<dt>-Z<br />--no-analyze</dt>
|
<dt>-p PORT<br />
|
||||||
<dd>再編成後に ANALYZE を行いません。
|
--port=PORT</dt>
|
||||||
このオプションが指定されていない場合は、再編成後に ANALYZE します。</dd>
|
<dd>サーバが接続を監視するTCPポートもしくはUnixドメインソケットファイルの拡張子を指定します。</dd>
|
||||||
|
|
||||||
|
<dt>-U USERNAME<br />
|
||||||
|
--username=USERNAME</dt>
|
||||||
|
<dd>接続するユーザ名を指定します。</dd>
|
||||||
|
|
||||||
|
<dt>-W<br />
|
||||||
|
--password</dt>
|
||||||
|
<dd>データベースに接続する前に、強制的にパスワード入力を促します。
|
||||||
|
サーバがパスワード認証を要求する場合 自動的にパスワード入力を促しますので、これが重要になることはありません。
|
||||||
|
しかし、サーバにパスワードが必要かどうかを判断するための接続試行を無駄に行います。
|
||||||
|
こうした余計な接続試行を防ぐために -W の入力が有意となる場合もあります。</dd>
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
<h3>一般オプション</h3>
|
||||||
|
<dl>
|
||||||
|
<dt>-e<br />--echo</dt>
|
||||||
|
<dd>サーバに送信するSQLを表示します。</dd>
|
||||||
|
<dt>-E<br />--elevel</dt>
|
||||||
|
<dd>ログ出力レベルを設定します。
|
||||||
|
DEBUG, INFO, NOTICE, WARNING, ERROR, LOG, FATAL, PANIC から選択します。
|
||||||
|
デフォルトは INFO です。</dd>
|
||||||
|
<dt>--help</dt>
|
||||||
|
<dd>使用方法について表示します。</dd>
|
||||||
|
<dt>--version</dt>
|
||||||
|
<dd>バージョン情報を表示します。</dd>
|
||||||
</dl>
|
</dl>
|
||||||
|
|
||||||
<h2 id="environment">環境変数</h2>
|
<h2 id="environment">環境変数</h2>
|
||||||
@ -268,9 +288,12 @@ pg_reorg の実行中には、VACUUM と ANALYZE <STRONG>以外</STRONG> のDDL
|
|||||||
|
|
||||||
<h2 id="requirement">動作環境</h2>
|
<h2 id="requirement">動作環境</h2>
|
||||||
<dl>
|
<dl>
|
||||||
<dt>PostgreSQLバージョン</dt><dd>PostgreSQL 8.3</dd>
|
<dt>PostgreSQLバージョン</dt>
|
||||||
<dt>OS</dt><dd>RHEL 5.2, Windows XP SP3</dd>
|
<dd>PostgreSQL 8.3, 8.4, 9.0</dd>
|
||||||
<dt>ディスク容量</dt><dd>処理対象のテーブル、インデックスサイズの2倍以上のディスク空き容量</dd>
|
<dt>OS</dt>
|
||||||
|
<dd>RHEL 5.2, Windows XP SP3</dd>
|
||||||
|
<dt>ディスク容量</dt>
|
||||||
|
<dd>処理対象のテーブル、インデックスサイズの2倍以上のディスク空き容量 (対象が1GBならば、さらに追加で2GB)</dd>
|
||||||
</dl>
|
</dl>
|
||||||
|
|
||||||
<h2 id="seealso">関連項目</h2>
|
<h2 id="seealso">関連項目</h2>
|
||||||
@ -278,6 +301,10 @@ pg_reorg の実行中には、VACUUM と ANALYZE <STRONG>以外</STRONG> のDDL
|
|||||||
<a href="http://www.postgresql.jp/document/current/html/app-vacuumdb.html">vacuumdb</a>
|
<a href="http://www.postgresql.jp/document/current/html/app-vacuumdb.html">vacuumdb</a>
|
||||||
|
|
||||||
<hr />
|
<hr />
|
||||||
|
<div class="navigation">
|
||||||
|
<a href="index-ja.html">Top</a> >
|
||||||
|
<a href="pg_reorg-ja.html">pg_reorg</a>
|
||||||
|
<div>
|
||||||
<p class="footer">Copyright (c) 2008-2010, NIPPON TELEGRAPH AND TELEPHONE CORPORATION</p>
|
<p class="footer">Copyright (c) 2008-2010, NIPPON TELEGRAPH AND TELEPHONE CORPORATION</p>
|
||||||
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
|
@ -8,7 +8,12 @@
|
|||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<h1 id="pg_reorg">pg_reorg</h1>
|
<h1 id="pg_reorg">pg_reorg 1.1.0</h1>
|
||||||
|
<div class="navigation">
|
||||||
|
<a href="index.html">Top</a> >
|
||||||
|
<a href="pg_reorg.html">pg_reorg</a>
|
||||||
|
<div>
|
||||||
|
<hr />
|
||||||
|
|
||||||
<div class="index">
|
<div class="index">
|
||||||
<ol>
|
<ol>
|
||||||
@ -31,28 +36,34 @@ pg_reorg -- Reorganize tables in PostgreSQL databases without any locks.
|
|||||||
|
|
||||||
<h2 id="synopsis">Synopsis</h2>
|
<h2 id="synopsis">Synopsis</h2>
|
||||||
<p>
|
<p>
|
||||||
pg_reorg [connection-options...] [message-options...] [order-options...] [target-options...]
|
pg_reorg [OPTIONS]
|
||||||
</p>
|
</p>
|
||||||
<p>There 4 option categories.
|
|
||||||
See also <a href="#options">options</a> for details.</p>
|
<p>The following options can be specified in OPTIONS.
|
||||||
<dl>
|
See also "<a href="#options">Options</a>" for details.</p>
|
||||||
<dt>connection-options</dt>
|
<ul>
|
||||||
<dd>-h [--host] host</dd>
|
<li>Reorg Options<ul>
|
||||||
<dd>-p [--port] port</dd>
|
<li>-o [--order-by] columns [,...]</li>
|
||||||
<dd>-U [--username] username</dd>
|
<li>-n [--no-order]</li>
|
||||||
<dd>-W [--password]</dd>
|
<li>-t [--table] table</li>
|
||||||
<dt>message-options</dt>
|
<li>-T [--wait-timeout] seconds</li>
|
||||||
<dd>-q [--quiet]</dd>
|
<li>-Z [--no-analyze]</li>
|
||||||
<dd>-v [--verbose]</dd>
|
</ul></li>
|
||||||
<dt>order-options</dt>
|
<li>Connection Options<ul>
|
||||||
<dd>-o [--order-by] columns [,...]</dd>
|
<li>-a, --all : reorganize all databases</li>
|
||||||
<dd>-n [--no-order]</dd>
|
<li>-d, --dbname=DBNAME : database to connect</li>
|
||||||
<dt>target-options</dt>
|
<li>-h, --host=HOSTNAME : database server host or socket directory</li>
|
||||||
<dd>-a [--all]</dd>
|
<li>-p, --port=PORT : database server port</li>
|
||||||
<dd>-d [--dbname] dbname</dd>
|
<li>-U, --username=USERNAME : user name to connect as</li>
|
||||||
<dd>-t [--table] table</dd>
|
<li>-W, --password : force password prompt</li>
|
||||||
<dd>-Z [--no-analyze]</dd>
|
</ul></li>
|
||||||
</dl>
|
<li>Generic Options<ul>
|
||||||
|
<li>-e, --echo : echo queries</li>
|
||||||
|
<li>-E, --elevel=LEVEL : set output message level</li>
|
||||||
|
<li>--help : show the help, then exit</li>
|
||||||
|
<li>--version : output version information, then exit</li>
|
||||||
|
</ul></li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
<h2 id="description">Description</h2>
|
<h2 id="description">Description</h2>
|
||||||
<p>pg_reorg is an utility program to reorganize tables in PostgreSQL databases.
|
<p>pg_reorg is an utility program to reorganize tables in PostgreSQL databases.
|
||||||
@ -77,15 +88,68 @@ You can choose one of the following methods to reorganize.</p>
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
<h2 id="options">Options</h2>
|
<h2 id="options">Options</h2>
|
||||||
<p>pg_reorg has command line options in 4 categolies.</p>
|
<p>pg_reorg has the following command line options:</p>
|
||||||
<div>
|
|
||||||
<dl>
|
<dl>
|
||||||
|
|
||||||
<h3>connection-options</h3>
|
<h3>Reorg Options</h3>
|
||||||
<p>Parameters to connect PostgreSQL.</p>
|
<p>Options to order rows.
|
||||||
|
If not specified, pg_reorg do online CLUSTER using cluster indexes.
|
||||||
|
Only one option can be specified.
|
||||||
|
|
||||||
|
Options to specify target tables or databases.
|
||||||
|
</p>
|
||||||
|
|
||||||
<div>
|
|
||||||
<dl>
|
<dl>
|
||||||
|
<dt>-n<br />--no-order</dt>
|
||||||
|
<dd>Do online VACUUM FULL.</dd>
|
||||||
|
|
||||||
|
<dt>-o columns [,...]<br />
|
||||||
|
--order-by=columns [,...]</dt>
|
||||||
|
<dd>Do online CLUSTER ordered by specified columns.</dd>
|
||||||
|
|
||||||
|
<dt>
|
||||||
|
-t table<br />
|
||||||
|
--table=table
|
||||||
|
</dt>
|
||||||
|
<dd>Reorganize table only. If you don't specify this option, all tables in specified databases are reorganized.</dd>
|
||||||
|
|
||||||
|
<dt>-Z<br />--no-analyze</dt>
|
||||||
|
<dd>Do ANALYZE after reorganization. If you don't specify this option, ANALYZE is performed automatically after reorg.</dd>
|
||||||
|
|
||||||
|
<dt>
|
||||||
|
-T seconds<br />
|
||||||
|
--wait-timeout=seconds
|
||||||
|
</dt>
|
||||||
|
<dd>
|
||||||
|
pg_reorg needs to take an exclusive lock at the end of the reorganization.
|
||||||
|
This setting controls how long it wait for acquiring the lock in seconds.
|
||||||
|
If the lock cannot be taken even after the duration, pg_reorg forces to cancel conflicted queries.
|
||||||
|
Also, if the server version is 8.4 or newer, pg_reorg forces to disconnect conflicted backends after twice time passed.
|
||||||
|
The default is 60 seconds.
|
||||||
|
</dd>
|
||||||
|
|
||||||
|
<dt>-Z<br />--no-analyze</dt>
|
||||||
|
<dd>Disable ANALYZE after the reorganization.
|
||||||
|
If not specified, run ANALYZE after the reorganization.</dd>
|
||||||
|
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
<h3>Connection Options</h3>
|
||||||
|
<p>
|
||||||
|
Options to connect to servers.
|
||||||
|
You cannot use --all and --dbname or --table together.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<dl>
|
||||||
|
<dt>-a<br />--all</dt>
|
||||||
|
<dd>Reorganize all databases.</dd>
|
||||||
|
|
||||||
|
<dt>
|
||||||
|
-d dbname<br />
|
||||||
|
--dbname dbname
|
||||||
|
</dt>
|
||||||
|
<dd>Specifies the name of the database to be reorganized. If this is not specified and -a (or --all) is not used, the database name is read from the environment variable PGDATABASE. If that is not set, the user name specified for the connection is used. </dd>
|
||||||
|
|
||||||
<dt>-h host<br />
|
<dt>-h host<br />
|
||||||
--host host</dt>
|
--host host</dt>
|
||||||
<dd>Specifies the host name of the machine on which the server is running. If the value begins with a slash, it is used as the directory for the Unix domain socket. </dd>
|
<dd>Specifies the host name of the machine on which the server is running. If the value begins with a slash, it is used as the directory for the Unix domain socket. </dd>
|
||||||
@ -103,58 +167,17 @@ You can choose one of the following methods to reorganize.</p>
|
|||||||
<dd>This option is never essential, since pg_reorg will automatically prompt for a password if the server demands password authentication. However, vacuumdb will waste a connection attempt finding out that the server wants a password. In some cases it is worth typing -W to avoid the extra connection attempt. </dd>
|
<dd>This option is never essential, since pg_reorg will automatically prompt for a password if the server demands password authentication. However, vacuumdb will waste a connection attempt finding out that the server wants a password. In some cases it is worth typing -W to avoid the extra connection attempt. </dd>
|
||||||
</dl>
|
</dl>
|
||||||
|
|
||||||
<h3>message-options</h3>
|
<h3>Generic Options</h3>
|
||||||
<p>Specifies message output by pg_reorg.
|
|
||||||
--quiet is ignored if some of the other options are specified.</p>
|
|
||||||
|
|
||||||
<dl>
|
<dl>
|
||||||
<dt>-q<br />--quiet</dt>
|
<dt>-e<br />--echo</dt>
|
||||||
<dd>Do not display progress messages. </dd>
|
<dd>Echo commands sent to server.</dd>
|
||||||
<dt>-v<br />--verbose</dt>
|
<dt>-E<br />--elevel</dt>
|
||||||
<dd>Print detailed information during processing.</dd>
|
<dd>Choose the output message level from DEBUG, INFO, NOTICE, WARNING, ERROR, LOG, FATAL, and PANIC.
|
||||||
</dl>
|
The default is INFO.</dd>
|
||||||
|
<dt>--help</dt>
|
||||||
<h3>order-options</h3>
|
<dd>Show usage of the program.</dd>
|
||||||
<p>Options to order rows.
|
<dt>--version</dt>
|
||||||
If not specified, pg_reorg do online CLUSTER using cluster indexes.
|
<dd>Show the version number of the program.</dd>
|
||||||
Only one option can be specified.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<dl>
|
|
||||||
<dt>-n<br />--no-order</dt>
|
|
||||||
<dd>Do online VACUUM FULL.</dd>
|
|
||||||
|
|
||||||
<dt>-o columns [,...]<br />
|
|
||||||
--order-by columns [,...]</dt>
|
|
||||||
<dd>Do online CLUSTER ordered by specified columns.</dd>
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
|
|
||||||
<h3>target-options</h3>
|
|
||||||
<p>
|
|
||||||
Options to specify target tables or databases.
|
|
||||||
You cannot use --all and --dbname or --table together.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<dl>
|
|
||||||
<dt>-a<br />--all</dt>
|
|
||||||
<dd>Reorganize all databases.</dd>
|
|
||||||
|
|
||||||
<dt>
|
|
||||||
-d dbname<br />
|
|
||||||
--dbname dbname
|
|
||||||
</dt>
|
|
||||||
<dd>Specifies the name of the database to be reorganized. If this is not specified and -a (or --all) is not used, the database name is read from the environment variable PGDATABASE. If that is not set, the user name specified for the connection is used. </dd>
|
|
||||||
|
|
||||||
<dt>
|
|
||||||
-t table<br />
|
|
||||||
--table table
|
|
||||||
</dt>
|
|
||||||
<dd>Reorganize table only. If you don't specify this option, all tables in specified databases are reorganized.</dd>
|
|
||||||
|
|
||||||
<dt>-Z<br />--no-analyze</dt>
|
|
||||||
<dd>Do ANALYZE after reorganization. If you don't specify this option, ANALYZE is performed automatically after reorg.</dd>
|
|
||||||
|
|
||||||
</dl>
|
</dl>
|
||||||
|
|
||||||
<h2 id="environment">Environment</h2>
|
<h2 id="environment">Environment</h2>
|
||||||
@ -253,9 +276,10 @@ Then, it updates system catalog directly to swap the work table and the original
|
|||||||
|
|
||||||
<h2 id="requirement">Requirements</h2>
|
<h2 id="requirement">Requirements</h2>
|
||||||
<dl>
|
<dl>
|
||||||
<dt>PostgreSQL version</dt><dd>PostgreSQL 8.3</dd>
|
<dt>PostgreSQL version</dt>
|
||||||
|
<dd>PostgreSQL 8.3, 8.4, 9.0</dd>
|
||||||
<dt>OS</dt><dd>RHEL 5.2, Windows XP SP3</dd>
|
<dt>OS</dt><dd>RHEL 5.2, Windows XP SP3</dd>
|
||||||
<dt>Disks</dt><dd>Requires amount of disks twice larger than target table and indexes.</dd>
|
<dt>Disks</dt><dd>Requires amount of disks twice larger than target table and indexes. (If the total size of targets are 1GB, additional 2GB of disks are required.)</dd>
|
||||||
</dl>
|
</dl>
|
||||||
|
|
||||||
<h2 id="seealso">See Also</h2>
|
<h2 id="seealso">See Also</h2>
|
||||||
@ -263,6 +287,10 @@ Then, it updates system catalog directly to swap the work table and the original
|
|||||||
<a href="http://developer.postgresql.org/pgdocs/postgres/app-vacuumdb.html">vacuumdb</a>
|
<a href="http://developer.postgresql.org/pgdocs/postgres/app-vacuumdb.html">vacuumdb</a>
|
||||||
|
|
||||||
<hr />
|
<hr />
|
||||||
|
<div class="navigation">
|
||||||
|
<a href="index.html">Top</a> >
|
||||||
|
<a href="pg_reorg.html">pg_reorg</a>
|
||||||
|
<div>
|
||||||
<p class="footer">Copyright (c) 2008-2010, NIPPON TELEGRAPH AND TELEPHONE CORPORATION</p>
|
<p class="footer">Copyright (c) 2008-2010, NIPPON TELEGRAPH AND TELEPHONE CORPORATION</p>
|
||||||
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
|
@ -79,3 +79,7 @@ p.footer {
|
|||||||
text-align: right;
|
text-align: right;
|
||||||
font-size: small;
|
font-size: small;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
span.param {
|
||||||
|
color: #0000cd;
|
||||||
|
}
|
||||||
|
@ -118,7 +118,7 @@ CREATE VIEW reorg.tables AS
|
|||||||
reorg.get_create_trigger(R.oid, PK.indexrelid) AS create_trigger,
|
reorg.get_create_trigger(R.oid, PK.indexrelid) AS create_trigger,
|
||||||
'CREATE TABLE reorg.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 * FROM ONLY ' || reorg.oid2text(R.oid) AS create_table,
|
'CREATE TABLE reorg.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 * FROM ONLY ' || reorg.oid2text(R.oid) AS create_table,
|
||||||
'DELETE FROM reorg.log_' || R.oid AS delete_log,
|
'DELETE FROM reorg.log_' || R.oid AS delete_log,
|
||||||
'LOCK TABLE ' || reorg.oid2text(R.oid) || ' IN ACCESS EXCLUSIVE MODE NOWAIT' AS lock_table,
|
'LOCK TABLE ' || reorg.oid2text(R.oid) || ' IN ACCESS EXCLUSIVE MODE' AS lock_table,
|
||||||
reorg.get_index_keys(CK.indexrelid, R.oid) AS ckey,
|
reorg.get_index_keys(CK.indexrelid, R.oid) AS ckey,
|
||||||
'SELECT * FROM reorg.log_' || R.oid || ' ORDER BY id LIMIT $1' AS sql_peek,
|
'SELECT * FROM reorg.log_' || R.oid || ' ORDER BY id LIMIT $1' AS sql_peek,
|
||||||
'INSERT INTO reorg.table_' || R.oid || ' VALUES ($1.*)' AS sql_insert,
|
'INSERT INTO reorg.table_' || R.oid || ' VALUES ($1.*)' AS sql_insert,
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "postgres.h"
|
#include "postgres.h"
|
||||||
#include "fmgr.h"
|
#include "access/heapam.h"
|
||||||
#include "pgut-be.h"
|
#include "pgut-be.h"
|
||||||
|
|
||||||
#if PG_VERSION_NUM < 80400
|
#if PG_VERSION_NUM < 80400
|
||||||
@ -42,4 +42,11 @@ cstring_to_text(const char *s)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
tuplestore_putvalues(Tuplestorestate *state, TupleDesc tdesc,
|
||||||
|
Datum *values, bool *isnull)
|
||||||
|
{
|
||||||
|
tuplestore_puttuple(state, heap_form_tuple(tdesc, values, isnull));
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -10,6 +10,48 @@
|
|||||||
#ifndef PGUT_BE_H
|
#ifndef PGUT_BE_H
|
||||||
#define PGUT_BE_H
|
#define PGUT_BE_H
|
||||||
|
|
||||||
|
#include "fmgr.h"
|
||||||
|
#include "utils/tuplestore.h"
|
||||||
|
|
||||||
|
#ifndef WIN32
|
||||||
|
|
||||||
|
#define PGUT_EXPORT
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#define PGUT_EXPORT __declspec(dllexport)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* PG_MODULE_MAGIC and PG_FUNCTION_INFO_V1 macros seems to be broken.
|
||||||
|
* It uses PGDLLIMPORT, but those objects are not imported from postgres
|
||||||
|
* and exported from the user module. So, it should be always dllexported.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#undef PG_MODULE_MAGIC
|
||||||
|
#define PG_MODULE_MAGIC \
|
||||||
|
extern PGUT_EXPORT const Pg_magic_struct *PG_MAGIC_FUNCTION_NAME(void); \
|
||||||
|
const Pg_magic_struct * \
|
||||||
|
PG_MAGIC_FUNCTION_NAME(void) \
|
||||||
|
{ \
|
||||||
|
static const Pg_magic_struct Pg_magic_data = PG_MODULE_MAGIC_DATA; \
|
||||||
|
return &Pg_magic_data; \
|
||||||
|
} \
|
||||||
|
extern int no_such_variable
|
||||||
|
|
||||||
|
#undef PG_FUNCTION_INFO_V1
|
||||||
|
#define PG_FUNCTION_INFO_V1(funcname) \
|
||||||
|
extern PGUT_EXPORT const Pg_finfo_record * CppConcat(pg_finfo_,funcname)(void); \
|
||||||
|
const Pg_finfo_record * \
|
||||||
|
CppConcat(pg_finfo_,funcname) (void) \
|
||||||
|
{ \
|
||||||
|
static const Pg_finfo_record my_finfo = { 1 }; \
|
||||||
|
return &my_finfo; \
|
||||||
|
} \
|
||||||
|
extern int no_such_variable
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#if PG_VERSION_NUM < 80300
|
#if PG_VERSION_NUM < 80300
|
||||||
|
|
||||||
#define PGDLLIMPORT DLLIMPORT
|
#define PGDLLIMPORT DLLIMPORT
|
||||||
@ -33,8 +75,6 @@
|
|||||||
#define GetCurrentCommandId(used) GetCurrentCommandId()
|
#define GetCurrentCommandId(used) GetCurrentCommandId()
|
||||||
#define stringToQualifiedNameList(str) \
|
#define stringToQualifiedNameList(str) \
|
||||||
stringToQualifiedNameList((str), "pg_bulkload")
|
stringToQualifiedNameList((str), "pg_bulkload")
|
||||||
#define setNewRelfilenode(rel, xid) \
|
|
||||||
setNewRelfilenode((rel))
|
|
||||||
#define PageAddItem(page, item, size, offnum, overwrite, is_heap) \
|
#define PageAddItem(page, item, size, offnum, overwrite, is_heap) \
|
||||||
PageAddItem((page), (item), (size), (offnum), LP_USED)
|
PageAddItem((page), (item), (size), (offnum), LP_USED)
|
||||||
|
|
||||||
@ -56,32 +96,75 @@
|
|||||||
#define GetBulkInsertState() (NULL)
|
#define GetBulkInsertState() (NULL)
|
||||||
#define FreeBulkInsertState(bistate) ((void)0)
|
#define FreeBulkInsertState(bistate) ((void)0)
|
||||||
#define FreeExprContext(econtext, isCommit) FreeExprContext((econtext))
|
#define FreeExprContext(econtext, isCommit) FreeExprContext((econtext))
|
||||||
#define FuncnameGetCandidates(names, nargs, argnames, variadic, defaults) \
|
|
||||||
FuncnameGetCandidates((names), (nargs))
|
|
||||||
#define pgstat_init_function_usage(fcinfo, fcu) ((void)0)
|
#define pgstat_init_function_usage(fcinfo, fcu) ((void)0)
|
||||||
#define pgstat_end_function_usage(fcu, finalize) ((void)0)
|
#define pgstat_end_function_usage(fcu, finalize) ((void)0)
|
||||||
|
#define makeRangeVar(schemaname, relname, location) \
|
||||||
|
makeRangeVar((schemaname), (relname))
|
||||||
|
#define pgstat_track_activity_query_size PGBE_ACTIVITY_SIZE
|
||||||
typedef void *BulkInsertState;
|
typedef void *BulkInsertState;
|
||||||
|
|
||||||
|
#define DefineCustomBoolVariable(name, short_desc, long_desc, valueAddr, bootValue, context, flags, assign_hook, show_hook) \
|
||||||
|
do { \
|
||||||
|
*(valueAddr) = (bootValue); \
|
||||||
|
DefineCustomBoolVariable((name), (short_desc), (long_desc), (valueAddr), (context), (assign_hook), (show_hook)); \
|
||||||
|
} while(0)
|
||||||
|
#define DefineCustomIntVariable(name, short_desc, long_desc, valueAddr, bootValue, minValue, maxValue, context, flags, assign_hook, show_hook) \
|
||||||
|
do { \
|
||||||
|
*(valueAddr) = (bootValue); \
|
||||||
|
DefineCustomIntVariable((name), (short_desc), (long_desc), (valueAddr), (minValue), (maxValue), (context), (assign_hook), (show_hook)); \
|
||||||
|
} while(0)
|
||||||
|
#define DefineCustomRealVariable(name, short_desc, long_desc, valueAddr, bootValue, minValue, maxValue, context, flags, assign_hook, show_hook) \
|
||||||
|
do { \
|
||||||
|
*(valueAddr) = (bootValue); \
|
||||||
|
DefineCustomRealVariable((name), (short_desc), (long_desc), (valueAddr), (minValue), (maxValue), (context), (assign_hook), (show_hook)); \
|
||||||
|
} while(0)
|
||||||
|
#define DefineCustomStringVariable(name, short_desc, long_desc, valueAddr, bootValue, context, flags, assign_hook, show_hook) \
|
||||||
|
do { \
|
||||||
|
*(valueAddr) = (char *) (bootValue); \
|
||||||
|
DefineCustomStringVariable((name), (short_desc), (long_desc), (valueAddr), (context), (assign_hook), (show_hook)); \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
struct config_enum_entry
|
||||||
|
{
|
||||||
|
const char *name;
|
||||||
|
int val;
|
||||||
|
bool hidden;
|
||||||
|
};
|
||||||
|
|
||||||
extern char *text_to_cstring(const text *t);
|
extern char *text_to_cstring(const text *t);
|
||||||
extern text *cstring_to_text(const char *s);
|
extern text *cstring_to_text(const char *s);
|
||||||
|
extern void tuplestore_putvalues(Tuplestorestate *state, TupleDesc tdesc,
|
||||||
|
Datum *values, bool *isnull);
|
||||||
|
|
||||||
#define CStringGetTextDatum(s) PointerGetDatum(cstring_to_text(s))
|
#define CStringGetTextDatum(s) PointerGetDatum(cstring_to_text(s))
|
||||||
#define TextDatumGetCString(d) text_to_cstring((text *) DatumGetPointer(d))
|
#define TextDatumGetCString(d) text_to_cstring((text *) DatumGetPointer(d))
|
||||||
|
|
||||||
#elif PG_VERSION_NUM < 80500
|
|
||||||
|
|
||||||
#define FuncnameGetCandidates(names, nargs, argnames, variadic, defaults) \
|
|
||||||
FuncnameGetCandidates((names), (nargs), (variadic), (defaults))
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if PG_VERSION_NUM < 80500
|
#if PG_VERSION_NUM < 90000
|
||||||
|
|
||||||
|
#define reindex_index(indexId, skip_constraint_checks) \
|
||||||
|
reindex_index((indexId))
|
||||||
#define func_signature_string(funcname, nargs, argnames, argtypes) \
|
#define func_signature_string(funcname, nargs, argnames, argtypes) \
|
||||||
func_signature_string((funcname), (nargs), (argtypes))
|
func_signature_string((funcname), (nargs), (argtypes))
|
||||||
#define GetConfigOption(name, restrict_superuser) GetConfigOption((name))
|
#define GetConfigOption(name, restrict_superuser) GetConfigOption((name))
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if PG_VERSION_NUM < 80300
|
||||||
|
#define RelationSetNewRelfilenode(rel, xid) \
|
||||||
|
setNewRelfilenode((rel))
|
||||||
|
#elif PG_VERSION_NUM < 90000
|
||||||
|
#define RelationSetNewRelfilenode(rel, xid) \
|
||||||
|
setNewRelfilenode((rel), (xid))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if PG_VERSION_NUM < 80400
|
||||||
|
#define FuncnameGetCandidates(names, nargs, argnames, variadic, defaults) \
|
||||||
|
FuncnameGetCandidates((names), (nargs))
|
||||||
|
#elif PG_VERSION_NUM < 90000
|
||||||
|
#define FuncnameGetCandidates(names, nargs, argnames, variadic, defaults) \
|
||||||
|
FuncnameGetCandidates((names), (nargs), (variadic), (defaults))
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* PGUT_BE_H */
|
#endif /* PGUT_BE_H */
|
||||||
|
18
lib/reorg.c
18
lib/reorg.c
@ -30,14 +30,14 @@
|
|||||||
|
|
||||||
PG_MODULE_MAGIC;
|
PG_MODULE_MAGIC;
|
||||||
|
|
||||||
Datum reorg_version(PG_FUNCTION_ARGS);
|
extern Datum PGUT_EXPORT reorg_version(PG_FUNCTION_ARGS);
|
||||||
Datum reorg_trigger(PG_FUNCTION_ARGS);
|
extern Datum PGUT_EXPORT reorg_trigger(PG_FUNCTION_ARGS);
|
||||||
Datum reorg_apply(PG_FUNCTION_ARGS);
|
extern Datum PGUT_EXPORT reorg_apply(PG_FUNCTION_ARGS);
|
||||||
Datum reorg_get_index_keys(PG_FUNCTION_ARGS);
|
extern Datum PGUT_EXPORT reorg_get_index_keys(PG_FUNCTION_ARGS);
|
||||||
Datum reorg_indexdef(PG_FUNCTION_ARGS);
|
extern Datum PGUT_EXPORT reorg_indexdef(PG_FUNCTION_ARGS);
|
||||||
Datum reorg_swap(PG_FUNCTION_ARGS);
|
extern Datum PGUT_EXPORT reorg_swap(PG_FUNCTION_ARGS);
|
||||||
Datum reorg_drop(PG_FUNCTION_ARGS);
|
extern Datum PGUT_EXPORT reorg_drop(PG_FUNCTION_ARGS);
|
||||||
Datum reorg_disable_autovacuum(PG_FUNCTION_ARGS);
|
extern Datum PGUT_EXPORT reorg_disable_autovacuum(PG_FUNCTION_ARGS);
|
||||||
|
|
||||||
PG_FUNCTION_INFO_V1(reorg_version);
|
PG_FUNCTION_INFO_V1(reorg_version);
|
||||||
PG_FUNCTION_INFO_V1(reorg_trigger);
|
PG_FUNCTION_INFO_V1(reorg_trigger);
|
||||||
@ -75,7 +75,7 @@ static void RenameRelationInternal(Oid myrelid, const char *newrelname, Oid name
|
|||||||
Datum
|
Datum
|
||||||
reorg_version(PG_FUNCTION_ARGS)
|
reorg_version(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
return CStringGetTextDatum("pg_reorg 1.0.8");
|
return CStringGetTextDatum("pg_reorg 1.1.0");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
167
msvc/bin.vcproj
Executable file
167
msvc/bin.vcproj
Executable file
@ -0,0 +1,167 @@
|
|||||||
|
<?xml version="1.0" encoding="shift_jis"?>
|
||||||
|
<VisualStudioProject
|
||||||
|
ProjectType="Visual C++"
|
||||||
|
Version="8.00"
|
||||||
|
Name="bin"
|
||||||
|
ProjectGUID="{B6B37F22-9E44-4240-AAA0-650D4AC2C1E2}"
|
||||||
|
RootNamespace="bin"
|
||||||
|
Keyword="Win32Proj"
|
||||||
|
>
|
||||||
|
<Platforms>
|
||||||
|
<Platform
|
||||||
|
Name="Win32"
|
||||||
|
/>
|
||||||
|
</Platforms>
|
||||||
|
<ToolFiles>
|
||||||
|
</ToolFiles>
|
||||||
|
<Configurations>
|
||||||
|
<Configuration
|
||||||
|
Name="Release|Win32"
|
||||||
|
OutputDirectory="$(SolutionDir)/bin"
|
||||||
|
IntermediateDirectory="$(SolutionDir)/obj/$(ProjectName)"
|
||||||
|
ConfigurationType="1"
|
||||||
|
CharacterSet="1"
|
||||||
|
WholeProgramOptimization="1"
|
||||||
|
>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreBuildEventTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCCustomBuildTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCXMLDataGeneratorTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebServiceProxyGeneratorTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCMIDLTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCCLCompilerTool"
|
||||||
|
AdditionalIncludeDirectories="../include"
|
||||||
|
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS"
|
||||||
|
ExceptionHandling="0"
|
||||||
|
RuntimeLibrary="2"
|
||||||
|
UsePrecompiledHeader="0"
|
||||||
|
WarningLevel="3"
|
||||||
|
WarnAsError="true"
|
||||||
|
Detect64BitPortabilityProblems="false"
|
||||||
|
DebugInformationFormat="0"
|
||||||
|
CompileAs="1"
|
||||||
|
DisableSpecificWarnings="4996"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCManagedResourceCompilerTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCResourceCompilerTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreLinkEventTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCLinkerTool"
|
||||||
|
AdditionalDependencies="kernel32.lib advapi32.lib ws2_32.lib $(NoInherit) libpq.lib libpgport.lib libintl-8.lib"
|
||||||
|
OutputFile="$(OutDir)\$(SolutionName).exe"
|
||||||
|
LinkIncremental="1"
|
||||||
|
GenerateDebugInformation="false"
|
||||||
|
SubSystem="1"
|
||||||
|
OptimizeReferences="2"
|
||||||
|
EnableCOMDATFolding="2"
|
||||||
|
TargetMachine="1"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCALinkTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCManifestTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCXDCMakeTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCBscMakeTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCFxCopTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCAppVerifierTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebDeploymentTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPostBuildEventTool"
|
||||||
|
/>
|
||||||
|
</Configuration>
|
||||||
|
</Configurations>
|
||||||
|
<References>
|
||||||
|
</References>
|
||||||
|
<Files>
|
||||||
|
<Filter
|
||||||
|
Name="src"
|
||||||
|
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
||||||
|
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
|
||||||
|
>
|
||||||
|
<File
|
||||||
|
RelativePath="..\bin\pg_reorg.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\bin\pgut\pgut-fe.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\bin\pgut\pgut.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
</Filter>
|
||||||
|
<Filter
|
||||||
|
Name="include"
|
||||||
|
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
||||||
|
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
|
||||||
|
>
|
||||||
|
<File
|
||||||
|
RelativePath="..\bin\pgut\pgut-fe.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\bin\pgut\pgut.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
</Filter>
|
||||||
|
<Filter
|
||||||
|
Name="regress"
|
||||||
|
>
|
||||||
|
<File
|
||||||
|
RelativePath="..\bin\expected\init.out"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\bin\sql\init.sql"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\bin\expected\reorg.out"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\bin\sql\reorg.sql"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
</Filter>
|
||||||
|
<File
|
||||||
|
RelativePath="..\bin\Makefile"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\readme.txt"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
</Files>
|
||||||
|
<Globals>
|
||||||
|
</Globals>
|
||||||
|
</VisualStudioProject>
|
151
msvc/lib.vcproj
Executable file
151
msvc/lib.vcproj
Executable file
@ -0,0 +1,151 @@
|
|||||||
|
<?xml version="1.0" encoding="shift_jis"?>
|
||||||
|
<VisualStudioProject
|
||||||
|
ProjectType="Visual C++"
|
||||||
|
Version="8.00"
|
||||||
|
Name="lib"
|
||||||
|
ProjectGUID="{B6B37F22-9E44-4240-AAA0-650D4AC2C2E2}"
|
||||||
|
RootNamespace="lib"
|
||||||
|
Keyword="Win32Proj"
|
||||||
|
>
|
||||||
|
<Platforms>
|
||||||
|
<Platform
|
||||||
|
Name="Win32"
|
||||||
|
/>
|
||||||
|
</Platforms>
|
||||||
|
<ToolFiles>
|
||||||
|
</ToolFiles>
|
||||||
|
<Configurations>
|
||||||
|
<Configuration
|
||||||
|
Name="Release|Win32"
|
||||||
|
OutputDirectory="$(SolutionDir)/bin"
|
||||||
|
IntermediateDirectory="$(SolutionDir)/obj/$(ProjectName)"
|
||||||
|
ConfigurationType="2"
|
||||||
|
CharacterSet="1"
|
||||||
|
WholeProgramOptimization="1"
|
||||||
|
>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreBuildEventTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCCustomBuildTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCXMLDataGeneratorTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebServiceProxyGeneratorTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCMIDLTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCCLCompilerTool"
|
||||||
|
AdditionalIncludeDirectories="../include"
|
||||||
|
PreprocessorDefinitions="WIN32;NDEBUG;_CRT_SECURE_NO_WARNINGS"
|
||||||
|
ExceptionHandling="0"
|
||||||
|
RuntimeLibrary="2"
|
||||||
|
UsePrecompiledHeader="0"
|
||||||
|
WarningLevel="3"
|
||||||
|
WarnAsError="true"
|
||||||
|
Detect64BitPortabilityProblems="false"
|
||||||
|
DebugInformationFormat="0"
|
||||||
|
CompileAs="1"
|
||||||
|
DisableSpecificWarnings="4996;4018"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCManagedResourceCompilerTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCResourceCompilerTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreLinkEventTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCLinkerTool"
|
||||||
|
AdditionalDependencies="kernel32.lib advapi32.lib ws2_32.lib $(NoInherit) postgres.lib libpq.lib"
|
||||||
|
OutputFile="$(OutDir)\$(SolutionName).dll"
|
||||||
|
LinkIncremental="1"
|
||||||
|
GenerateDebugInformation="false"
|
||||||
|
SubSystem="1"
|
||||||
|
OptimizeReferences="2"
|
||||||
|
EnableCOMDATFolding="2"
|
||||||
|
TargetMachine="1"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCALinkTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCManifestTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCXDCMakeTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCBscMakeTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCFxCopTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCAppVerifierTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebDeploymentTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPostBuildEventTool"
|
||||||
|
/>
|
||||||
|
</Configuration>
|
||||||
|
</Configurations>
|
||||||
|
<References>
|
||||||
|
</References>
|
||||||
|
<Files>
|
||||||
|
<Filter
|
||||||
|
Name="src"
|
||||||
|
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
||||||
|
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
|
||||||
|
>
|
||||||
|
<File
|
||||||
|
RelativePath="..\lib\pgut\pgut-be.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\lib\pgut\pgut-spi.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\lib\reorg.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
</Filter>
|
||||||
|
<Filter
|
||||||
|
Name="include"
|
||||||
|
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
||||||
|
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
|
||||||
|
>
|
||||||
|
<File
|
||||||
|
RelativePath="..\lib\pgut\pgut-be.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\lib\pgut\pgut-spi.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
</Filter>
|
||||||
|
<File
|
||||||
|
RelativePath="..\lib\Makefile"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\lib\pg_reorg.sql.in"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\lib\uninstall_pg_reorg.sql"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
</Files>
|
||||||
|
<Globals>
|
||||||
|
</Globals>
|
||||||
|
</VisualStudioProject>
|
21
msvc/pg_reorg.sln
Executable file
21
msvc/pg_reorg.sln
Executable file
@ -0,0 +1,21 @@
|
|||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 9.00
|
||||||
|
# Visual C++ Express 2005
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bin", "bin.vcproj", "{B6B37F22-9E44-4240-AAA0-650D4AC2C1E2}"
|
||||||
|
EndProject
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "lib", "lib.vcproj", "{B6B37F22-9E44-4240-AAA0-650D4AC2C2E2}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Release|Win32 = Release|Win32
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{B6B37F22-9E44-4240-AAA0-650D4AC2C1E2}.Release|Win32.ActiveCfg = Release|Win32
|
||||||
|
{B6B37F22-9E44-4240-AAA0-650D4AC2C1E2}.Release|Win32.Build.0 = Release|Win32
|
||||||
|
{B6B37F22-9E44-4240-AAA0-650D4AC2C2E2}.Release|Win32.ActiveCfg = Release|Win32
|
||||||
|
{B6B37F22-9E44-4240-AAA0-650D4AC2C2E2}.Release|Win32.Build.0 = Release|Win32
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
42
msvc/readme.txt
Executable file
42
msvc/readme.txt
Executable file
@ -0,0 +1,42 @@
|
|||||||
|
How to build with Microsoft Visual C++ Express 2005
|
||||||
|
|
||||||
|
You might need:
|
||||||
|
1. Register PostgreSQL directory to your environment.
|
||||||
|
2. Resolve redefinitions of ERROR macro.
|
||||||
|
|
||||||
|
----
|
||||||
|
1. Register PostgreSQL directory to your environment.
|
||||||
|
|
||||||
|
The directory configuration options are found in:
|
||||||
|
Tool > Option > Projects and Solutions > VC++ directory
|
||||||
|
|
||||||
|
You might need to add the following directories:
|
||||||
|
into "include files"
|
||||||
|
- C:\Program Files\PostgreSQL\8.4\include
|
||||||
|
- C:\Program Files\PostgreSQL\8.4\include\internal
|
||||||
|
- C:\Program Files\PostgreSQL\8.4\include\server
|
||||||
|
- C:\Program Files\PostgreSQL\8.4\include\server\port\win32
|
||||||
|
- C:\Program Files\PostgreSQL\8.4\include\server\port\win32_msvc
|
||||||
|
into "library files"
|
||||||
|
- C:\Program Files\PostgreSQL\8.4\lib
|
||||||
|
|
||||||
|
----
|
||||||
|
2. Resolve redefinitions of ERROR macro.
|
||||||
|
|
||||||
|
It might be a bad manner, but I'll recommend to modify your wingdi.h.
|
||||||
|
|
||||||
|
--- wingdi.h 2008-01-18 22:17:42.000000000 +0900
|
||||||
|
+++ wingdi.fixed.h 2010-03-03 09:51:43.015625000 +0900
|
||||||
|
@@ -101,11 +101,10 @@
|
||||||
|
#endif // (_WIN32_WINNT >= _WIN32_WINNT_WINXP)
|
||||||
|
|
||||||
|
/* Region Flags */
|
||||||
|
-#define ERROR 0
|
||||||
|
+#define RGN_ERROR 0
|
||||||
|
#define NULLREGION 1
|
||||||
|
#define SIMPLEREGION 2
|
||||||
|
#define COMPLEXREGION 3
|
||||||
|
-#define RGN_ERROR ERROR
|
||||||
|
|
||||||
|
/* CombineRgn() Styles */
|
||||||
|
#define RGN_AND 1
|
Loading…
x
Reference in New Issue
Block a user