!210 fix dump interval partitioned table issue

Merge pull request !210 from yujiang/dump_interval_part_tab
This commit is contained in:
opengauss-bot
2020-09-11 15:56:57 +08:00
committed by Gitee
4 changed files with 364 additions and 2 deletions

View File

@ -156,6 +156,11 @@ typedef struct {
int objsubid; /* subobject (table column #) */
} SecLabelItem;
typedef struct {
Oid oid;
char* name;
} TablespaceInfo;
/* global decls */
bool g_verbose; /* User wants verbose narration of our
* activities. */
@ -267,6 +272,9 @@ bool isSingleTableDump = false;
static int include_nodes = 0;
#endif
static int g_tablespaceNum = -1;
static TablespaceInfo* g_tablespaces = nullptr;
#define disconnect_and_exit(conn, code) \
do { \
if ((conn) != NULL) { \
@ -15630,6 +15638,65 @@ static void binary_upgrade_set_pg_partition_oids(
destroyPQExpBuffer(upgrade_query);
}
static void LoadTablespaces(Archive* fout)
{
PQExpBuffer query = createPQExpBuffer();
appendPQExpBuffer(query, "select oid, spcname from pg_tablespace");
PGresult* res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
g_tablespaceNum = PQntuples(res);
Assert(g_tablespaceNum > 0);
g_tablespaces = (TablespaceInfo*)pg_malloc(g_tablespaceNum * sizeof(TablespaceInfo));
for (int i = 0; i < g_tablespaceNum; ++i) {
g_tablespaces[i].oid = atooid(PQgetvalue(res, i, 0));
g_tablespaces[i].name = gs_strdup(PQgetvalue(res, i, 1));
}
destroyPQExpBuffer(query);
PQclear(res);
}
static const char* GetTablespaceNameByOid(Archive* fout, Oid oid)
{
if (g_tablespaceNum == -1) {
LoadTablespaces(fout);
}
for (int i = 0; i < g_tablespaceNum; ++i) {
if (g_tablespaces[i].oid == oid) {
return g_tablespaces[i].name;
}
}
exit_horribly(NULL, "tablespace %u not exist\n", oid);
}
static void OutputIntervalPartitionDef(Archive* fout, const PGresult* res, PQExpBuffer outputBuf)
{
int intervalIdx = PQfnumber(res, "interval");
appendPQExpBuffer(outputBuf, "INTERVAL('%s')", PQgetvalue(res, 0, intervalIdx));
int interTblSpcNumIdx = PQfnumber(res, "inttblspcnum");
if (PQgetisnull(res, 0, interTblSpcNumIdx)) {
return;
}
int interTblSpcNum = atoi(PQgetvalue(res, 0, interTblSpcNumIdx));
if (interTblSpcNum <= 0) {
return;
}
appendPQExpBuffer(outputBuf, " STORE IN(");
int interTblSpcIdx = PQfnumber(res, "intervaltablespace");
Oid* interTblSpcs = (Oid*)pg_malloc((size_t)interTblSpcNum * sizeof(Oid));
parseOidArray(PQgetvalue(res, 0, interTblSpcIdx), interTblSpcs, interTblSpcNum);
for (int i = 0; i < interTblSpcNum; ++i) {
if (i > 0) {
appendPQExpBuffer(outputBuf, ", ");
}
appendPQExpBuffer(outputBuf, "%s", GetTablespaceNameByOid(fout, interTblSpcs[i]));
}
appendPQExpBuffer(outputBuf, ")");
free(interTblSpcs);
}
/*
* createTablePartition
* Write the declaration of partitioned table.
@ -15659,7 +15726,7 @@ static PQExpBuffer createTablePartition(Archive* fout, TableInfo* tbinfo)
appendPQExpBuffer(defq,
"SELECT partstrategy, interval[1], "
"array_length(partkey, 1) AS partkeynum, partkey, "
"intspnum AS inttblspcnum, intervaltablespace "
"array_length(intervaltablespace, 1) AS inttblspcnum, intervaltablespace "
"FROM pg_partition WHERE parentid = '%u' AND parttype = '%c'",
tbinfo->dobj.catId.oid,
PART_OBJ_TYPE_PARTED_TABLE);
@ -15670,7 +15737,11 @@ static PQExpBuffer createTablePartition(Archive* fout, TableInfo* tbinfo)
partkeynum = atoi(PQgetvalue(res, 0, i_partkeynum));
partkeycols = (Oid*)pg_malloc((size_t)partkeynum * sizeof(Oid));
parseOidArray(PQgetvalue(res, 0, i_partkey), partkeycols, partkeynum);
PQclear(res);
int partStrategyIdx = PQfnumber(res, "partstrategy");
char partStrategy = *PQgetvalue(res, 0, partStrategyIdx);
if (partStrategy != PART_STRATEGY_INTERVAL) {
PQclear(res);
}
if (RELKIND_FOREIGN_TABLE == tbinfo->relkind) {
int i_fdwname = -1;
@ -15714,6 +15785,12 @@ static PQExpBuffer createTablePartition(Archive* fout, TableInfo* tbinfo)
}
appendPQExpBuffer(result, ")\n");
if (partStrategy == PART_STRATEGY_INTERVAL) {
OutputIntervalPartitionDef(fout, res, result);
appendPQExpBuffer(result, "\n");
PQclear(res);
}
/* generate partition details */
if (isHDFSFTbl) {
appendPQExpBuffer(result, "AUTOMAPPED");

View File

@ -0,0 +1,112 @@
--
-- test interval partition without specified tablespaces
--
-- prepare: create interval partition table and load data
create database interval_db;
\c interval_db;
drop table if exists t_part_auto;
create table t_part_auto(id int not null, name varchar, birthday timestamp not null, age int)
partition by range(birthday) interval ('1 month') (
partition p1 values less than('2000-01-01 00:00:00'),
partition p2 values less than('2000-02-01 00:00:00')
);
declare
v_sql varchar;
v_name varchar;
v_dt_begin timestamp;
v_dt timestamp;
v_age int;
begin
v_sql := 'insert into t_part_auto(id, name, birthday, age) values(:1, :2, :3, :4)';
v_dt_begin := to_date('1999-10-01 00:00:00', 'yyyy-mm-dd hh24:mi:ss');
for i in 1..200 loop
v_name := 'name_' || i;
v_dt := v_dt_begin + i*30;
v_age := mod(i,90) + 5;
execute immediate v_sql using i, v_name, v_dt, v_age;
end loop;
end;
/
\d t_part_auto
select count(1) from t_part_auto;
-- dump data
\! @abs_bindir@/gs_dump interval_db -p @portstring@ -t t_part_auto -f @abs_bindir@/backup.sql
drop table t_part_auto;
-- restore data
\! @abs_bindir@/gsql -p @portstring@ -d interval_db -f @abs_bindir@/backup.sql
\d t_part_auto
select count(1) from t_part_auto;
drop table t_part_auto;
--
-- test interval partition with specified tablespaces
--
-- prepare: create interval partition table and load data
create tablespace interval_tsp1 location '@testtablespace@/interval_tsp1' maxsize '20M';
create tablespace interval_tsp2 location '@testtablespace@/interval_tsp2' maxsize '20M';
create tablespace interval_tsp3 location '@testtablespace@/interval_tsp3' maxsize '20M';
drop table if exists t_part_auto;
create table t_part_auto(id int not null, name varchar, birthday timestamp not null, age int)
partition by range(birthday)
interval ('1 month') store in(interval_tsp1, interval_tsp2, interval_tsp3)
(
partition p1 values less than('2000-01-01 00:00:00'),
partition p2 values less than('2000-02-01 00:00:00')
);
declare
v_sql varchar;
v_name varchar;
v_dt_begin timestamp;
v_dt timestamp;
v_age int;
begin
v_sql := 'insert into t_part_auto(id, name, birthday, age) values(:1, :2, :3, :4)';
v_dt_begin := to_date('1999-10-01 00:00:00', 'yyyy-mm-dd hh24:mi:ss');
for i in 1..200 loop
v_name := 'name_' || i;
v_dt := v_dt_begin + i*30;
v_age := mod(i,90) + 5;
execute immediate v_sql using i, v_name, v_dt, v_age;
end loop;
end;
/
-- dump data
\! @abs_bindir@/gs_dump interval_db -p @portstring@ -t t_part_auto -f @abs_bindir@/backup.sql
drop table t_part_auto;
-- restore data
\! @abs_bindir@/gsql -p @portstring@ -d interval_db -f @abs_bindir@/backup.sql
\d t_part_auto
select count(1) from t_part_auto;
-- check tablespace
select spcname from pg_tablespace where oid in(select intervaltablespace[0] from pg_partition where relname = 't_part_auto' union select intervaltablespace[1] from pg_partition where relname = 't_part_auto' union select intervaltablespace[2] from pg_partition where relname = 't_part_auto') order by spcname;
drop table t_part_auto;
drop tablespace interval_tsp1;
drop tablespace interval_tsp2;
drop tablespace interval_tsp3;
\c regression
drop database interval_db;

View File

@ -0,0 +1,172 @@
--
-- test interval partition without specified tablespaces
--
-- prepare: create interval partition table and load data
create database interval_db;
\c interval_db;
drop table if exists t_part_auto;
NOTICE: table "t_part_auto" does not exist, skipping
create table t_part_auto(id int not null, name varchar, birthday timestamp not null, age int)
partition by range(birthday) interval ('1 month') (
partition p1 values less than('2000-01-01 00:00:00'),
partition p2 values less than('2000-02-01 00:00:00')
);
declare
v_sql varchar;
v_name varchar;
v_dt_begin timestamp;
v_dt timestamp;
v_age int;
begin
v_sql := 'insert into t_part_auto(id, name, birthday, age) values(:1, :2, :3, :4)';
v_dt_begin := to_date('1999-10-01 00:00:00', 'yyyy-mm-dd hh24:mi:ss');
for i in 1..200 loop
v_name := 'name_' || i;
v_dt := v_dt_begin + i*30;
v_age := mod(i,90) + 5;
execute immediate v_sql using i, v_name, v_dt, v_age;
end loop;
end;
/
\d t_part_auto
Table "public.t_part_auto"
Column | Type | Modifiers
----------+-----------------------------+-----------
id | integer | not null
name | character varying |
birthday | timestamp without time zone | not null
age | integer |
Interval partition by(birthday)
Number of partition: 195 (View pg_partition to check each partition range.)
select count(1) from t_part_auto;
count
-------
200
(1 row)
-- dump data
\! @abs_bindir@/gs_dump interval_db -p @portstring@ -t t_part_auto -f @abs_bindir@/backup.sql
--?gs_dump[port='@portstring@'][interval_db][.*]: The total objects number is 374.
--?gs_dump[port='@portstring@'][interval_db][.*]: [100.00%] 374 objects have been dumped.
--?gs_dump[port='@portstring@'][interval_db][.*]: dump database interval_db successfully
--?gs_dump[port='@portstring@'][interval_db][.*]: total time: .* ms
drop table t_part_auto;
-- restore data
\! @abs_bindir@/gsql -p @portstring@ -d interval_db -f @abs_bindir@/backup.sql
SET
SET
SET
SET
SET
SET
SET
SET
SET
CREATE TABLE
ALTER TABLE
--?total time: .* ms
\d t_part_auto
Table "public.t_part_auto"
Column | Type | Modifiers
----------+-----------------------------+-----------
id | integer | not null
name | character varying |
birthday | timestamp without time zone | not null
age | integer |
Interval partition by(birthday)
Number of partition: 195 (View pg_partition to check each partition range.)
select count(1) from t_part_auto;
count
-------
200
(1 row)
drop table t_part_auto;
--
-- test interval partition with specified tablespaces
--
-- prepare: create interval partition table and load data
create tablespace interval_tsp1 location '@testtablespace@/interval_tsp1' maxsize '20M';
create tablespace interval_tsp2 location '@testtablespace@/interval_tsp2' maxsize '20M';
create tablespace interval_tsp3 location '@testtablespace@/interval_tsp3' maxsize '20M';
drop table if exists t_part_auto;
NOTICE: table "t_part_auto" does not exist, skipping
create table t_part_auto(id int not null, name varchar, birthday timestamp not null, age int)
partition by range(birthday)
interval ('1 month') store in(interval_tsp1, interval_tsp2, interval_tsp3)
(
partition p1 values less than('2000-01-01 00:00:00'),
partition p2 values less than('2000-02-01 00:00:00')
);
declare
v_sql varchar;
v_name varchar;
v_dt_begin timestamp;
v_dt timestamp;
v_age int;
begin
v_sql := 'insert into t_part_auto(id, name, birthday, age) values(:1, :2, :3, :4)';
v_dt_begin := to_date('1999-10-01 00:00:00', 'yyyy-mm-dd hh24:mi:ss');
for i in 1..200 loop
v_name := 'name_' || i;
v_dt := v_dt_begin + i*30;
v_age := mod(i,90) + 5;
execute immediate v_sql using i, v_name, v_dt, v_age;
end loop;
end;
/
-- dump data
\! @abs_bindir@/gs_dump interval_db -p @portstring@ -t t_part_auto -f @abs_bindir@/backup.sql
--?gs_dump[port='@portstring@'][interval_db][.*]: The total objects number is 374.
--?gs_dump[port='@portstring@'][interval_db][.*]: [100.00%] 374 objects have been dumped.
--?gs_dump[port='@portstring@'][interval_db][.*]: dump database interval_db successfully
--?gs_dump[port='@portstring@'][interval_db][.*]: total time: .* ms
drop table t_part_auto;
-- restore data
\! @abs_bindir@/gsql -p @portstring@ -d interval_db -f @abs_bindir@/backup.sql
SET
SET
SET
SET
SET
SET
SET
SET
SET
CREATE TABLE
ALTER TABLE
--?total time: .* ms
\d t_part_auto
Table "public.t_part_auto"
Column | Type | Modifiers
----------+-----------------------------+-----------
id | integer | not null
name | character varying |
birthday | timestamp without time zone | not null
age | integer |
Interval partition by(birthday)
Number of partition: 195 (View pg_partition to check each partition range.)
select count(1) from t_part_auto;
count
-------
200
(1 row)
-- check tablespace
select spcname from pg_tablespace where oid in(select intervaltablespace[0] from pg_partition where relname = 't_part_auto' union select intervaltablespace[1] from pg_partition where relname = 't_part_auto' union select intervaltablespace[2] from pg_partition where relname = 't_part_auto') order by spcname;
spcname
---------------
interval_tsp1
interval_tsp2
interval_tsp3
(3 rows)
drop table t_part_auto;
drop tablespace interval_tsp1;
drop tablespace interval_tsp2;
drop tablespace interval_tsp3;
\c regression
drop database interval_db;

View File

@ -27,6 +27,7 @@ test: hw_partition_interval_check_syntax
test: hw_partition_interval_split
test: hw_partition_interval_merge
test: hw_partition_interval_compatibility
test: hw_partition_interval_dump_restore
# Global Partition index feature testcase
# gpi create