13
13
14
14
-- Shardman tables
15
15
16
- -- list of nodes present in the cluster
16
+ -- List of nodes present in the cluster
17
17
CREATE TABLE nodes (
18
18
id serial PRIMARY KEY ,
19
19
connection_string text UNIQUE NOT NULL ,
20
20
replication_group text NOT NULL -- group of nodes within which shard replicas are allocated
21
21
);
22
22
23
+ -- List of sharded tables
24
+ CREATE TABLE tables (
25
+ relation text PRIMARY KEY , -- table name
26
+ sharding_key text NOT NULL , -- expression by which table is sharded
27
+ partitions_count int NOT NULL , -- number of partitions
28
+ create_sql text NOT NULL -- sql to create the table
29
+ );
30
+
23
31
-- Main partitions
24
32
CREATE TABLE partitions (
25
33
part_name text PRIMARY KEY ,
@@ -41,6 +49,8 @@ CREATE FUNCTION add_node(conn_string text, repl_group text = 'all') RETURNS void
41
49
DECLARE
42
50
new_node_id int ;
43
51
node shardman .nodes ;
52
+ part shardman .partitions ;
53
+ t shardman .tables ;
44
54
pubs text = ' ' ;
45
55
subs text = ' ' ;
46
56
sync text = ' ' ;
@@ -53,6 +63,14 @@ DECLARE
53
63
new_um_opts text ;
54
64
sync_standbys text ;
55
65
shardlord_conn_string text ;
66
+ create_table text ;
67
+ create_tables text = ' ' ;
68
+ create_partitions text = ' ' ;
69
+ create_fdws text = ' ' ;
70
+ replace_parts text = ' ' ;
71
+ fdw_part_name text ;
72
+ table_attrs text ;
73
+ srv_name text ;
56
74
BEGIN
57
75
-- Insert new node in nodes table
58
76
INSERT INTO shardman .nodes (connection_string,replication_group) VALUES (conn_string, repl_group) RETURNING id INTO new_node_id;
@@ -129,6 +147,36 @@ BEGIN
129
147
PERFORM shardman .broadcast (fdws);
130
148
-- Broadcast command for creating user mapping for this servers
131
149
PERFORM shardman .broadcast (usms);
150
+
151
+ -- Create FDWs at new node for all existed partitions
152
+ FOR t IN SELECT * from shardman .tables
153
+ LOOP
154
+ create_tables := format(' %s{%s:%s}' ,
155
+ create_tables, new_node_id, t .create_sql );
156
+ create_partitions := format(' %s%s:select create_hash_partitions(%L,%L,%L);' ,
157
+ create_partitions, new_node_id, t .relation , t .sharding_key , t .partitions_count );
158
+ SELECT shardman .reconstruct_table_attrs (t .relation ) INTO table_attrs;
159
+ FOR part IN SELECT * from shardman .partitions WHERE relation= t .relation
160
+ LOOP
161
+ SELECT connection_string INTO conn_string from shardman .nodes WHERE id= part .node ;
162
+ SELECT * FROM shardman .conninfo_to_postgres_fdw_opts (conn_str) INTO server_opts, um_opts;
163
+ srv_name := format(' node_%s' , part .node );
164
+ fdw_part_name := format(' %s_fdw' , part .part_name );
165
+ create_fdws := format(' %s%s:CREATE FOREIGN TABLE %I %s SERVER %s OPTIONS (table_name %L);' ,
166
+ create_fdws, new_node_id, fdw_part_name, table_attrs, srv_name, part .part_name );
167
+ replace_parts := format(' %s%s:SELECT replace_hash_partition(%L, %L);' ,
168
+ replace_parts, new_node_id, part .part_name , fdw_part_name);
169
+ END LOOP;
170
+ END LOOP;
171
+
172
+ -- Broadcast create table commands
173
+ PERFORM shardman .broadcast (create_tables);
174
+ -- Broadcast create hash partitions command
175
+ PERFORM shardman .broadcast (create_partitions);
176
+ -- Broadcast create foreign table commands
177
+ PERFORM shardman .broadcast (create_fdws);
178
+ -- Broadcast replace hash partition commands
179
+ PERFORM shardman .broadcast (replace_parts);
132
180
END
133
181
$$ LANGUAGE plpgsql;
134
182
@@ -266,7 +314,7 @@ $$ LANGUAGE plpgsql;
266
314
-- Shard table with hash partitions. Parameters are the same as in pathman.
267
315
-- It also scatter partitions through all nodes.
268
316
-- This function expects that empty table is created at shardlord.
269
- CREATE FUNCTION create_hash_partitions (rel regclass, expr text , partitions_count int )
317
+ CREATE FUNCTION create_hash_partitions (rel regclass, expr text , part_count int )
270
318
RETURNS void AS $$
271
319
DECLARE
272
320
create_table text ;
@@ -291,6 +339,8 @@ BEGIN
291
339
END IF;
292
340
SELECT shardman .gen_create_table_sql (rel_name) INTO create_table;
293
341
342
+ INSERT INTO shardman .tables (relation,sharding_key,partitions_count,create_sql) values (rel_name,expr,part_count,create_table);
343
+
294
344
-- Create parent table and partitions at all nodes
295
345
FOR node IN SELECT * FROM shardman .nodes
296
346
LOOP
@@ -299,7 +349,7 @@ BEGIN
299
349
create_tables, node .id , create_table);
300
350
-- Create partitions using pathman at all nodes
301
351
create_partitions := format(' %s%s:select create_hash_partitions(%L,%L,%L);' ,
302
- create_partitions, node .id , rel_name, expr, partitions_count );
352
+ create_partitions, node .id , rel_name, expr, part_count );
303
353
END LOOP;
304
354
305
355
-- Broadcast create table commands
@@ -314,7 +364,7 @@ BEGIN
314
364
-- Reconstruct table attributes from parent table
315
365
SELECT shardman .reconstruct_table_attrs (rel_name) INTO table_attrs;
316
366
317
- FOR i IN 0 ..partitions_count - 1
367
+ FOR i IN 0 ..part_count - 1
318
368
LOOP
319
369
-- Choose location of new partition
320
370
node_id := node_ids[1 + (i % n_nodes)]; -- round robin
@@ -390,6 +440,25 @@ BEGIN
390
440
END
391
441
$$ LANGUAGE plpgsql;
392
442
443
+ -- Remove table from all nodes. All table partitions are removed.
444
+ CREATE FUNCTION rm_table (rel regclass)
445
+ RETURNS void AS $$
446
+ DECLARE
447
+ rel_name text = rel::text ;
448
+ node shardman .nodes ;
449
+ drops text = ' ' ;
450
+ BEGIN
451
+ -- Drop table at all nodes
452
+ FOR node IN SELECT * FROM shardman .nodes
453
+ LOOP
454
+ drops := format(' %s%s:DROP TABLE %I CASCADE;' ,
455
+ drops, node .id , rel_name);
456
+ END LOOP;
457
+
458
+ -- Broadcast drop table commands
459
+ PERFORM shardman .broadcast (drops);
460
+ END
461
+ $$ LANGUAGE plpgsql;
393
462
394
463
-- Utility functions
395
464
0 commit comments