Skip to content

Commit f4a997d

Browse files
committed
merge multiple partitions
1 parent f2f0b54 commit f4a997d

File tree

6 files changed

+101
-67
lines changed

6 files changed

+101
-67
lines changed

src/backend/commands/partition.c

Lines changed: 30 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@
99
*/
1010

1111
#include "postgres.h"
12+
#include "miscadmin.h"
13+
14+
#include "access/htup_details.h"
1215
#include "catalog/heap.h"
1316
#include "catalog/namespace.h"
1417
#include "catalog/dependency.h"
@@ -17,13 +20,13 @@
1720
#include "commands/pathman_wrapper.h"
1821
#include "commands/tablecmds.h"
1922
#include "commands/event_trigger.h"
23+
#include "commands/tablespace.h"
2024
#include "executor/spi.h"
2125
#include "nodes/value.h"
26+
#include "parser/parse_node.h"
2227
#include "utils/builtins.h"
2328
#include "utils/timestamp.h"
2429
#include "utils/lsyscache.h"
25-
#include "parser/parse_node.h"
26-
#include "access/htup_details.h"
2730

2831

2932
static void create_hash_partitions(CreateStmt *stmt, Oid relid, const char* attname);
@@ -69,6 +72,7 @@ create_hash_partitions(CreateStmt *stmt, Oid relid, const char* attname)
6972
{
7073
PartitionInfo *pinfo = (PartitionInfo *) stmt->partition_info;
7174
char **relnames = NULL;
75+
char **tablespaces = NULL;
7276

7377
if (pinfo->partitions_count > 0)
7478
{
@@ -77,11 +81,15 @@ create_hash_partitions(CreateStmt *stmt, Oid relid, const char* attname)
7781

7882
/* Convert RangeVars into cstrings */
7983
relnames = palloc(sizeof(char *) * pinfo->partitions_count);
84+
tablespaces = palloc(sizeof(char *) * pinfo->partitions_count);
8085
foreach(lc, pinfo->partitions)
8186
{
8287
RangePartitionInfo *p = (RangePartitionInfo *) lfirst(lc);
8388

8489
relnames[i] = RangeVarGetString(p->relation);
90+
tablespaces[i] = p->tablespace ?
91+
p->tablespace :
92+
get_tablespace_name(MyDatabaseTableSpace);
8593
i++;
8694
}
8795
}
@@ -90,7 +98,7 @@ create_hash_partitions(CreateStmt *stmt, Oid relid, const char* attname)
9098
attname,
9199
pinfo->partitions_count,
92100
relnames,
93-
NULL);
101+
tablespaces);
94102

95103
pfree(relnames);
96104
}
@@ -267,46 +275,47 @@ add_range_partition(Oid parent, RangePartitionInfo *rpinfo)
267275

268276

269277
void
270-
merge_range_partitions(List *partitions)
278+
merge_range_partitions(List *partitions, RangePartitionInfo *into)
271279
{
272-
Oid p1_relid,
273-
p2_relid;
280+
List *relids = NIL;
281+
ListCell *lc;
274282

275283
/*
276-
* There could be two or three partitions: two partitions are input ones
277-
* and the last is the output one. If the last is absent then partitions
278-
* are merged into the first one
284+
* There should be at least two partitions
279285
*/
280-
Assert(list_length(partitions) >= 2);
286+
if (list_length(partitions) < 2)
287+
elog(ERROR, "There must be at least two partitions to merge");
281288

282289
if (SPI_connect() != SPI_OK_CONNECT)
283290
elog(ERROR, "could not connect using SPI");
284291

285292
/* Convert rangevars to relids */
286-
p1_relid = RangeVarGetRelid(linitial(partitions), NoLock, false);
287-
p2_relid = RangeVarGetRelid(lsecond(partitions), NoLock, false);
293+
foreach(lc, partitions)
294+
{
295+
RangeVar *rv = (RangeVar *) lfirst(lc);
296+
Oid relid = RangeVarGetRelid(rv, NoLock, false);
297+
298+
relids = lappend_oid(relids, relid);
299+
}
288300

289301
/* Merge */
290-
pm_merge_range_partitions(p1_relid,
291-
p2_relid);
302+
pm_merge_range_partitions(relids);
292303

293304
/* Handle INTO clause (if there is one) */
294-
if (list_length(partitions) > 2)
305+
if (into)
295306
{
296-
/* Last object in the list is the output partition */
297-
RangePartitionInfo *output = (RangePartitionInfo *) lthird(partitions);
298-
Oid new_namespace = RangeVarGetNamespaceId(output->relation);
307+
Oid new_namespace = RangeVarGetNamespaceId(into->relation);
299308

300309
/*
301310
* When merging data pg_pathman copies data to the first partition.
302311
* Oracle does it slightly different, it creates a new partition and
303312
* merges all data there. So to simulate this behaviour we are renaming
304313
* and (if needed) moving the first partition to a new tablespace
305314
*/
306-
pm_alter_partition(p1_relid,
307-
output->relation->relname,
315+
pm_alter_partition(linitial_oid(relids),
316+
into->relation->relname,
308317
new_namespace,
309-
output->tablespace);
318+
into->tablespace);
310319
}
311320

312321
SPI_finish();

src/backend/commands/pathman_wrapper.c

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -296,7 +296,7 @@ pm_create_hash_partitions(Oid relid,
296296
FuncArgs args;
297297
bool ret;
298298

299-
InitFuncArgs(&args, 5);
299+
InitFuncArgs(&args, 6);
300300
PG_SETARG_DATUM(&args, 0, OIDOID, ObjectIdGetDatum(relid));
301301
PG_SETARG_DATUM(&args, 1, TEXTOID, CStringGetTextDatum(attname));
302302
PG_SETARG_DATUM(&args, 2, INT4OID, ObjectIdGetDatum(UInt32GetDatum(partitions_count)));
@@ -308,7 +308,13 @@ pm_create_hash_partitions(Oid relid,
308308
else
309309
PG_SETARG_NULL(&args, 4, TEXTARRAYOID);
310310

311-
ret = pathman_invoke("create_hash_partitions($1, $2, $3, $4, $5)", &args);
311+
if (tablespaces != NULL)
312+
PG_SETARG_DATUM(&args, 5, TEXTARRAYOID,
313+
construct_text_array(tablespaces, partitions_count));
314+
else
315+
PG_SETARG_NULL(&args, 5, TEXTARRAYOID);
316+
317+
ret = pathman_invoke("create_hash_partitions($1, $2, $3, $4, $5, $6)", &args);
312318
FreeFuncArgs(&args);
313319

314320
if (!ret)
@@ -441,16 +447,32 @@ pm_add_range_partition(Oid relid,
441447
* Merge partitions
442448
*/
443449
void
444-
pm_merge_range_partitions(Oid relid1, Oid relid2)
450+
pm_merge_range_partitions(List *relids)
445451
{
452+
/* Array constructor variables */
453+
Datum *datums = palloc(sizeof(Datum) * list_length(relids));
454+
int16 elemlen;
455+
bool elembyval;
456+
char elemalign;
457+
ArrayType *at;
458+
int i = 0;
459+
ListCell *lc;
460+
461+
/* Function call variables */
446462
FuncArgs args;
447463
bool ret;
448464

449-
InitFuncArgs(&args, 2);
450-
PG_SETARG_DATUM(&args, 0, OIDOID, relid1);
451-
PG_SETARG_DATUM(&args, 1, OIDOID, relid2);
465+
foreach(lc, relids)
466+
datums[i++] = ObjectIdGetDatum(lfirst_oid(lc));
467+
468+
get_typlenbyvalalign(REGCLASSOID, &elemlen, &elembyval, &elemalign);
469+
at = construct_array(datums, list_length(relids), REGCLASSOID,
470+
elemlen, elembyval, elemalign);
471+
472+
InitFuncArgs(&args, 1);
473+
PG_SETARG_DATUM(&args, 0, OIDARRAYOID, PointerGetDatum(at));
452474

453-
ret = pathman_invoke("merge_range_partitions($1, $2)", &args);
475+
ret = pathman_invoke("merge_range_partitions($1)", &args);
454476
FreeFuncArgs(&args);
455477

456478
if (!ret)

src/backend/commands/tablecmds.c

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12296,9 +12296,16 @@ RangeVarCallbackForAlterRelation(const RangeVar *rv, Oid relid, Oid oldrelid,
1229612296
*
1229712297
*/
1229812298
void
12299-
AtExecMergePartitions(Relation rel, List *partitions)
12299+
AtExecMergePartitions(Relation rel, List *rangevars)
1230012300
{
12301-
merge_range_partitions(partitions);
12301+
/*
12302+
* The first element is a tablename to merge all partitions into. The rest
12303+
* are partitions themselves
12304+
*/
12305+
RangePartitionInfo *into = linitial(rangevars);
12306+
List *partitions = list_copy_tail(rangevars, 1);
12307+
12308+
merge_range_partitions(partitions, into);
1230212309
}
1230312310

1230412311
void

src/backend/parser/gram.y

Lines changed: 31 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -547,7 +547,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
547547

548548
%type <partinfo> partitionType;
549549
%type <rangeinfo> OptRangePartitionsListElement OptHashPartitionsListElement
550-
PartitionNameTablespace OptIntoSinglePartition;
550+
PartitionNameTablespace
551551
%type <list> OptRangePartitionsList OptHashPartitionsList OptRangePartitions
552552
PartitionNameTablespaceList OptIntoPartitions
553553
%type <node> OptRangePartitionsInterval
@@ -2398,14 +2398,22 @@ alter_table_cmd:
23982398
n->partitions = list_make1($2);
23992399
$$ = (Node *) n;
24002400
}
2401-
| MERGE PARTITIONS qualified_name ',' qualified_name OptIntoSinglePartition
2401+
| MERGE PARTITIONS qualified_name_list INTO PartitionNameTablespace
24022402
{
24032403
AlterTableCmd *n = makeNode(AlterTableCmd);
24042404
n->subtype = AT_MergePartitions;
2405-
n->partitions = list_make2($3, $5);
24062405

2407-
if ($6 != NULL)
2408-
n->partitions = lappend(n->partitions, $6);
2406+
/*
2407+
* The first element in partitions list is a partition name
2408+
* to merge all partitions into
2409+
*/
2410+
if ($5 != NULL)
2411+
n->partitions = list_make1($5);
2412+
else
2413+
n->partitions = list_make1(NULL);
2414+
2415+
/* The rest elements are partitions to merge */
2416+
n->partitions = list_concat(n->partitions, $3);
24092417

24102418
$$ = (Node *) n;
24112419
}
@@ -2427,7 +2435,6 @@ alter_table_cmd:
24272435
"INTO clause must contain exactly two partitions");
24282436
}
24292437

2430-
//((RangePartitionInfo *) linitial(into_partitions))->upper_bound = $6;
24312438
n->def = $6;
24322439
n->partitions = list_concat(n->partitions, into_partitions);
24332440

@@ -2551,47 +2558,36 @@ reloption_elem:
25512558
}
25522559
;
25532560

2554-
OptIntoSinglePartition:
2555-
INTO PartitionNameTablespace
2556-
{
2557-
$$ = $2;
2558-
}
2559-
| /* EMPTY */
2560-
{
2561-
$$ = NULL;
2562-
}
2563-
;
2564-
25652561
OptIntoPartitions:
25662562
INTO '(' PartitionNameTablespaceList ')'
2567-
{
2568-
$$ = $3;
2569-
}
2563+
{
2564+
$$ = $3;
2565+
}
25702566
| /* EMPTY */
2571-
{
2572-
$$ = NIL;
2573-
}
2567+
{
2568+
$$ = NIL;
2569+
}
25742570
;
25752571

25762572
PartitionNameTablespaceList:
25772573
PartitionNameTablespace
2578-
{
2579-
$$ = list_make1($1);
2580-
}
2574+
{
2575+
$$ = list_make1($1);
2576+
}
25812577
| PartitionNameTablespaceList ',' PartitionNameTablespace
2582-
{
2583-
$$ = lappend($1, $3);
2584-
}
2578+
{
2579+
$$ = lappend($1, $3);
2580+
}
25852581
;
25862582

25872583
PartitionNameTablespace:
25882584
PARTITION qualified_name OptTableSpace
2589-
{
2590-
RangePartitionInfo *n = makeNode(RangePartitionInfo);
2591-
n->relation = $2;
2592-
n->tablespace = $3;
2593-
$$ = n;
2594-
}
2585+
{
2586+
RangePartitionInfo *n = makeNode(RangePartitionInfo);
2587+
n->relation = $2;
2588+
n->tablespace = $3;
2589+
$$ = n;
2590+
}
25952591
;
25962592

25972593

src/include/commands/partition.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
#include "nodes/parsenodes.h"
1616

1717
extern void create_partitions(CreateStmt *stmt, Oid relid);
18-
extern void merge_range_partitions(List *partitions);
18+
extern void merge_range_partitions(List *partitions, RangePartitionInfo *into);
1919
extern void add_range_partition(Oid parent, RangePartitionInfo *rpinfo);
2020
extern void split_range_partition(Oid relid, AlterTableCmd *cmd);
2121
extern void rename_partition(Oid parent, AlterTableCmd *cmd);

src/include/commands/pathman_wrapper.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ void pm_add_range_partition(Oid relid,
6464
bool lower_null,
6565
bool upper_null,
6666
const char *tablespace);
67-
void pm_merge_range_partitions(Oid relid1, Oid relid2);
67+
void pm_merge_range_partitions(List *relids);
6868
void pm_split_range_partition(Oid part_relid,
6969
Datum split_value,
7070
Oid split_value_type,

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy