pg_partitioner 0.4.3 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 45af2ccf7905618261ce0c46ad347356e2cb46144d0298c379777c55de3d4ec4
4
- data.tar.gz: 21b9ee9fcd048f40c82ac119e77ca2e26e5f549f51ef9e1754017d0720402b64
3
+ metadata.gz: c2fde7de994fd9c1895b12d6347fce42e8fa84a622ad917ac73ed90d249daa27
4
+ data.tar.gz: '08bf1490d4a4462890291353eaadeec9a88cf101e54ccb982af8633c3eeab868'
5
5
  SHA512:
6
- metadata.gz: fd11ac4386b85420f1ac10ea28fa9e84980a7cd691b2fe37b553a2c9c18ab1af310ef312006379df39af76ef28059bb727d1997c71e105c506347521b10d5ee3
7
- data.tar.gz: 5d3ec6a976b909682f0c1ac46a3a8f9a1c6b5ac7ef972b6e1a07a77e2ccd6737a1957f657172d4b7ea6247849a5b5664e729ff3b11cc8230dc8edd4433f0093d
6
+ metadata.gz: 726173d02f3c6f173e784667f0543cf51d95170b9eb1446db7138707ebefa45774f727b25be8a5eb5cb3e6d3efa87f279817acc4ddd7e40772f08e735c2b30db
7
+ data.tar.gz: 571636fac008a954653af4c54b34eb43d3e1080c8dbd55a7c5aa4fe3357620849372ade89b97646c2b75daab6b5771276e9280c7c1e55ff4ff1c6e4b0b0154de
data/README.md CHANGED
@@ -61,6 +61,16 @@ rails g migration make_partitioning_of_you_table
61
61
 
62
62
  add instructions to migration:
63
63
 
64
+ ```ruby
65
+ class YouMigrationClassName
66
+ def change
67
+ YourModel.create_partitioning_by_week_trigger_sql
68
+ YourModel.create_current_week_table
69
+ YourModel.create_next_week_table
70
+ end
71
+ end
72
+ ```
73
+
64
74
  ```ruby
65
75
  class YouMigrationClassName
66
76
  def change
@@ -71,9 +81,27 @@ class YouMigrationClassName
71
81
  end
72
82
  ```
73
83
 
74
- 3) For correct work you need to create next partition every month.
84
+ ```ruby
85
+ class YouMigrationClassName
86
+ def change
87
+ YourModel.create_partitioning_by_quater_trigger_sql
88
+ YourModel.create_current_quater_table
89
+ YourModel.create_next_quater_table
90
+ end
91
+ end
92
+ ```
93
+
94
+ 3) For correct work you need to create next partition every month/quater.
75
95
  We recommend you to create a rake task and run it once a month by crontab. Code for a rake task:
76
96
 
77
97
  ```ruby
98
+ YourModel.create_next_week_table
99
+ ```
100
+ or
101
+ ```ruby
78
102
  YourModel.create_next_month_table
79
103
  ```
104
+ or
105
+ ```ruby
106
+ YourModel.create_next_quater_table
107
+ ```
@@ -0,0 +1,64 @@
1
+ module PgPartitioner
2
+ module SeparationType
3
+ module Base
4
+ def drop_table(table_name)
5
+ sql = "DROP TABLE IF EXISTS #{table_name};"
6
+ execute_sql(sql)
7
+ end
8
+
9
+ def drop_partitioning_trigger_sql
10
+ sql = "DROP TRIGGER #{table_name}_insert ON #{table_name};
11
+ DROP FUNCTION #{table_name}_insert_trigger();
12
+ DROP TRIGGER #{table_name}_after_insert ON #{table_name};
13
+ DROP FUNCTION #{table_name}_delete_trigger();"
14
+
15
+ execute_sql(sql)
16
+ end
17
+
18
+ def create_partition_indexes(partition_table_name)
19
+ custom_indexes = partition_table_indexes.presence
20
+ return unless custom_indexes
21
+
22
+ custom_indexes.each { |custom_index| create_custom_index(partition_table_name, custom_index) }
23
+ end
24
+
25
+ def create_partition_named_indexes(partition_table_name)
26
+ custom_indexes = partition_table_named_indexes.presence
27
+ return unless custom_indexes
28
+
29
+ custom_indexes.map do |name, custom_index|
30
+ index_name = "index_#{partition_table_name}_#{name}"
31
+ create_custom_named_index(partition_table_name, custom_index, index_name)
32
+ end
33
+ end
34
+
35
+ def create_partition_unique_indexes(partition_table_name)
36
+ custom_unique_indexes = partition_table_unique_indexes.presence
37
+ return unless custom_unique_indexes
38
+
39
+ custom_unique_indexes.each { |custom_index| create_custom_index(partition_table_name, custom_index, true) }
40
+ end
41
+
42
+ def create_partition_named_unique_indexes(partition_table_name)
43
+ custom_indexes = partition_table_named_unique_indexes.presence
44
+ return unless custom_indexes
45
+
46
+ custom_indexes.map do |name, custom_index|
47
+ index_name = "index_#{partition_table_name}_#{name}"
48
+ create_custom_named_index(partition_table_name, custom_index, index_name, true)
49
+ end
50
+ end
51
+
52
+ def name_of_partition_table(date = Date.today, type:)
53
+ case type
54
+ when :month
55
+ date.strftime("#{table_name}_y%Ym%m")
56
+ when :quater
57
+ "#{table_name}_y#{date.year}q#{(((date.month - 1) / 3) + 1).to_i}"
58
+ when :week
59
+ "#{table_name}_y#{date.year}w#{date.cweek}"
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
@@ -10,13 +10,15 @@ module PgPartitioner
10
10
  end
11
11
 
12
12
  def drop_old_month_table
13
- drop_month_table(Date.today.prev_month.prev_month)
13
+ table_name = name_of_partition_table(Date.today.prev_month.prev_month,
14
+ type: :quater)
15
+ drop_month_table(table_name)
14
16
  end
15
17
 
16
18
  def create_month_table(date = Date.today)
17
19
  date_start = date.at_beginning_of_month
18
20
  date_end = date.at_beginning_of_month.next_month
19
- partition_table_name = name_of_partition_table(date)
21
+ partition_table_name = name_of_partition_table(date, type: :month)
20
22
  return 'Already exists' if connection.table_exists? partition_table_name
21
23
 
22
24
  sql = "CREATE TABLE IF NOT EXISTS #{partition_table_name} (
@@ -32,18 +34,13 @@ module PgPartitioner
32
34
  create_partition_named_unique_indexes(partition_table_name)
33
35
  end
34
36
 
35
- def drop_month_table(date = Date.today)
36
- sql = "DROP TABLE IF EXISTS #{name_of_partition_table(date)};"
37
- execute_sql(sql)
38
- end
39
-
40
37
  def create_partitioning_by_month_triggers
41
38
  sql = "CREATE OR REPLACE FUNCTION #{table_name}_insert_trigger() RETURNS trigger AS
42
39
  $$
43
40
  DECLARE
44
41
  curY varchar(4);
45
42
  curM varchar(2);
46
- tbl varchar(63);
43
+ tbl varchar(121);
47
44
  BEGIN
48
45
  select cast(DATE_PART('year', new.#{parting_column}) as varchar) into curY;
49
46
  select lpad(cast(DATE_PART('month', new.#{parting_column}) as varchar), 2, '0') into curM;
@@ -78,53 +75,6 @@ module PgPartitioner
78
75
 
79
76
  execute_sql(sql)
80
77
  end
81
-
82
- def drop_partitioning_by_month_trigger_sql
83
- sql = "DROP TRIGGER #{table_name}_insert ON #{table_name};
84
- DROP FUNCTION #{table_name}_insert_trigger();
85
- DROP TRIGGER #{table_name}_after_insert ON #{table_name};
86
- DROP FUNCTION #{table_name}_delete_trigger();"
87
-
88
- execute_sql(sql)
89
- end
90
-
91
- def create_partition_indexes(partition_table_name)
92
- custom_indexes = partition_table_indexes.presence
93
- return unless custom_indexes
94
-
95
- custom_indexes.each { |custom_index| create_custom_index(partition_table_name, custom_index) }
96
- end
97
-
98
- def create_partition_named_indexes(partition_table_name)
99
- custom_indexes = partition_table_named_indexes.presence
100
- return unless custom_indexes
101
-
102
- custom_indexes.map do |name, custom_index|
103
- index_name = "index_#{partition_table_name}_#{name}"
104
- create_custom_named_index(partition_table_name, custom_index, index_name)
105
- end
106
- end
107
-
108
- def create_partition_unique_indexes(partition_table_name)
109
- custom_unique_indexes = partition_table_unique_indexes.presence
110
- return unless custom_unique_indexes
111
-
112
- custom_unique_indexes.each { |custom_index| create_custom_index(partition_table_name, custom_index, true) }
113
- end
114
-
115
- def create_partition_named_unique_indexes(partition_table_name)
116
- custom_indexes = partition_table_named_unique_indexes.presence
117
- return unless custom_indexes
118
-
119
- custom_indexes.map do |name, custom_index|
120
- index_name = "index_#{partition_table_name}_#{name}"
121
- create_custom_named_index(partition_table_name, custom_index, index_name, true)
122
- end
123
- end
124
-
125
- def name_of_partition_table(date = Date.today)
126
- date.strftime("#{table_name}_y%Ym%m")
127
- end
128
78
  end
129
79
  end
130
80
  end
@@ -0,0 +1,74 @@
1
+ module PgPartitioner
2
+ module SeparationType
3
+ module Quater
4
+ def create_current_quater_table
5
+ create_quater_table(Date.today)
6
+ end
7
+
8
+ def create_next_quater_table
9
+ create_quater_table(Date.today.next_quarter)
10
+ end
11
+
12
+ def create_quater_table(date = Date.today)
13
+ date_start = date.at_beginning_of_quarter
14
+ date_end = date.end_of_quarter.next_month.at_beginning_of_month
15
+ partition_table_name = name_of_partition_table(date, type: :quater)
16
+ return 'Already exists' if connection.table_exists? partition_table_name
17
+
18
+ sql = "CREATE TABLE IF NOT EXISTS #{partition_table_name} (
19
+ CHECK ( #{parting_column} >= DATE('#{date_start}') AND #{parting_column} < DATE('#{date_end}') )
20
+ ) INHERITS (#{table_name});"
21
+ execute_sql(sql)
22
+ sql = "ALTER TABLE #{partition_table_name} ADD PRIMARY KEY (id);"
23
+ execute_sql(sql)
24
+
25
+ create_partition_indexes(partition_table_name)
26
+ create_partition_named_indexes(partition_table_name)
27
+ create_partition_unique_indexes(partition_table_name)
28
+ create_partition_named_unique_indexes(partition_table_name)
29
+ end
30
+
31
+ def create_partitioning_by_quater_triggers
32
+ sql = "CREATE OR REPLACE FUNCTION #{table_name}_insert_trigger() RETURNS trigger AS
33
+ $$
34
+ DECLARE
35
+ curY varchar(4);
36
+ curQ varchar(1);
37
+ tbl varchar(121);
38
+ BEGIN
39
+ select cast(DATE_PART('year', new.#{parting_column}) as varchar) into curY;
40
+ select lpad(cast(DATE_PART('quarter', new.#{parting_column}) as varchar), 2, '0') into curQ;
41
+ tbl := '#{table_name}_y' || curY || 'q' || curQ;
42
+ EXECUTE format('INSERT into %I values ($1.*);', tbl) USING NEW;
43
+ return NEW;
44
+ END;
45
+ $$
46
+ LANGUAGE plpgsql;
47
+
48
+ CREATE TRIGGER #{table_name}_insert
49
+ BEFORE INSERT ON #{table_name}
50
+ FOR EACH ROW
51
+ EXECUTE PROCEDURE #{table_name}_insert_trigger();
52
+
53
+ -- Trigger function to delete from the master table after the insert
54
+ CREATE OR REPLACE FUNCTION #{table_name}_delete_trigger() RETURNS trigger
55
+ AS $$
56
+ DECLARE
57
+ r #{table_name}%rowtype;
58
+ BEGIN
59
+ DELETE FROM ONLY #{table_name} where id = new.id returning * into r;
60
+ RETURN r;
61
+ end;
62
+ $$
63
+ LANGUAGE plpgsql;
64
+
65
+ CREATE TRIGGER #{table_name}_after_insert
66
+ AFTER INSERT ON #{table_name}
67
+ FOR EACH ROW
68
+ EXECUTE PROCEDURE #{table_name}_delete_trigger();"
69
+
70
+ execute_sql(sql)
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,80 @@
1
+ module PgPartitioner
2
+ module SeparationType
3
+ module Week
4
+ def create_current_week_table
5
+ create_week_table(Date.today)
6
+ end
7
+
8
+ def create_next_week_table
9
+ create_week_table(Date.today.next_week)
10
+ end
11
+
12
+ def drop_old_week_table
13
+ table_name = name_of_partition_table(Date.today.prev_month.prev_month,
14
+ type: :week)
15
+ drop_month_table(table_name)
16
+ end
17
+
18
+ def create_week_table(date = Date.today)
19
+ date_start = date.at_beginning_of_week
20
+ date_end = date.at_beginning_of_week.next_week
21
+ partition_table_name = name_of_partition_table(date, type: :week)
22
+ return 'Already exists' if connection.table_exists? partition_table_name
23
+
24
+ sql = "CREATE TABLE IF NOT EXISTS #{partition_table_name} (
25
+ CHECK ( #{parting_column} >= DATE('#{date_start}') AND #{parting_column} < DATE('#{date_end}') )
26
+ ) INHERITS (#{table_name});"
27
+ execute_sql(sql)
28
+ sql = "ALTER TABLE #{partition_table_name} ADD PRIMARY KEY (id);"
29
+ execute_sql(sql)
30
+
31
+ create_partition_indexes(partition_table_name)
32
+ create_partition_named_indexes(partition_table_name)
33
+ create_partition_unique_indexes(partition_table_name)
34
+ create_partition_named_unique_indexes(partition_table_name)
35
+ end
36
+
37
+ def create_partitioning_by_week_triggers
38
+ sql = "CREATE OR REPLACE FUNCTION #{table_name}_insert_trigger() RETURNS trigger AS
39
+ $$
40
+ DECLARE
41
+ curY varchar(4);
42
+ curW varchar(2);
43
+ tbl varchar(121);
44
+ BEGIN
45
+ select cast(DATE_PART('year', new.#{parting_column}) as varchar) into curY;
46
+ select lpad(cast(DATE_PART('week', new.#{parting_column}) as varchar), 2, '0') into curW;
47
+ tbl := '#{table_name}_y' || curY || 'w' || curW;
48
+ EXECUTE format('INSERT into %I values ($1.*);', tbl) USING NEW;
49
+ return NEW;
50
+ END;
51
+ $$
52
+ LANGUAGE plpgsql;
53
+
54
+ CREATE TRIGGER #{table_name}_insert
55
+ BEFORE INSERT ON #{table_name}
56
+ FOR EACH ROW
57
+ EXECUTE PROCEDURE #{table_name}_insert_trigger();
58
+
59
+ -- Trigger function to delete from the master table after the insert
60
+ CREATE OR REPLACE FUNCTION #{table_name}_delete_trigger() RETURNS trigger
61
+ AS $$
62
+ DECLARE
63
+ r #{table_name}%rowtype;
64
+ BEGIN
65
+ DELETE FROM ONLY #{table_name} where id = new.id returning * into r;
66
+ RETURN r;
67
+ end;
68
+ $$
69
+ LANGUAGE plpgsql;
70
+
71
+ CREATE TRIGGER #{table_name}_after_insert
72
+ AFTER INSERT ON #{table_name}
73
+ FOR EACH ROW
74
+ EXECUTE PROCEDURE #{table_name}_delete_trigger();"
75
+
76
+ execute_sql(sql)
77
+ end
78
+ end
79
+ end
80
+ end
@@ -1,3 +1,3 @@
1
1
  module PartitionerPg
2
- VERSION = '0.4.3'
2
+ VERSION = '0.5.0'
3
3
  end
@@ -1,9 +1,17 @@
1
1
  require 'pg_partitioner/version'
2
+ require 'pg_partitioner/separation_type/base'
3
+ require 'pg_partitioner/separation_type/week'
2
4
  require 'pg_partitioner/separation_type/month'
5
+ require 'pg_partitioner/separation_type/quater'
3
6
 
4
7
  module PgPartitioner
5
8
  def self.extended(base)
6
- base.extend(PgPartitioner::SeparationType::Month)
9
+ base.extend(
10
+ PgPartitioner::SeparationType::Base,
11
+ PgPartitioner::SeparationType::Week,
12
+ PgPartitioner::SeparationType::Month,
13
+ PgPartitioner::SeparationType::Quater
14
+ )
7
15
  end
8
16
 
9
17
  # Template method
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pg_partitioner
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.3
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ovsapyan Mishel
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-04-20 00:00:00.000000000 Z
11
+ date: 2023-10-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -52,7 +52,10 @@ files:
52
52
  - bin/console
53
53
  - bin/setup
54
54
  - lib/pg_partitioner.rb
55
+ - lib/pg_partitioner/separation_type/base.rb
55
56
  - lib/pg_partitioner/separation_type/month.rb
57
+ - lib/pg_partitioner/separation_type/quater.rb
58
+ - lib/pg_partitioner/separation_type/week.rb
56
59
  - lib/pg_partitioner/version.rb
57
60
  - partitioner_pg.gemspec
58
61
  homepage: http://appodeal.com