Merge branch 'master' into change-tablespace
This commit is contained in:
		| @ -314,3 +314,51 @@ WARNING: relation "tbl_uk" must have a primary key or not-null unique keys | |||||||
| \! pg_repack --dbname=contrib_regression --no-order --table=tbl_nn_puk | \! pg_repack --dbname=contrib_regression --no-order --table=tbl_nn_puk | ||||||
| WARNING: relation "tbl_nn_puk" must have a primary key or not-null unique keys | WARNING: relation "tbl_nn_puk" must have a primary key or not-null unique keys | ||||||
| -- => WARNING | -- => WARNING | ||||||
|  | -- | ||||||
|  | -- pg_repack issue #3 | ||||||
|  | -- | ||||||
|  | CREATE TABLE issue3_1 (col1 int NOT NULL, col2 text NOT NULL); | ||||||
|  | CREATE UNIQUE INDEX issue3_1_idx ON issue3_1 (col1, col2 DESC); | ||||||
|  | SELECT repack.get_order_by('issue3_1_idx'::regclass::oid, 'issue3_1'::regclass::oid); | ||||||
|  |   get_order_by    | ||||||
|  | ----------------- | ||||||
|  |  col1, col2 DESC | ||||||
|  | (1 row) | ||||||
|  |  | ||||||
|  | \! pg_repack --dbname=contrib_regression --no-order --table=issue3_1 | ||||||
|  | CREATE TABLE issue3_2 (col1 int NOT NULL, col2 text NOT NULL); | ||||||
|  | CREATE UNIQUE INDEX issue3_2_idx ON issue3_2 (col1 DESC, col2 text_pattern_ops); | ||||||
|  | SELECT repack.get_order_by('issue3_2_idx'::regclass::oid, 'issue3_2'::regclass::oid); | ||||||
|  |        get_order_by         | ||||||
|  | --------------------------- | ||||||
|  |  col1 DESC, col2 USING ~<~ | ||||||
|  | (1 row) | ||||||
|  |  | ||||||
|  | \! pg_repack --dbname=contrib_regression --no-order --table=issue3_2 | ||||||
|  | CREATE TABLE issue3_3 (col1 int NOT NULL, col2 text NOT NULL); | ||||||
|  | CREATE UNIQUE INDEX issue3_3_idx ON issue3_3 (col1 DESC, col2 DESC); | ||||||
|  | SELECT repack.get_order_by('issue3_3_idx'::regclass::oid, 'issue3_3'::regclass::oid); | ||||||
|  |      get_order_by      | ||||||
|  | ---------------------- | ||||||
|  |  col1 DESC, col2 DESC | ||||||
|  | (1 row) | ||||||
|  |  | ||||||
|  | \! pg_repack --dbname=contrib_regression --no-order --table=issue3_3 | ||||||
|  | CREATE TABLE issue3_4 (col1 int NOT NULL, col2 text NOT NULL); | ||||||
|  | CREATE UNIQUE INDEX issue3_4_idx ON issue3_4 (col1 NULLS FIRST, col2 text_pattern_ops DESC NULLS LAST); | ||||||
|  | SELECT repack.get_order_by('issue3_4_idx'::regclass::oid, 'issue3_4'::regclass::oid); | ||||||
|  |                    get_order_by                    | ||||||
|  | -------------------------------------------------- | ||||||
|  |  col1 NULLS FIRST, col2 DESC USING ~<~ NULLS LAST | ||||||
|  | (1 row) | ||||||
|  |  | ||||||
|  | \! pg_repack --dbname=contrib_regression --no-order --table=issue3_4 | ||||||
|  | CREATE TABLE issue3_5 (col1 int NOT NULL, col2 text NOT NULL); | ||||||
|  | CREATE UNIQUE INDEX issue3_5_idx ON issue3_5 (col1 DESC NULLS FIRST, col2 COLLATE "POSIX" DESC); | ||||||
|  | SELECT repack.get_order_by('issue3_5_idx'::regclass::oid, 'issue3_5'::regclass::oid); | ||||||
|  |              get_order_by              | ||||||
|  | -------------------------------------- | ||||||
|  |  col1 DESC, col2 COLLATE "POSIX" DESC | ||||||
|  | (1 row) | ||||||
|  |  | ||||||
|  | \! pg_repack --dbname=contrib_regression --no-order --table=issue3_5 | ||||||
|  | |||||||
| @ -187,3 +187,31 @@ CREATE UNIQUE INDEX tbl_nn_puk_pcol1_idx ON tbl_nn_puk(col1) WHERE col1 < 10; | |||||||
| -- => OK | -- => OK | ||||||
| \! pg_repack --dbname=contrib_regression --no-order --table=tbl_nn_puk | \! pg_repack --dbname=contrib_regression --no-order --table=tbl_nn_puk | ||||||
| -- => WARNING | -- => WARNING | ||||||
|  |  | ||||||
|  | -- | ||||||
|  | -- pg_repack issue #3 | ||||||
|  | -- | ||||||
|  | CREATE TABLE issue3_1 (col1 int NOT NULL, col2 text NOT NULL); | ||||||
|  | CREATE UNIQUE INDEX issue3_1_idx ON issue3_1 (col1, col2 DESC); | ||||||
|  | SELECT repack.get_order_by('issue3_1_idx'::regclass::oid, 'issue3_1'::regclass::oid); | ||||||
|  | \! pg_repack --dbname=contrib_regression --no-order --table=issue3_1 | ||||||
|  |  | ||||||
|  | CREATE TABLE issue3_2 (col1 int NOT NULL, col2 text NOT NULL); | ||||||
|  | CREATE UNIQUE INDEX issue3_2_idx ON issue3_2 (col1 DESC, col2 text_pattern_ops); | ||||||
|  | SELECT repack.get_order_by('issue3_2_idx'::regclass::oid, 'issue3_2'::regclass::oid); | ||||||
|  | \! pg_repack --dbname=contrib_regression --no-order --table=issue3_2 | ||||||
|  |  | ||||||
|  | CREATE TABLE issue3_3 (col1 int NOT NULL, col2 text NOT NULL); | ||||||
|  | CREATE UNIQUE INDEX issue3_3_idx ON issue3_3 (col1 DESC, col2 DESC); | ||||||
|  | SELECT repack.get_order_by('issue3_3_idx'::regclass::oid, 'issue3_3'::regclass::oid); | ||||||
|  | \! pg_repack --dbname=contrib_regression --no-order --table=issue3_3 | ||||||
|  |  | ||||||
|  | CREATE TABLE issue3_4 (col1 int NOT NULL, col2 text NOT NULL); | ||||||
|  | CREATE UNIQUE INDEX issue3_4_idx ON issue3_4 (col1 NULLS FIRST, col2 text_pattern_ops DESC NULLS LAST); | ||||||
|  | SELECT repack.get_order_by('issue3_4_idx'::regclass::oid, 'issue3_4'::regclass::oid); | ||||||
|  | \! pg_repack --dbname=contrib_regression --no-order --table=issue3_4 | ||||||
|  |  | ||||||
|  | CREATE TABLE issue3_5 (col1 int NOT NULL, col2 text NOT NULL); | ||||||
|  | CREATE UNIQUE INDEX issue3_5_idx ON issue3_5 (col1 DESC NULLS FIRST, col2 COLLATE "POSIX" DESC); | ||||||
|  | SELECT repack.get_order_by('issue3_5_idx'::regclass::oid, 'issue3_5'::regclass::oid); | ||||||
|  | \! pg_repack --dbname=contrib_regression --no-order --table=issue3_5 | ||||||
|  | |||||||
| @ -44,8 +44,8 @@ $$ | |||||||
| $$ | $$ | ||||||
| LANGUAGE sql STABLE STRICT; | LANGUAGE sql STABLE STRICT; | ||||||
|  |  | ||||||
| CREATE FUNCTION repack.get_index_keys(oid, oid) RETURNS text AS | CREATE FUNCTION repack.get_order_by(oid, oid) RETURNS text AS | ||||||
| 'MODULE_PATHNAME', 'repack_get_index_keys' | 'MODULE_PATHNAME', 'repack_get_order_by' | ||||||
| LANGUAGE C STABLE STRICT; | LANGUAGE C STABLE STRICT; | ||||||
|  |  | ||||||
| CREATE FUNCTION repack.get_create_index_type(oid, name) RETURNS text AS | CREATE FUNCTION repack.get_create_index_type(oid, name) RETURNS text AS | ||||||
| @ -185,7 +185,7 @@ CREATE VIEW repack.tables AS | |||||||
|          repack.get_drop_columns(R.oid, 'repack.table_' || R.oid) AS drop_columns, |          repack.get_drop_columns(R.oid, 'repack.table_' || R.oid) AS drop_columns, | ||||||
|          'DELETE FROM repack.log_' || R.oid AS delete_log, |          'DELETE FROM repack.log_' || R.oid AS delete_log, | ||||||
|          'LOCK TABLE ' || repack.oid2text(R.oid) || ' IN ACCESS EXCLUSIVE MODE' AS lock_table, |          'LOCK TABLE ' || repack.oid2text(R.oid) || ' IN ACCESS EXCLUSIVE MODE' AS lock_table, | ||||||
|          repack.get_index_keys(CK.indexrelid, R.oid) AS ckey, |          repack.get_order_by(CK.indexrelid, R.oid) AS ckey, | ||||||
|          'SELECT * FROM repack.log_' || R.oid || ' ORDER BY id LIMIT $1' AS sql_peek, |          'SELECT * FROM repack.log_' || R.oid || ' ORDER BY id LIMIT $1' AS sql_peek, | ||||||
|          'INSERT INTO repack.table_' || R.oid || ' VALUES ($1.*)' AS sql_insert, |          'INSERT INTO repack.table_' || R.oid || ' VALUES ($1.*)' AS sql_insert, | ||||||
|          'DELETE FROM repack.table_' || R.oid || ' WHERE ' || repack.get_compare_pkey(PK.indexrelid, '$1') AS sql_delete, |          'DELETE FROM repack.table_' || R.oid || ' WHERE ' || repack.get_compare_pkey(PK.indexrelid, '$1') AS sql_delete, | ||||||
|  | |||||||
							
								
								
									
										62
									
								
								lib/repack.c
									
									
									
									
									
								
							
							
						
						
									
										62
									
								
								lib/repack.c
									
									
									
									
									
								
							| @ -41,7 +41,7 @@ PG_MODULE_MAGIC; | |||||||
| extern Datum PGUT_EXPORT repack_version(PG_FUNCTION_ARGS); | extern Datum PGUT_EXPORT repack_version(PG_FUNCTION_ARGS); | ||||||
| extern Datum PGUT_EXPORT repack_trigger(PG_FUNCTION_ARGS); | extern Datum PGUT_EXPORT repack_trigger(PG_FUNCTION_ARGS); | ||||||
| extern Datum PGUT_EXPORT repack_apply(PG_FUNCTION_ARGS); | extern Datum PGUT_EXPORT repack_apply(PG_FUNCTION_ARGS); | ||||||
| extern Datum PGUT_EXPORT repack_get_index_keys(PG_FUNCTION_ARGS); | extern Datum PGUT_EXPORT repack_get_order_by(PG_FUNCTION_ARGS); | ||||||
| extern Datum PGUT_EXPORT repack_indexdef(PG_FUNCTION_ARGS); | extern Datum PGUT_EXPORT repack_indexdef(PG_FUNCTION_ARGS); | ||||||
| extern Datum PGUT_EXPORT repack_swap(PG_FUNCTION_ARGS); | extern Datum PGUT_EXPORT repack_swap(PG_FUNCTION_ARGS); | ||||||
| extern Datum PGUT_EXPORT repack_drop(PG_FUNCTION_ARGS); | extern Datum PGUT_EXPORT repack_drop(PG_FUNCTION_ARGS); | ||||||
| @ -50,7 +50,7 @@ extern Datum PGUT_EXPORT repack_disable_autovacuum(PG_FUNCTION_ARGS); | |||||||
| PG_FUNCTION_INFO_V1(repack_version); | PG_FUNCTION_INFO_V1(repack_version); | ||||||
| PG_FUNCTION_INFO_V1(repack_trigger); | PG_FUNCTION_INFO_V1(repack_trigger); | ||||||
| PG_FUNCTION_INFO_V1(repack_apply); | PG_FUNCTION_INFO_V1(repack_apply); | ||||||
| PG_FUNCTION_INFO_V1(repack_get_index_keys); | PG_FUNCTION_INFO_V1(repack_get_order_by); | ||||||
| PG_FUNCTION_INFO_V1(repack_indexdef); | PG_FUNCTION_INFO_V1(repack_indexdef); | ||||||
| PG_FUNCTION_INFO_V1(repack_swap); | PG_FUNCTION_INFO_V1(repack_swap); | ||||||
| PG_FUNCTION_INFO_V1(repack_drop); | PG_FUNCTION_INFO_V1(repack_drop); | ||||||
| @ -472,21 +472,51 @@ parse_indexdef(IndexDef *stmt, Oid index, Oid table) | |||||||
| 	stmt->options = sql; | 	stmt->options = sql; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * Parse the trailing ... [ COLLATE X ] [ DESC ] [ NULLS { FIRST | LAST } ] from an index | ||||||
|  |  * definition column. | ||||||
|  |  * Returned values point to token. \0's are inserted to separate parsed parts. | ||||||
|  |  */ | ||||||
|  | static void | ||||||
|  | parse_indexdef_col(char *token, char **desc, char **nulls, char **collate) | ||||||
|  | { | ||||||
|  | 	char *pos; | ||||||
|  |  | ||||||
|  | 	/* easier to walk backwards than to parse quotes and escapes... */ | ||||||
|  | 	if (NULL != (pos = strstr(token, " NULLS FIRST"))) | ||||||
|  | 	{ | ||||||
|  | 		*nulls = pos + 1; | ||||||
|  | 		*pos = '\0'; | ||||||
|  | 	} | ||||||
|  | 	else if (NULL != (pos = strstr(token, " NULLS LAST"))) | ||||||
|  | 	{ | ||||||
|  | 		*nulls = pos + 1; | ||||||
|  | 		*pos = '\0'; | ||||||
|  | 	} | ||||||
|  | 	if (NULL != (pos = strstr(token, " DESC"))) | ||||||
|  | 	{ | ||||||
|  | 		*desc = pos + 1; | ||||||
|  | 		*pos = '\0'; | ||||||
|  | 	} | ||||||
|  | 	if (NULL != (pos = strstr(token, " COLLATE "))) | ||||||
|  | 	{ | ||||||
|  | 		*collate = pos + 1; | ||||||
|  | 		*pos = '\0'; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * @fn      Datum repack_get_index_keys(PG_FUNCTION_ARGS) |  * @fn      Datum repack_get_order_by(PG_FUNCTION_ARGS) | ||||||
|  * @brief   Get key definition of the index. |  * @brief   Get key definition of the index. | ||||||
|  * |  * | ||||||
|  * repack_get_index_keys(index, table) |  * repack_get_order_by(index, table) | ||||||
|  * |  * | ||||||
|  * @param	index	Oid of target index. |  * @param	index	Oid of target index. | ||||||
|  * @param	table	Oid of table of the index. |  * @param	table	Oid of table of the index. | ||||||
|  * @retval			Create index DDL for temp table. |  * @retval			Create index DDL for temp table. | ||||||
|  * |  | ||||||
|  * FIXME: this function is named get_index_keys, but actually returns |  | ||||||
|  * an expression for ORDER BY clause. get_order_by() might be a better name. |  | ||||||
|  */ |  */ | ||||||
| Datum | Datum | ||||||
| repack_get_index_keys(PG_FUNCTION_ARGS) | repack_get_order_by(PG_FUNCTION_ARGS) | ||||||
| { | { | ||||||
| 	Oid				index = PG_GETARG_OID(0); | 	Oid				index = PG_GETARG_OID(0); | ||||||
| 	Oid				table = PG_GETARG_OID(1); | 	Oid				table = PG_GETARG_OID(1); | ||||||
| @ -514,12 +544,21 @@ repack_get_index_keys(PG_FUNCTION_ARGS) | |||||||
| 	for (nattr = 0, next = stmt.columns; next; nattr++) | 	for (nattr = 0, next = stmt.columns; next; nattr++) | ||||||
| 	{ | 	{ | ||||||
| 		char *opcname; | 		char *opcname; | ||||||
|  | 		char *coldesc = NULL; | ||||||
|  | 		char *colnulls = NULL; | ||||||
|  | 		char *colcollate = NULL; | ||||||
|  |  | ||||||
| 		token = next; | 		token = next; | ||||||
| 		while (isspace((unsigned char) *token)) | 		while (isspace((unsigned char) *token)) | ||||||
| 			token++; | 			token++; | ||||||
| 		next = skip_until(index, next, ','); | 		next = skip_until(index, next, ','); | ||||||
|  | 		parse_indexdef_col(token, &coldesc, &colnulls, &colcollate); | ||||||
| 		opcname = skip_until(index, token, ' '); | 		opcname = skip_until(index, token, ' '); | ||||||
|  | 		appendStringInfoString(&str, token); | ||||||
|  | 		if (colcollate) | ||||||
|  | 			appendStringInfo(&str, " %s", colcollate); | ||||||
|  | 		if (coldesc) | ||||||
|  | 			appendStringInfo(&str, " %s", coldesc); | ||||||
| 		if (opcname) | 		if (opcname) | ||||||
| 		{ | 		{ | ||||||
| 			/* lookup default operator name from operator class */ | 			/* lookup default operator name from operator class */ | ||||||
| @ -556,12 +595,11 @@ repack_get_index_keys(PG_FUNCTION_ARGS) | |||||||
| 				elog(ERROR, "missing operator %d(%u,%u) in opfamily %u", | 				elog(ERROR, "missing operator %d(%u,%u) in opfamily %u", | ||||||
| 					 strategy, opcintype, opcintype, opfamily); | 					 strategy, opcintype, opcintype, opfamily); | ||||||
|  |  | ||||||
|  |  | ||||||
| 			opcname[-1] = '\0'; | 			opcname[-1] = '\0'; | ||||||
| 			appendStringInfo(&str, "%s USING %s", token, get_opname(oprid)); | 			appendStringInfo(&str, " USING %s", get_opname(oprid)); | ||||||
| 		} | 		} | ||||||
| 		else | 		if (colnulls) | ||||||
| 			appendStringInfoString(&str, token); | 			appendStringInfo(&str, " %s", colnulls); | ||||||
| 		if (next) | 		if (next) | ||||||
| 			appendStringInfoString(&str, ", "); | 			appendStringInfoString(&str, ", "); | ||||||
| 	} | 	} | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user