Fix crashes when cluster indexes have storage options (fillfactor, etc).
This commit is contained in:
parent
7084ec6de9
commit
a7a42b7bbf
@ -6,9 +6,9 @@ CREATE TABLE tbl_cluster (
|
|||||||
col1 int,
|
col1 int,
|
||||||
col2 timestamp,
|
col2 timestamp,
|
||||||
","")" text,
|
","")" text,
|
||||||
PRIMARY KEY (","")", col1)
|
PRIMARY KEY (","")", col1) WITH (fillfactor = 75)
|
||||||
) WITH (fillfactor = 70);
|
) WITH (fillfactor = 70);
|
||||||
CREATE INDEX ","") cluster" ON tbl_cluster (col2, length(","")"), ","")" text_pattern_ops);
|
CREATE INDEX ","") cluster" ON tbl_cluster (col2, length(","")"), ","")" text_pattern_ops) WITH (fillfactor = 75);
|
||||||
ALTER TABLE tbl_cluster CLUSTER ON ","") cluster";
|
ALTER TABLE tbl_cluster CLUSTER ON ","") cluster";
|
||||||
CREATE TABLE tbl_only_pkey (
|
CREATE TABLE tbl_only_pkey (
|
||||||
col1 int PRIMARY KEY,
|
col1 int PRIMARY KEY,
|
||||||
@ -35,8 +35,9 @@ CREATE TABLE tbl_with_dropped_column (
|
|||||||
c2 text,
|
c2 text,
|
||||||
d3 text
|
d3 text
|
||||||
);
|
);
|
||||||
|
ALTER INDEX tbl_with_dropped_column_pkey SET (fillfactor = 75);
|
||||||
ALTER TABLE tbl_with_dropped_column CLUSTER ON tbl_with_dropped_column_pkey;
|
ALTER TABLE tbl_with_dropped_column CLUSTER ON tbl_with_dropped_column_pkey;
|
||||||
CREATE INDEX idx_c1c2 ON tbl_with_dropped_column (c1, c2);
|
CREATE INDEX idx_c1c2 ON tbl_with_dropped_column (c1, c2) WITH (fillfactor = 75);
|
||||||
CREATE INDEX idx_c2c1 ON tbl_with_dropped_column (c2, c1);
|
CREATE INDEX idx_c2c1 ON tbl_with_dropped_column (c2, c1);
|
||||||
--
|
--
|
||||||
-- insert data
|
-- insert data
|
||||||
@ -85,8 +86,8 @@ SELECT * FROM tbl_with_dropped_column;
|
|||||||
col2 | timestamp without time zone |
|
col2 | timestamp without time zone |
|
||||||
,") | text | not null
|
,") | text | not null
|
||||||
Indexes:
|
Indexes:
|
||||||
"tbl_cluster_pkey" PRIMARY KEY, btree (","")", col1)
|
"tbl_cluster_pkey" PRIMARY KEY, btree (","")", col1) WITH (fillfactor=75)
|
||||||
",") cluster" btree (col2, length(","")"), ","")" text_pattern_ops) CLUSTER
|
",") cluster" btree (col2, length(","")"), ","")" text_pattern_ops) WITH (fillfactor=75) CLUSTER
|
||||||
|
|
||||||
\d tbl_gistkey
|
\d tbl_gistkey
|
||||||
Table "public.tbl_gistkey"
|
Table "public.tbl_gistkey"
|
||||||
@ -126,8 +127,8 @@ Table "public.tbl_with_dropped_column"
|
|||||||
c2 | text |
|
c2 | text |
|
||||||
c3 | text |
|
c3 | text |
|
||||||
Indexes:
|
Indexes:
|
||||||
"tbl_with_dropped_column_pkey" PRIMARY KEY, btree (id) CLUSTER
|
"tbl_with_dropped_column_pkey" PRIMARY KEY, btree (id) WITH (fillfactor=75) CLUSTER
|
||||||
"idx_c1c2" btree (c1, c2)
|
"idx_c1c2" btree (c1, c2) WITH (fillfactor=75)
|
||||||
"idx_c2c1" btree (c2, c1)
|
"idx_c2c1" btree (c2, c1)
|
||||||
|
|
||||||
SELECT col1, to_char(col2, 'YYYY-MM-DD HH24:MI:SS'), ","")" FROM tbl_cluster;
|
SELECT col1, to_char(col2, 'YYYY-MM-DD HH24:MI:SS'), ","")" FROM tbl_cluster;
|
||||||
|
@ -144,8 +144,8 @@ option_find(int c, pgut_option opts1[], pgut_option opts2[])
|
|||||||
return NULL; /* not found */
|
return NULL; /* not found */
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
void
|
||||||
assign_option(pgut_option *opt, const char *optarg, pgut_optsrc src)
|
pgut_setopt(pgut_option *opt, const char *optarg, pgut_optsrc src)
|
||||||
{
|
{
|
||||||
const char *message;
|
const char *message;
|
||||||
|
|
||||||
@ -578,7 +578,7 @@ option_from_env(pgut_option options[])
|
|||||||
name[j] = '\0';
|
name[j] = '\0';
|
||||||
|
|
||||||
if ((value = getenv(name)) != NULL)
|
if ((value = getenv(name)) != NULL)
|
||||||
assign_option(opt, value, SOURCE_ENV);
|
pgut_setopt(opt, value, SOURCE_ENV);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -620,7 +620,7 @@ pgut_getopt(int argc, char **argv, pgut_option options[])
|
|||||||
while ((c = getopt_long(argc, argv, optstring, longopts, &optindex)) != -1)
|
while ((c = getopt_long(argc, argv, optstring, longopts, &optindex)) != -1)
|
||||||
{
|
{
|
||||||
opt = option_find(c, default_options, options);
|
opt = option_find(c, default_options, options);
|
||||||
assign_option(opt, optarg, SOURCE_CMDLINE);
|
pgut_setopt(opt, optarg, SOURCE_CMDLINE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Read environment variables */
|
/* Read environment variables */
|
||||||
@ -637,8 +637,8 @@ pgut_getopt(int argc, char **argv, pgut_option options[])
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* compare two strings ignore cases and ignore -_ */
|
/* compare two strings ignore cases and ignore -_ */
|
||||||
static bool
|
bool
|
||||||
key_equals(const char *lhs, const char *rhs)
|
pgut_keyeq(const char *lhs, const char *rhs)
|
||||||
{
|
{
|
||||||
for (; *lhs && *rhs; lhs++, rhs++)
|
for (; *lhs && *rhs; lhs++, rhs++)
|
||||||
{
|
{
|
||||||
@ -684,13 +684,13 @@ pgut_readopt(const char *path, pgut_option options[], int elevel)
|
|||||||
{
|
{
|
||||||
pgut_option *opt = &options[i];
|
pgut_option *opt = &options[i];
|
||||||
|
|
||||||
if (key_equals(key, opt->lname))
|
if (pgut_keyeq(key, opt->lname))
|
||||||
{
|
{
|
||||||
if (opt->allowed == SOURCE_DEFAULT ||
|
if (opt->allowed == SOURCE_DEFAULT ||
|
||||||
opt->allowed > SOURCE_FILE)
|
opt->allowed > SOURCE_FILE)
|
||||||
elog(elevel, "option %s cannot specified in file", opt->lname);
|
elog(elevel, "option %s cannot specified in file", opt->lname);
|
||||||
else if (opt->source <= SOURCE_FILE)
|
else if (opt->source <= SOURCE_FILE)
|
||||||
assign_option(opt, value, SOURCE_FILE);
|
pgut_setopt(opt, value, SOURCE_FILE);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -105,6 +105,8 @@ extern bool interrupted;
|
|||||||
extern void help(bool details);
|
extern void help(bool details);
|
||||||
extern int pgut_getopt(int argc, char **argv, pgut_option options[]);
|
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_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);
|
||||||
|
|
||||||
|
@ -6,10 +6,10 @@ CREATE TABLE tbl_cluster (
|
|||||||
col1 int,
|
col1 int,
|
||||||
col2 timestamp,
|
col2 timestamp,
|
||||||
","")" text,
|
","")" text,
|
||||||
PRIMARY KEY (","")", col1)
|
PRIMARY KEY (","")", col1) WITH (fillfactor = 75)
|
||||||
) WITH (fillfactor = 70);
|
) WITH (fillfactor = 70);
|
||||||
|
|
||||||
CREATE INDEX ","") cluster" ON tbl_cluster (col2, length(","")"), ","")" text_pattern_ops);
|
CREATE INDEX ","") cluster" ON tbl_cluster (col2, length(","")"), ","")" text_pattern_ops) WITH (fillfactor = 75);
|
||||||
ALTER TABLE tbl_cluster CLUSTER ON ","") cluster";
|
ALTER TABLE tbl_cluster CLUSTER ON ","") cluster";
|
||||||
|
|
||||||
CREATE TABLE tbl_only_pkey (
|
CREATE TABLE tbl_only_pkey (
|
||||||
@ -42,8 +42,9 @@ CREATE TABLE tbl_with_dropped_column (
|
|||||||
c2 text,
|
c2 text,
|
||||||
d3 text
|
d3 text
|
||||||
);
|
);
|
||||||
|
ALTER INDEX tbl_with_dropped_column_pkey SET (fillfactor = 75);
|
||||||
ALTER TABLE tbl_with_dropped_column CLUSTER ON tbl_with_dropped_column_pkey;
|
ALTER TABLE tbl_with_dropped_column CLUSTER ON tbl_with_dropped_column_pkey;
|
||||||
CREATE INDEX idx_c1c2 ON tbl_with_dropped_column (c1, c2);
|
CREATE INDEX idx_c1c2 ON tbl_with_dropped_column (c1, c2) WITH (fillfactor = 75);
|
||||||
CREATE INDEX idx_c2c1 ON tbl_with_dropped_column (c2, c1);
|
CREATE INDEX idx_c2c1 ON tbl_with_dropped_column (c2, c1);
|
||||||
|
|
||||||
--
|
--
|
||||||
|
20
lib/reorg.c
20
lib/reorg.c
@ -350,6 +350,10 @@ skip_ident(Oid index, char *sql)
|
|||||||
return parse_error(index);
|
return parse_error(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Skip until 'end' character found. The 'end' character is replaced with \0.
|
||||||
|
* Returns the next character of the 'end', or NULL if 'end' is not found.
|
||||||
|
*/
|
||||||
static char *
|
static char *
|
||||||
skip_until(Oid index, char *sql, char end)
|
skip_until(Oid index, char *sql, char end)
|
||||||
{
|
{
|
||||||
@ -391,8 +395,13 @@ skip_until(Oid index, char *sql, char end)
|
|||||||
|
|
||||||
if (nopen == 0 && instr == 0)
|
if (nopen == 0 && instr == 0)
|
||||||
{
|
{
|
||||||
*sql = '\0';
|
if (*sql)
|
||||||
return sql + 1;
|
{
|
||||||
|
*sql = '\0';
|
||||||
|
return sql + 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* error */
|
/* error */
|
||||||
@ -427,7 +436,8 @@ parse_indexdef(IndexDef *stmt, Oid index, Oid table)
|
|||||||
parse_error(index);
|
parse_error(index);
|
||||||
sql++;
|
sql++;
|
||||||
stmt->columns = sql;
|
stmt->columns = sql;
|
||||||
sql = skip_until(index, sql, ')');
|
if ((sql = skip_until(index, sql, ')')) == NULL)
|
||||||
|
parse_error(index);
|
||||||
/* options */
|
/* options */
|
||||||
stmt->options = sql;
|
stmt->options = sql;
|
||||||
}
|
}
|
||||||
@ -467,7 +477,7 @@ reorg_get_index_keys(PG_FUNCTION_ARGS)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
initStringInfo(&str);
|
initStringInfo(&str);
|
||||||
for (nattr = 0, next = stmt.columns; *next; nattr++)
|
for (nattr = 0, next = stmt.columns; next; nattr++)
|
||||||
{
|
{
|
||||||
char *opcname;
|
char *opcname;
|
||||||
|
|
||||||
@ -544,7 +554,7 @@ reorg_get_index_keys(PG_FUNCTION_ARGS)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
appendStringInfoString(&str, token);
|
appendStringInfoString(&str, token);
|
||||||
if (*next)
|
if (next)
|
||||||
appendStringInfoChar(&str, ',');
|
appendStringInfoChar(&str, ',');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user