tablature 0.3.1 → 1.0.0.pre
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 +4 -4
- data/.github/workflows/ci.yml +68 -0
- data/.gitignore +2 -0
- data/.rubocop.yml +1 -1
- data/.yardopts +1 -0
- data/Gemfile +12 -0
- data/README.md +45 -3
- data/lib/tablature/adapters/postgres/connection.rb +7 -0
- data/lib/tablature/adapters/postgres/errors.rb +19 -2
- data/lib/tablature/adapters/postgres/handlers/base.rb +4 -0
- data/lib/tablature/adapters/postgres/handlers/list.rb +57 -3
- data/lib/tablature/adapters/postgres/handlers/range.rb +62 -3
- data/lib/tablature/adapters/postgres/partitioned_tables.rb +10 -9
- data/lib/tablature/adapters/postgres.rb +63 -3
- data/lib/tablature/command_recorder.rb +93 -0
- data/lib/tablature/model.rb +6 -4
- data/lib/tablature/partition.rb +23 -0
- data/lib/tablature/partitioned_table.rb +26 -7
- data/lib/tablature/schema_dumper.rb +1 -1
- data/lib/tablature/statements.rb +67 -11
- data/lib/tablature/version.rb +1 -1
- data/lib/tablature.rb +1 -0
- data/tablature.gemspec +5 -3
- metadata +17 -17
- data/.circleci/config.yml +0 -81
- data/Gemfile.lock +0 -106
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8db9f3d3c82e1667d5931739f53bdc0c218f01281c56e3e1cd2541b51264ae4f
|
4
|
+
data.tar.gz: 45fa5efd4a15199e22d5d15b8d0f84114de3ed634121171bb561ff206c5bcc28
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d30f66c7398da2249edc10d3b4a5d2239aa017647f78c266fb07708abc943ee9d79f950d57e93a508c1d4211a408de17d7f97c96b092e9237a8962abdcfba58d
|
7
|
+
data.tar.gz: db95e1b650a5337be05a61986ae99ed4adb829d9dd2d98642b34907bdd71416da8dbfe1f8ec66bdc9caa2ec0e0b178b433ec39afa625928afe6d1708c4912558
|
@@ -0,0 +1,68 @@
|
|
1
|
+
name: CI
|
2
|
+
|
3
|
+
on:
|
4
|
+
push:
|
5
|
+
branches: master
|
6
|
+
pull_request:
|
7
|
+
branches: "*"
|
8
|
+
|
9
|
+
jobs:
|
10
|
+
build:
|
11
|
+
name: Ruby ${{ matrix.ruby }}, Rails ${{ matrix.rails }}, Postgres ${{ matrix.postgres }}
|
12
|
+
|
13
|
+
strategy:
|
14
|
+
fail-fast: false
|
15
|
+
matrix:
|
16
|
+
ruby: ["2.5", "2.7"]
|
17
|
+
rails: ["5.2", "6.0", "master"]
|
18
|
+
postgres: ["10.12", "11.7", "12.2"]
|
19
|
+
include:
|
20
|
+
- postgres: "10.12"
|
21
|
+
rspec_tag: --tag ~postgres_11
|
22
|
+
- rails: "master"
|
23
|
+
continue-on-error: true
|
24
|
+
|
25
|
+
runs-on: ubuntu-latest
|
26
|
+
|
27
|
+
services:
|
28
|
+
postgres:
|
29
|
+
image: postgres:${{ matrix.postgres }}-alpine
|
30
|
+
env:
|
31
|
+
POSTGRES_PASSWORD: postgres
|
32
|
+
ports:
|
33
|
+
- 5432:5432
|
34
|
+
options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5
|
35
|
+
|
36
|
+
env:
|
37
|
+
RAILS_VERSION: ${{ matrix.rails }}
|
38
|
+
POSTGRES_USER: "postgres"
|
39
|
+
POSTGRES_PASSWORD: "postgres"
|
40
|
+
CI: "true"
|
41
|
+
|
42
|
+
steps:
|
43
|
+
- name: Checkout
|
44
|
+
uses: actions/checkout@v2
|
45
|
+
|
46
|
+
- name: Install dependent libraries
|
47
|
+
run: sudo apt-get install libpq-dev
|
48
|
+
|
49
|
+
- name: Install Ruby ${{ matrix.ruby }}
|
50
|
+
uses: ruby/setup-ruby@v1.31.0
|
51
|
+
with:
|
52
|
+
ruby-version: ${{ matrix.ruby }}
|
53
|
+
|
54
|
+
- name: Generate lockfile
|
55
|
+
run: bundle lock
|
56
|
+
|
57
|
+
- name: Cache dependencies
|
58
|
+
uses: actions/cache@v1
|
59
|
+
with:
|
60
|
+
path: vendor/bundle
|
61
|
+
key: bundle-${{ hashFiles('Gemfile.lock') }}
|
62
|
+
|
63
|
+
- name: Set up Tablature
|
64
|
+
run: bin/setup
|
65
|
+
|
66
|
+
- name: Run tests
|
67
|
+
run: bundle exec rspec ${{ matrix.rspec_tag }}
|
68
|
+
continue-on-error: ${{ matrix.continue-on-error }}
|
data/.gitignore
CHANGED
data/.rubocop.yml
CHANGED
data/.yardopts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
-m markdown
|
data/Gemfile
CHANGED
@@ -1,3 +1,15 @@
|
|
1
|
+
source "https://rubygems.org"
|
1
2
|
gemspec
|
2
3
|
|
3
4
|
gem 'pry'
|
5
|
+
gem 'rubocop'
|
6
|
+
|
7
|
+
rails_version = ENV.fetch("RAILS_VERSION", "6.0")
|
8
|
+
|
9
|
+
if rails_version == "master"
|
10
|
+
rails_constraint = { github: "rails/rails" }
|
11
|
+
else
|
12
|
+
rails_constraint = "~> #{rails_version}.0"
|
13
|
+
end
|
14
|
+
|
15
|
+
gem "rails", rails_constraint
|
data/README.md
CHANGED
@@ -7,7 +7,7 @@ It ships with Postgres support and can easily supports other databases through a
|
|
7
7
|
|
8
8
|
##### Requirements
|
9
9
|
|
10
|
-
Tablature requires Rails 5+ and Postgres 10+.
|
10
|
+
Tablature requires Ruby 2.5+, Rails 5+ and Postgres 10+.
|
11
11
|
|
12
12
|
##### Installation
|
13
13
|
|
@@ -67,7 +67,6 @@ end
|
|
67
67
|
|
68
68
|
### Having a partition back a model
|
69
69
|
|
70
|
-
|
71
70
|
In your migration:
|
72
71
|
```ruby
|
73
72
|
# db/migrate/create_events.rb
|
@@ -93,7 +92,7 @@ end
|
|
93
92
|
|
94
93
|
In your model, calling one of `range_partition` or `list_partition` to inject
|
95
94
|
methods:
|
96
|
-
```
|
95
|
+
```ruby
|
97
96
|
# app/models/event.rb
|
98
97
|
class Event < ApplicationRecord
|
99
98
|
range_partition
|
@@ -118,6 +117,49 @@ You can also create new partitions directly from the model :
|
|
118
117
|
# => ["events_y2018m12", "events_y2019m01", "events_y2019m02"]
|
119
118
|
```
|
120
119
|
|
120
|
+
### Partitioning an existing table
|
121
|
+
Start by renaming your table and create the partition table:
|
122
|
+
```ruby
|
123
|
+
class PartitionEvents < ActiveRecord::Migration
|
124
|
+
def change
|
125
|
+
# Get the bounds of the events.
|
126
|
+
min_month = Event.minimum(:timestamp).beginning_of_month.to_date
|
127
|
+
max_month = Event.maximum(:timestamp).beginning_of_month.to_date
|
128
|
+
|
129
|
+
# Create the partition bounds based on the existing data. In this example,
|
130
|
+
# we generate an array with the ranges.
|
131
|
+
months = min_month.upto(max_month).uniq(&:beginning_of_month)
|
132
|
+
|
133
|
+
# Rename the existing table.
|
134
|
+
rename_table :events, :old_events
|
135
|
+
|
136
|
+
# Create the partitioned table.
|
137
|
+
create_range_partition :events, partition_key: -> { '(timestamp::DATE)' } do |t|
|
138
|
+
t.string :event_type, null: false
|
139
|
+
t.integer :value, null: false
|
140
|
+
t.datetime :timestamp, null: false
|
141
|
+
t.timestamps
|
142
|
+
end
|
143
|
+
|
144
|
+
# Create the partitions based on the bounds generated before:
|
145
|
+
months.each do |month|
|
146
|
+
# Creates a name like "events_y2018m12"
|
147
|
+
partition_name = "events_y#{month.year}m#{month.month}"
|
148
|
+
|
149
|
+
create_range_partition_of :events,
|
150
|
+
name: partition_name, range_start: month, range_end: month.next_month
|
151
|
+
end
|
152
|
+
|
153
|
+
# Finally, add the rows from the old table to the new partitioned table.
|
154
|
+
# This might take some time depending on the size of your old table.
|
155
|
+
execute(<<~SQL)
|
156
|
+
INSERT INTO events
|
157
|
+
SELECT * FROM old_events
|
158
|
+
SQL
|
159
|
+
end
|
160
|
+
end
|
161
|
+
```
|
162
|
+
|
121
163
|
## Development
|
122
164
|
|
123
165
|
After checking out the repo, run `bin/setup` to install dependencies.
|
@@ -31,6 +31,13 @@ module Tablature
|
|
31
31
|
postgresql_version >= 110_000
|
32
32
|
end
|
33
33
|
|
34
|
+
# True if the connection supports default partitions.
|
35
|
+
#
|
36
|
+
# @return [Boolean]
|
37
|
+
def supports_default_partitions?
|
38
|
+
postgresql_version >= 110_000
|
39
|
+
end
|
40
|
+
|
34
41
|
# An integer representing the version of Postgres we're connected to.
|
35
42
|
#
|
36
43
|
# +postgresql_version+ is public in Rails 5, but protected in earlier
|
@@ -1,6 +1,23 @@
|
|
1
1
|
module Tablature
|
2
2
|
module Adapters
|
3
3
|
class Postgres
|
4
|
+
# Raised when a setting a partition as default on a database
|
5
|
+
# version that does not support default partitions.
|
6
|
+
#
|
7
|
+
# Default partitions are supported on Postgres 11 or newer.
|
8
|
+
class DefaultPartitionNotSupportedError < StandardError
|
9
|
+
def initialize
|
10
|
+
super('Default partitions require Postgres 11 or newer')
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
# Raised when trying to attach or detach a partition without supplying a name.
|
15
|
+
class MissingPartitionName < StandardError
|
16
|
+
def initialize
|
17
|
+
super('Missing partition name')
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
4
21
|
# Raised when a list partition operation is attempted on a database
|
5
22
|
# version that does not support list partitions.
|
6
23
|
#
|
@@ -15,7 +32,7 @@ module Tablature
|
|
15
32
|
# key.
|
16
33
|
class MissingListPartitionValuesError < StandardError
|
17
34
|
def initialize
|
18
|
-
super('Missing values for
|
35
|
+
super('Missing values for list partition')
|
19
36
|
end
|
20
37
|
end
|
21
38
|
|
@@ -33,7 +50,7 @@ module Tablature
|
|
33
50
|
# key.
|
34
51
|
class MissingRangePartitionBoundsError < StandardError
|
35
52
|
def initialize
|
36
|
-
super('Missing bounds for
|
53
|
+
super('Missing bounds for range partition')
|
37
54
|
end
|
38
55
|
end
|
39
56
|
end
|
@@ -13,6 +13,10 @@ module Tablature
|
|
13
13
|
|
14
14
|
protected
|
15
15
|
|
16
|
+
def raise_unless_default_partition_supported
|
17
|
+
raise DefaultPartitionNotSupportedError unless connection.supports_default_partitions?
|
18
|
+
end
|
19
|
+
|
16
20
|
def create_partition(table_name, id_options, table_options, &block)
|
17
21
|
create_table(table_name, table_options) do |td|
|
18
22
|
# TODO: Handle the id things here (depending on the postgres version)
|
@@ -29,15 +29,50 @@ module Tablature
|
|
29
29
|
|
30
30
|
def create_list_partition_of(parent_table, options)
|
31
31
|
values = options.fetch(:values, [])
|
32
|
-
|
32
|
+
as_default = options.fetch(:default, false)
|
33
|
+
|
34
|
+
raise_unless_default_partition_supported if as_default
|
35
|
+
raise MissingListPartitionValuesError if values.blank? && !as_default
|
33
36
|
|
34
37
|
name = options.fetch(:name, partition_name(parent_table, values))
|
35
38
|
# TODO: Call `create_table` here instead of running the query.
|
36
39
|
# TODO: Pass the options to `create_table` to allow further configuration of the table,
|
37
40
|
# e.g. sub-partitioning the table.
|
38
|
-
|
41
|
+
|
42
|
+
query = <<~SQL
|
39
43
|
CREATE TABLE #{quote_table_name(name)} PARTITION OF #{quote_table_name(parent_table)}
|
40
|
-
|
44
|
+
SQL
|
45
|
+
|
46
|
+
query += if as_default
|
47
|
+
'DEFAULT'
|
48
|
+
else
|
49
|
+
"FOR VALUES IN (#{quote_collection(values)})"
|
50
|
+
end
|
51
|
+
|
52
|
+
execute(query)
|
53
|
+
end
|
54
|
+
|
55
|
+
def attach_to_list_partition(parent_table, options)
|
56
|
+
values = options.fetch(:values, [])
|
57
|
+
as_default = options.fetch(:default, false)
|
58
|
+
|
59
|
+
raise_unless_default_partition_supported if as_default
|
60
|
+
raise MissingListPartitionValuesError if values.blank? && !as_default
|
61
|
+
|
62
|
+
name = options.fetch(:name) { raise MissingPartitionName }
|
63
|
+
|
64
|
+
if as_default
|
65
|
+
attach_default_partition(parent_table, name)
|
66
|
+
else
|
67
|
+
attach_partition(parent_table, name, values)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def detach_from_list_partition(parent_table, options)
|
72
|
+
name = options.fetch(:name) { raise MissingPartitionName }
|
73
|
+
query = <<~SQL.strip
|
74
|
+
ALTER TABLE #{quote_table_name(parent_table)}
|
75
|
+
DETACH PARTITION #{quote_table_name(name)}
|
41
76
|
SQL
|
42
77
|
|
43
78
|
execute(query)
|
@@ -59,6 +94,25 @@ module Tablature
|
|
59
94
|
key = values.inspect
|
60
95
|
"#{parent_table}_#{Digest::MD5.hexdigest(key)[0..6]}"
|
61
96
|
end
|
97
|
+
|
98
|
+
def attach_default_partition(parent_table, partition_name)
|
99
|
+
query = <<~SQL.strip
|
100
|
+
ALTER TABLE #{quote_table_name(parent_table)}
|
101
|
+
ATTACH PARTITION #{quote_table_name(partition_name)} DEFAULT
|
102
|
+
SQL
|
103
|
+
|
104
|
+
execute(query)
|
105
|
+
end
|
106
|
+
|
107
|
+
def attach_partition(parent_table, partition_name, values)
|
108
|
+
query = <<~SQL.strip
|
109
|
+
ALTER TABLE #{quote_table_name(parent_table)}
|
110
|
+
ATTACH PARTITION #{quote_table_name(partition_name)}
|
111
|
+
FOR VALUES IN (#{quote_collection(values)})
|
112
|
+
SQL
|
113
|
+
|
114
|
+
execute(query)
|
115
|
+
end
|
62
116
|
end
|
63
117
|
end
|
64
118
|
end
|
@@ -31,16 +31,56 @@ module Tablature
|
|
31
31
|
def create_range_partition_of(parent_table, options)
|
32
32
|
range_start = options.fetch(:range_start, nil)
|
33
33
|
range_end = options.fetch(:range_end, nil)
|
34
|
+
as_default = options.fetch(:default, false)
|
34
35
|
|
35
|
-
|
36
|
+
raise_unless_default_partition_supported if as_default
|
37
|
+
if (range_start.nil? || range_end.nil?) && !as_default
|
38
|
+
raise MissingRangePartitionBoundsError
|
39
|
+
end
|
36
40
|
|
37
41
|
name = options.fetch(:name, partition_name(parent_table, range_start, range_end))
|
38
42
|
# TODO: Call `create_table` here instead of running the query.
|
39
43
|
# TODO: Pass the options to `create_table` to allow further configuration of the table,
|
40
44
|
# e.g. sub-partitioning the table.
|
41
|
-
|
45
|
+
|
46
|
+
query = <<~SQL
|
42
47
|
CREATE TABLE #{quote_table_name(name)} PARTITION OF #{quote_table_name(parent_table)}
|
43
|
-
|
48
|
+
SQL
|
49
|
+
|
50
|
+
query += if as_default
|
51
|
+
'DEFAULT'
|
52
|
+
else
|
53
|
+
"FOR VALUES FROM (#{quote(range_start)}) TO (#{quote(range_end)})"
|
54
|
+
end
|
55
|
+
|
56
|
+
execute(query)
|
57
|
+
end
|
58
|
+
|
59
|
+
def attach_to_range_partition(parent_table, options)
|
60
|
+
range_start = options.fetch(:range_start, nil)
|
61
|
+
range_end = options.fetch(:range_end, nil)
|
62
|
+
as_default = options.fetch(:default, false)
|
63
|
+
|
64
|
+
raise_unless_default_partition_supported if as_default
|
65
|
+
if (range_start.nil? || range_end.nil?) && !as_default
|
66
|
+
raise MissingRangePartitionBoundsError
|
67
|
+
end
|
68
|
+
|
69
|
+
name = options.fetch(:name) { raise MissingPartitionName }
|
70
|
+
|
71
|
+
if as_default
|
72
|
+
attach_default_partition(parent_table, name)
|
73
|
+
else
|
74
|
+
attach_partition(parent_table, name, range_start, range_end)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def detach_from_range_partition(parent_table, options)
|
79
|
+
name = options.fetch(:name) { raise MissingPartitionName }
|
80
|
+
|
81
|
+
query = <<~SQL.strip
|
82
|
+
ALTER TABLE #{quote_table_name(parent_table)}
|
83
|
+
DETACH PARTITION #{quote_table_name(name)}
|
44
84
|
SQL
|
45
85
|
|
46
86
|
execute(query)
|
@@ -61,6 +101,25 @@ module Tablature
|
|
61
101
|
key = [range_start, range_end].join(', ')
|
62
102
|
"#{parent_table}_#{Digest::MD5.hexdigest(key)[0..6]}"
|
63
103
|
end
|
104
|
+
|
105
|
+
def attach_default_partition(parent_table, partition_name)
|
106
|
+
query = <<~SQL.strip
|
107
|
+
ALTER TABLE #{quote_table_name(parent_table)}
|
108
|
+
ATTACH PARTITION #{quote_table_name(partition_name)} DEFAULT
|
109
|
+
SQL
|
110
|
+
|
111
|
+
execute(query)
|
112
|
+
end
|
113
|
+
|
114
|
+
def attach_partition(parent_table, partition_name, range_start, range_end)
|
115
|
+
query = <<~SQL.strip
|
116
|
+
ALTER TABLE #{quote_table_name(parent_table)}
|
117
|
+
ATTACH PARTITION #{quote_table_name(partition_name)}
|
118
|
+
FOR VALUES FROM (#{quote(range_start)}) TO (#{quote(range_end)})
|
119
|
+
SQL
|
120
|
+
|
121
|
+
execute(query)
|
122
|
+
end
|
64
123
|
end
|
65
124
|
end
|
66
125
|
end
|
@@ -23,9 +23,11 @@ module Tablature
|
|
23
23
|
connection.execute(<<-SQL)
|
24
24
|
SELECT
|
25
25
|
c.oid,
|
26
|
+
i.inhrelid,
|
26
27
|
c.relname AS table_name,
|
27
|
-
p.partstrat AS
|
28
|
+
p.partstrat AS strategy,
|
28
29
|
(i.inhrelid::REGCLASS)::TEXT AS partition_name,
|
30
|
+
#{connection.supports_default_partitions? ? 'i.inhrelid = p.partdefid AS is_default_partition,' : ''}
|
29
31
|
pg_get_partkeydef(c.oid) AS partition_key_definition
|
30
32
|
FROM pg_class c
|
31
33
|
INNER JOIN pg_partitioned_table p ON c.oid = p.partrelid
|
@@ -39,26 +41,25 @@ module Tablature
|
|
39
41
|
SQL
|
40
42
|
end
|
41
43
|
|
42
|
-
|
44
|
+
STRATEGY_MAP = {
|
43
45
|
'l' => :list,
|
44
46
|
'r' => :range,
|
45
47
|
'h' => :hash
|
46
48
|
}.freeze
|
47
|
-
private_constant :
|
49
|
+
private_constant :STRATEGY_MAP
|
48
50
|
|
49
51
|
def to_tablature_table(table_name, rows)
|
50
52
|
result = rows.first
|
51
|
-
|
52
|
-
partitions = rows.map { |row| row['partition_name'] }.compact.map(&method(:unquote))
|
53
|
+
partitioning_strategy = STRATEGY_MAP.fetch(result['strategy'])
|
53
54
|
# This is very fragile code. This makes the assumption that:
|
54
55
|
# - Postgres will always have a function `pg_get_partkeydef` that returns the partition
|
55
|
-
#
|
56
|
-
# - Postgres will never have a partition
|
56
|
+
# strategy with the partition key
|
57
|
+
# - Postgres will never have a partition strategy with two words in its name.
|
57
58
|
_, partition_key = result['partition_key_definition'].split(' ', 2)
|
58
59
|
|
59
60
|
Tablature::PartitionedTable.new(
|
60
|
-
name: table_name,
|
61
|
-
partitions:
|
61
|
+
name: table_name, partitioning_strategy: partitioning_strategy,
|
62
|
+
partitions: rows, partition_key: partition_key
|
62
63
|
)
|
63
64
|
end
|
64
65
|
|
@@ -68,14 +68,44 @@ module Tablature
|
|
68
68
|
# @option options [String, Symbol] :values The values appearing in the partition.
|
69
69
|
# @option options [String, Symbol] :name The name of the partition. If it is not given, this
|
70
70
|
# will be randomly generated.
|
71
|
+
# @option options [Boolean] :default Whether the partition is the default partition or not.
|
71
72
|
#
|
72
73
|
# @example
|
73
74
|
# # With a table :events partitioned using the list method on the partition key `date`:
|
74
75
|
# create_list_partition_of :events, name: "events_2018-W49", values: [
|
75
|
-
# "2018-12-03", "2018-12-04", "2018-12-05", "2018-12-06", "2018-12-07", "2018-12-08",
|
76
|
+
# "2018-12-03", "2018-12-04", "2018-12-05", "2018-12-06", "2018-12-07", "2018-12-08",
|
77
|
+
# "2018-12-09"
|
76
78
|
# ]
|
77
79
|
delegate :create_list_partition_of, to: :list_handler
|
78
80
|
|
81
|
+
# @!method attach_to_list_partition(parent_table_name, options)
|
82
|
+
# Attaches a partition to a parent by specifying the key values appearing in the partition.
|
83
|
+
#
|
84
|
+
# @param parent_table_name [String, Symbol] The name of the parent table.
|
85
|
+
# @param [Hash] options The options to attach the partition.
|
86
|
+
# @option options [String, Symbol] :name The name of the partition.
|
87
|
+
# @option options [String, Symbol] :values The values appearing in the partition.
|
88
|
+
#
|
89
|
+
# @example
|
90
|
+
# # With a table :events partitioned using the list method on the partition key `date`:
|
91
|
+
# attach_to_list_partition :events, name: "events_2018-W49", values: [
|
92
|
+
# "2018-12-03", "2018-12-04", "2018-12-05", "2018-12-06", "2018-12-07", "2018-12-08",
|
93
|
+
# "2018-12-09"
|
94
|
+
# ]
|
95
|
+
delegate :attach_to_list_partition, to: :list_handler
|
96
|
+
|
97
|
+
# @!method detach_from_list_partition(parent_table_name, options)
|
98
|
+
# Detaches a partition from a parent.
|
99
|
+
#
|
100
|
+
# @param parent_table_name [String, Symbol] The name of the parent table.
|
101
|
+
# @param [Hash] options The options to create the partition.
|
102
|
+
# @option options [String, Symbol] :name The name of the partition.
|
103
|
+
#
|
104
|
+
# @example
|
105
|
+
# # With a table :events partitioned using the list method on the partition key `date`:
|
106
|
+
# detach_from_list_partition :events, name: "events_2018-W49"
|
107
|
+
delegate :detach_from_list_partition, to: :list_handler
|
108
|
+
|
79
109
|
# @!method create_range_partition(table_name, options, &block)
|
80
110
|
# Creates a partitioned table using the range partition method.
|
81
111
|
#
|
@@ -102,12 +132,13 @@ module Tablature
|
|
102
132
|
#
|
103
133
|
# @param parent_table_name [String, Symbol] The name of the parent table.
|
104
134
|
# @param [Hash] options The options to create the partition.
|
135
|
+
# @option options [String, Symbol] :name The name of the partition. If it is not given, this
|
136
|
+
# will be randomly generated.
|
105
137
|
# @option options [String, Symbol] :range_start The start of the range of values appearing in
|
106
138
|
# the partition.
|
107
139
|
# @option options [String, Symbol] :range_end The end of the range of values appearing in
|
108
140
|
# the partition.
|
109
|
-
# @option options [
|
110
|
-
# will be randomly generated.
|
141
|
+
# @option options [Boolean] :default Whether the partition is the default partition or not.
|
111
142
|
#
|
112
143
|
# @example
|
113
144
|
# # With a table :events partitioned using the range method on the partition key `date`:
|
@@ -115,6 +146,35 @@ module Tablature
|
|
115
146
|
# range_end: '2018-12-10'
|
116
147
|
delegate :create_range_partition_of, to: :range_handler
|
117
148
|
|
149
|
+
# @!method attach_to_range_partition(parent_table_name, options)
|
150
|
+
# Attaches a partition to a parent by specifying the key values appearing in the partition.
|
151
|
+
#
|
152
|
+
# @param parent_table_name [String, Symbol] The name of the parent table.
|
153
|
+
# @param [Hash] options The options to create the partition.
|
154
|
+
# @option options [String, Symbol] :name The name of the partition.
|
155
|
+
# @option options [String, Symbol] :range_start The start of the range of values appearing in
|
156
|
+
# the partition.
|
157
|
+
# @option options [String, Symbol] :range_end The end of the range of values appearing in
|
158
|
+
# the partition.
|
159
|
+
# @option options [Boolean] :default Whether the partition is the default partition or not.
|
160
|
+
#
|
161
|
+
# @example
|
162
|
+
# # With a table :events partitioned using the range method on the partition key `date`:
|
163
|
+
# attach_to_range_partition :events, name: "events_2018-W49", range_start: '2018-12-03',
|
164
|
+
# range_end: '2018-12-10'
|
165
|
+
delegate :attach_to_range_partition, to: :range_handler
|
166
|
+
|
167
|
+
# @!method detach_from_range_partition(parent_table_name, options)
|
168
|
+
# Detaches a partition from a parent.
|
169
|
+
#
|
170
|
+
# @param parent_table_name [String, Symbol] The name of the parent table.
|
171
|
+
# @param [Hash] options The options to detach the partition.
|
172
|
+
# @option options [String, Symbol] :name The name of the partition.
|
173
|
+
#
|
174
|
+
# @example
|
175
|
+
# detach_from_range_partition :events, name: "events_2018-W49"
|
176
|
+
delegate :detach_from_range_partition, to: :range_handler
|
177
|
+
|
118
178
|
# Returns an array of partitioned tables in the database.
|
119
179
|
#
|
120
180
|
# This collection of tables is used by the [Tablature::SchemaDumper] to populate the schema.rb
|
@@ -1,4 +1,97 @@
|
|
1
1
|
module Tablature
|
2
|
+
# @api private
|
2
3
|
module CommandRecorder
|
4
|
+
def create_list_partition(*args)
|
5
|
+
record(:create_list_partition, args)
|
6
|
+
end
|
7
|
+
|
8
|
+
def create_list_partition_of(*args)
|
9
|
+
record(:create_list_partition_of, args)
|
10
|
+
end
|
11
|
+
|
12
|
+
def attach_to_list_partition(*args)
|
13
|
+
record(:attach_to_list_partition, args)
|
14
|
+
end
|
15
|
+
|
16
|
+
def detach_from_list_partition(*args)
|
17
|
+
record(:detach_from_list_partition, args)
|
18
|
+
end
|
19
|
+
|
20
|
+
def create_range_partition(*args)
|
21
|
+
record(:create_range_partition, args)
|
22
|
+
end
|
23
|
+
|
24
|
+
def create_range_partition_of(*args)
|
25
|
+
record(:create_range_partition_of, args)
|
26
|
+
end
|
27
|
+
|
28
|
+
def attach_to_range_partition(*args)
|
29
|
+
record(:attach_to_range_partition, args)
|
30
|
+
end
|
31
|
+
|
32
|
+
def detach_from_range_partition(*args)
|
33
|
+
record(:detach_from_range_partition, args)
|
34
|
+
end
|
35
|
+
|
36
|
+
def invert_create_partition(args)
|
37
|
+
[:drop_table, [args.first]]
|
38
|
+
end
|
39
|
+
|
40
|
+
alias :invert_create_list_partition :invert_create_partition
|
41
|
+
alias :invert_create_range_partition :invert_create_partition
|
42
|
+
|
43
|
+
def invert_create_partition_of(args)
|
44
|
+
_parent_table_name, options = args
|
45
|
+
partition_name = options[:name]
|
46
|
+
|
47
|
+
[:drop_table, [partition_name]]
|
48
|
+
end
|
49
|
+
|
50
|
+
alias :invert_create_list_partition_of :invert_create_partition_of
|
51
|
+
alias :invert_create_range_partition_of :invert_create_partition_of
|
52
|
+
|
53
|
+
def invert_attach_to_range_partition(args)
|
54
|
+
[:detach_from_range_partition, args]
|
55
|
+
end
|
56
|
+
|
57
|
+
def invert_detach_from_range_partition(args)
|
58
|
+
parent_table_name, options = args
|
59
|
+
options ||= {}
|
60
|
+
_partition_name = options[:name]
|
61
|
+
|
62
|
+
range_start = options[:range_start]
|
63
|
+
range_end = options[:range_end]
|
64
|
+
default = options[:default]
|
65
|
+
|
66
|
+
if (range_start.nil? || range_end.nil?) && default.blank?
|
67
|
+
message = <<-MESSAGE
|
68
|
+
invert_detach_from_range_partition is reversible only if given bounds or the default option
|
69
|
+
MESSAGE
|
70
|
+
raise ActiveRecord::IrreversibleMigration, message
|
71
|
+
end
|
72
|
+
|
73
|
+
[:attach_to_range_partition, [parent_table_name, options]]
|
74
|
+
end
|
75
|
+
|
76
|
+
def invert_attach_to_list_partition(args)
|
77
|
+
[:detach_from_list_partition, args]
|
78
|
+
end
|
79
|
+
|
80
|
+
def invert_detach_from_list_partition(args)
|
81
|
+
partitioned_table, options = args
|
82
|
+
options ||= {}
|
83
|
+
|
84
|
+
default = options[:default]
|
85
|
+
values = options[:values] || []
|
86
|
+
|
87
|
+
if values.blank? && default.blank?
|
88
|
+
message = <<-MESSAGE
|
89
|
+
invert_detach_from_list_partition is reversible only if given the value list or the default option
|
90
|
+
MESSAGE
|
91
|
+
raise ActiveRecord::IrreversibleMigration, message
|
92
|
+
end
|
93
|
+
|
94
|
+
[:attach_to_list_partition, [partitioned_table, options]]
|
95
|
+
end
|
3
96
|
end
|
4
97
|
end
|
data/lib/tablature/model.rb
CHANGED
@@ -15,7 +15,7 @@ module Tablature
|
|
15
15
|
module ClassMethods
|
16
16
|
extend Forwardable
|
17
17
|
|
18
|
-
def_delegators :tablature_partition, :partitions, :partition_key, :
|
18
|
+
def_delegators :tablature_partition, :partitions, :partition_key, :partitioning_strategy
|
19
19
|
|
20
20
|
def partitioned?
|
21
21
|
begin
|
@@ -28,12 +28,14 @@ module Tablature
|
|
28
28
|
end
|
29
29
|
|
30
30
|
def tablature_partition
|
31
|
-
|
31
|
+
return @tablature_partition if defined?(@tablature_partition)
|
32
|
+
|
33
|
+
@tablature_partition = Tablature.database.partitioned_tables.find do |pt|
|
32
34
|
pt.name == partition_name.to_s
|
33
35
|
end
|
34
|
-
raise Tablature::MissingPartition if
|
36
|
+
raise Tablature::MissingPartition if @tablature_partition.nil?
|
35
37
|
|
36
|
-
|
38
|
+
@tablature_partition
|
37
39
|
end
|
38
40
|
|
39
41
|
def list_partition(partition_name = table_name)
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Tablature
|
2
|
+
# The in-memory representation of a partition.
|
3
|
+
#
|
4
|
+
# **This object is used internally by adapters and the schema dumper and is
|
5
|
+
# not intended to be used by application code. It is documented here for
|
6
|
+
# use by adapter gems.**
|
7
|
+
#
|
8
|
+
# @api private
|
9
|
+
class Partition
|
10
|
+
attr_reader :name
|
11
|
+
attr_reader :parent_table_name
|
12
|
+
|
13
|
+
def initialize(name:, parent_table_name:, default_partition: false)
|
14
|
+
@name = name
|
15
|
+
@parent_table_name = parent_table_name
|
16
|
+
@default_partition = default_partition
|
17
|
+
end
|
18
|
+
|
19
|
+
def default_partition?
|
20
|
+
@default_partition
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -5,35 +5,54 @@ module Tablature
|
|
5
5
|
# not intended to be used by application code. It is documented here for
|
6
6
|
# use by adapter gems.**
|
7
7
|
#
|
8
|
-
# @api
|
8
|
+
# @api private
|
9
9
|
class PartitionedTable
|
10
10
|
# The name of the partitioned table
|
11
11
|
# @return [String]
|
12
|
+
# @api private
|
12
13
|
attr_reader :name
|
13
14
|
|
14
|
-
# The partitioning
|
15
|
+
# The partitioning strategy of the table
|
15
16
|
# @return [Symbol]
|
16
|
-
|
17
|
+
# @api private
|
18
|
+
attr_reader :partitioning_strategy
|
17
19
|
|
18
20
|
# The partitions of the table.
|
19
21
|
# @return [Array]
|
22
|
+
# @api private
|
20
23
|
attr_reader :partitions
|
21
24
|
|
22
25
|
# The partition key expression.
|
23
26
|
# @return [String]
|
27
|
+
# @api private
|
24
28
|
attr_reader :partition_key
|
25
29
|
|
26
30
|
# Returns a new instance of PartitionTable.
|
27
31
|
#
|
28
32
|
# @param name [String] The name of the view.
|
29
|
-
# @param
|
33
|
+
# @param partitioning_strategy [:symbol] One of :range, :list or :hash
|
30
34
|
# @param partitions [Array] The partitions of the table.
|
31
35
|
# @param partition_key [String] The partition key expression.
|
32
|
-
|
36
|
+
# @api private
|
37
|
+
def initialize(name:, partitioning_strategy:, partitions: [], partition_key:)
|
33
38
|
@name = name
|
34
|
-
@
|
35
|
-
@partitions = partitions
|
39
|
+
@partitioning_strategy = partitioning_strategy
|
40
|
+
@partitions = partitions.map do |row|
|
41
|
+
Tablature::Partition.new(
|
42
|
+
name: row['partition_name'],
|
43
|
+
parent_table_name: row['table_name'],
|
44
|
+
default_partition: row['is_default_partition']
|
45
|
+
)
|
46
|
+
end
|
36
47
|
@partition_key = partition_key
|
37
48
|
end
|
49
|
+
|
50
|
+
# Returns the representation of the default partition if present.
|
51
|
+
#
|
52
|
+
# @return [Tablature::Partition]
|
53
|
+
# @api private
|
54
|
+
def default_partition
|
55
|
+
partitions.find(&:default_partition?)
|
56
|
+
end
|
38
57
|
end
|
39
58
|
end
|
data/lib/tablature/statements.rb
CHANGED
@@ -3,15 +3,15 @@ module Tablature
|
|
3
3
|
module Statements
|
4
4
|
# Creates a partitioned table using the list partition method.
|
5
5
|
#
|
6
|
-
# @param
|
6
|
+
# @param table_name [String, Symbol] The name of the partition.
|
7
7
|
# @param options [Hash] The options to create the partition.
|
8
8
|
# @yield [td] A TableDefinition object. This allows creating the table columns the same way
|
9
9
|
# as Rails's +create_table+ does.
|
10
10
|
# @see Tablature::Adapters::Postgres#create_list_partition
|
11
|
-
def create_list_partition(
|
11
|
+
def create_list_partition(table_name, options, &block)
|
12
12
|
raise ArgumentError, 'partition_key must be defined' if options[:partition_key].nil?
|
13
13
|
|
14
|
-
Tablature.database.create_list_partition(
|
14
|
+
Tablature.database.create_list_partition(table_name, options, &block)
|
15
15
|
end
|
16
16
|
|
17
17
|
# Creates a partition of a parent by specifying the key values appearing in the partition.
|
@@ -21,23 +21,52 @@ module Tablature
|
|
21
21
|
#
|
22
22
|
# @see Tablature::Adapters::Postgres#create_list_partition_of
|
23
23
|
def create_list_partition_of(parent_table_name, options)
|
24
|
-
|
24
|
+
if options[:values].blank? && options[:default].blank?
|
25
|
+
raise ArgumentError, 'values or default must be defined'
|
26
|
+
end
|
25
27
|
|
26
28
|
Tablature.database.create_list_partition_of(parent_table_name, options)
|
27
29
|
end
|
28
30
|
|
31
|
+
# Attaches a partition to a parent by specifying the key values appearing in the partition.
|
32
|
+
#
|
33
|
+
# @param parent_table_name [String, Symbol] The name of the parent table.
|
34
|
+
# @param [Hash] options The options to attach the partition.
|
35
|
+
#
|
36
|
+
# @see Tablature::Adapters::Postgres#attach_to_list_partition
|
37
|
+
def attach_to_list_partition(parent_table_name, options)
|
38
|
+
raise ArgumentError, 'name must be defined' if options[:name].blank?
|
39
|
+
|
40
|
+
Tablature.database.attach_to_list_partition(parent_table_name, options)
|
41
|
+
end
|
42
|
+
|
43
|
+
# Detaches a partition from a parent.
|
44
|
+
#
|
45
|
+
# @param parent_table_name [String, Symbol] The name of the parent table.
|
46
|
+
# @param [Hash] options The options to create the partition.
|
47
|
+
#
|
48
|
+
# @see Tablature::Adapters::Postgres#detach_from_list_partition
|
49
|
+
def detach_from_list_partition(parent_table_name, options)
|
50
|
+
raise ArgumentError, 'name must be defined' if options[:name].blank?
|
51
|
+
if options[:values].blank? && options[:default].blank?
|
52
|
+
raise ArgumentError, 'values or default must be defined'
|
53
|
+
end
|
54
|
+
|
55
|
+
Tablature.database.attach_to_list_partition(parent_table_name, options)
|
56
|
+
end
|
57
|
+
|
29
58
|
# Creates a partitioned table using the range partition method.
|
30
59
|
#
|
31
|
-
# @param
|
60
|
+
# @param table_name [String, Symbol] The name of the partition.
|
32
61
|
# @param options [Hash] The options to create the partition.
|
33
62
|
# @yield [td] A TableDefinition object. This allows creating the table columns the same way
|
34
63
|
# as Rails's +create_table+ does.
|
35
64
|
#
|
36
65
|
# @see Tablature::Adapters::Postgres#create_range_partition
|
37
|
-
def create_range_partition(
|
66
|
+
def create_range_partition(table_name, options, &block)
|
38
67
|
raise ArgumentError, 'partition_key must be defined' if options[:partition_key].nil?
|
39
68
|
|
40
|
-
Tablature.database.create_range_partition(
|
69
|
+
Tablature.database.create_range_partition(table_name, options, &block)
|
41
70
|
end
|
42
71
|
|
43
72
|
# Creates a partition of a parent by specifying the key values appearing in the partition.
|
@@ -46,12 +75,39 @@ module Tablature
|
|
46
75
|
# @param [Hash] options The options to create the partition.
|
47
76
|
#
|
48
77
|
# @see Tablature::Adapters::Postgres#create_range_partition_of
|
49
|
-
def create_range_partition_of(
|
50
|
-
if options[:range_start].nil? || options[:range_end].nil?
|
51
|
-
raise ArgumentError, 'range_start and range_end must be defined'
|
78
|
+
def create_range_partition_of(parent_table_name, options)
|
79
|
+
if (options[:range_start].nil? || options[:range_end].nil?) && options[:default].blank?
|
80
|
+
raise ArgumentError, 'range_start and range_end or default must be defined'
|
52
81
|
end
|
53
82
|
|
54
|
-
Tablature.database.create_range_partition_of(
|
83
|
+
Tablature.database.create_range_partition_of(parent_table_name, options)
|
84
|
+
end
|
85
|
+
|
86
|
+
# Attaches a partition to a parent by specifying the key values appearing in the partition.
|
87
|
+
#
|
88
|
+
# @param parent_table_name [String, Symbol] The name of the parent table.
|
89
|
+
# @param [Hash] options The options to create the partition.
|
90
|
+
#
|
91
|
+
# @see Tablature::Adapters::Postgres#attach_to_range_partition
|
92
|
+
def attach_to_range_partition(parent_table_name, options)
|
93
|
+
raise ArgumentError, 'name must be defined' if options[:name].blank?
|
94
|
+
if (options[:range_start].nil? || options[:range_end].nil?) && options[:default].blank?
|
95
|
+
raise ArgumentError, 'range_start and range_end or default must be defined'
|
96
|
+
end
|
97
|
+
|
98
|
+
Tablature.database.attach_to_range_partition(parent_table_name, options)
|
99
|
+
end
|
100
|
+
|
101
|
+
# Detaches a partition from a parent.
|
102
|
+
#
|
103
|
+
# @param parent_table_name [String, Symbol] The name of the parent table.
|
104
|
+
# @param [Hash] options The options to detach the partition.
|
105
|
+
#
|
106
|
+
# @see Tablature::Adapters::Postgres#detach_from_range_partition
|
107
|
+
def detach_from_range_partition(parent_table_name, options)
|
108
|
+
raise ArgumentError, 'name must be defined' if options[:name].blank?
|
109
|
+
|
110
|
+
Tablature.database.detach_from_range_partition(parent_table_name, options)
|
55
111
|
end
|
56
112
|
end
|
57
113
|
end
|
data/lib/tablature/version.rb
CHANGED
data/lib/tablature.rb
CHANGED
@@ -2,6 +2,7 @@ require 'tablature/adapters/postgres'
|
|
2
2
|
require 'tablature/command_recorder'
|
3
3
|
require 'tablature/configuration'
|
4
4
|
require 'tablature/model'
|
5
|
+
require 'tablature/partition'
|
5
6
|
require 'tablature/partitioned_table'
|
6
7
|
require 'tablature/railtie'
|
7
8
|
require 'tablature/schema_dumper'
|
data/tablature.gemspec
CHANGED
@@ -20,10 +20,12 @@ Gem::Specification.new do |spec|
|
|
20
20
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
21
21
|
spec.require_paths = ['lib']
|
22
22
|
|
23
|
-
spec.
|
23
|
+
spec.required_ruby_version = '>= 2.5.0'
|
24
|
+
|
25
|
+
spec.add_development_dependency 'bundler'
|
24
26
|
spec.add_development_dependency 'database_cleaner'
|
25
|
-
spec.add_development_dependency 'pg', '~>
|
26
|
-
spec.add_development_dependency 'rake', '~>
|
27
|
+
spec.add_development_dependency 'pg', '~> 1.1'
|
28
|
+
spec.add_development_dependency 'rake', '~> 13.0'
|
27
29
|
spec.add_development_dependency 'rspec', '~> 3.0'
|
28
30
|
spec.add_development_dependency 'rspec-instafail'
|
29
31
|
|
metadata
CHANGED
@@ -1,29 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tablature
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0.pre
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Aliou Diallo
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2020-05-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
19
|
+
version: '0'
|
20
20
|
type: :development
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - "
|
24
|
+
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '
|
26
|
+
version: '0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: database_cleaner
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -44,28 +44,28 @@ dependencies:
|
|
44
44
|
requirements:
|
45
45
|
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: '
|
47
|
+
version: '1.1'
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: '
|
54
|
+
version: '1.1'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: rake
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
59
|
- - "~>"
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: '
|
61
|
+
version: '13.0'
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
66
|
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version: '
|
68
|
+
version: '13.0'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: rspec
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -129,13 +129,13 @@ executables: []
|
|
129
129
|
extensions: []
|
130
130
|
extra_rdoc_files: []
|
131
131
|
files:
|
132
|
-
- ".
|
132
|
+
- ".github/workflows/ci.yml"
|
133
133
|
- ".gitignore"
|
134
134
|
- ".rspec"
|
135
135
|
- ".rubocop.yml"
|
136
136
|
- ".travis.yml"
|
137
|
+
- ".yardopts"
|
137
138
|
- Gemfile
|
138
|
-
- Gemfile.lock
|
139
139
|
- LICENSE.txt
|
140
140
|
- README.md
|
141
141
|
- Rakefile
|
@@ -152,6 +152,7 @@ files:
|
|
152
152
|
- lib/tablature/command_recorder.rb
|
153
153
|
- lib/tablature/configuration.rb
|
154
154
|
- lib/tablature/model.rb
|
155
|
+
- lib/tablature/partition.rb
|
155
156
|
- lib/tablature/partitioned_table.rb
|
156
157
|
- lib/tablature/railtie.rb
|
157
158
|
- lib/tablature/schema_dumper.rb
|
@@ -170,15 +171,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
170
171
|
requirements:
|
171
172
|
- - ">="
|
172
173
|
- !ruby/object:Gem::Version
|
173
|
-
version:
|
174
|
+
version: 2.5.0
|
174
175
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
175
176
|
requirements:
|
176
|
-
- - "
|
177
|
+
- - ">"
|
177
178
|
- !ruby/object:Gem::Version
|
178
|
-
version:
|
179
|
+
version: 1.3.1
|
179
180
|
requirements: []
|
180
|
-
|
181
|
-
rubygems_version: 2.7.6
|
181
|
+
rubygems_version: 3.0.3
|
182
182
|
signing_key:
|
183
183
|
specification_version: 4
|
184
184
|
summary: Rails + Postgres Partitions
|
data/.circleci/config.yml
DELETED
@@ -1,81 +0,0 @@
|
|
1
|
-
# TODO: Simplify this
|
2
|
-
version: 2
|
3
|
-
jobs:
|
4
|
-
postgres_10:
|
5
|
-
working_directory: ~/tablature-rb
|
6
|
-
docker:
|
7
|
-
- image: circleci/ruby:2.4
|
8
|
-
environment:
|
9
|
-
DATABASE_URL: "postgres://postgres@localhost:5432/dummy_test"
|
10
|
-
- image: circleci/postgres:10-alpine
|
11
|
-
environment:
|
12
|
-
POSTGRES_USER: postgres
|
13
|
-
POSTGRES_DB: dummy_test
|
14
|
-
POSTGRES_PASSWORD: ""
|
15
|
-
steps:
|
16
|
-
- checkout
|
17
|
-
|
18
|
-
- type: cache-restore
|
19
|
-
name: Restore bundle cache
|
20
|
-
key: tablature-{{ checksum "tablature.gemspec" }}-{{ checksum "Gemfile" }}
|
21
|
-
|
22
|
-
- run:
|
23
|
-
name: Install dependencies
|
24
|
-
command: bundle install --path vendor/bundle
|
25
|
-
|
26
|
-
- type: cache-save
|
27
|
-
name: Store bundle cache
|
28
|
-
key: tablature-{{ checksum "tablature.gemspec" }}-{{ checksum "Gemfile" }}
|
29
|
-
paths:
|
30
|
-
- vendor/bundle
|
31
|
-
|
32
|
-
- run:
|
33
|
-
name: Wait for Postgres
|
34
|
-
command: dockerize -wait tcp://localhost:5432 -timeout 1m
|
35
|
-
|
36
|
-
- run:
|
37
|
-
name: Run tests
|
38
|
-
command: bundle exec rspec --tag ~postgres_11
|
39
|
-
|
40
|
-
postgres_11:
|
41
|
-
working_directory: ~/tablature-rb
|
42
|
-
docker:
|
43
|
-
- image: circleci/ruby:2.4
|
44
|
-
environment:
|
45
|
-
DATABASE_URL: "postgres://postgres@localhost:5432/dummy_test"
|
46
|
-
- image: circleci/postgres:11-alpine
|
47
|
-
environment:
|
48
|
-
POSTGRES_USER: postgres
|
49
|
-
POSTGRES_DB: dummy_test
|
50
|
-
POSTGRES_PASSWORD: ""
|
51
|
-
steps:
|
52
|
-
- checkout
|
53
|
-
|
54
|
-
- type: cache-restore
|
55
|
-
name: Restore bundle cache
|
56
|
-
key: tablature-{{ checksum "tablature.gemspec" }}-{{ checksum "Gemfile" }}
|
57
|
-
|
58
|
-
- run:
|
59
|
-
name: Install dependencies
|
60
|
-
command: bundle install --path vendor/bundle
|
61
|
-
|
62
|
-
- type: cache-save
|
63
|
-
name: Store bundle cache
|
64
|
-
key: tablature-{{ checksum "tablature.gemspec" }}-{{ checksum "Gemfile" }}
|
65
|
-
paths:
|
66
|
-
- vendor/bundle
|
67
|
-
|
68
|
-
- run:
|
69
|
-
name: Wait for Postgres
|
70
|
-
command: dockerize -wait tcp://localhost:5432 -timeout 1m
|
71
|
-
|
72
|
-
- run:
|
73
|
-
name: Run tests
|
74
|
-
command: bundle exec rspec
|
75
|
-
|
76
|
-
workflows:
|
77
|
-
version: 2
|
78
|
-
tablature:
|
79
|
-
jobs:
|
80
|
-
- postgres_10
|
81
|
-
- postgres_11
|
data/Gemfile.lock
DELETED
@@ -1,106 +0,0 @@
|
|
1
|
-
PATH
|
2
|
-
remote: .
|
3
|
-
specs:
|
4
|
-
tablature (0.3.1)
|
5
|
-
activerecord (>= 5.0.0)
|
6
|
-
railties (>= 5.0.0)
|
7
|
-
|
8
|
-
GEM
|
9
|
-
remote: https://rubygems.org/
|
10
|
-
specs:
|
11
|
-
actionpack (5.2.2)
|
12
|
-
actionview (= 5.2.2)
|
13
|
-
activesupport (= 5.2.2)
|
14
|
-
rack (~> 2.0)
|
15
|
-
rack-test (>= 0.6.3)
|
16
|
-
rails-dom-testing (~> 2.0)
|
17
|
-
rails-html-sanitizer (~> 1.0, >= 1.0.2)
|
18
|
-
actionview (5.2.2)
|
19
|
-
activesupport (= 5.2.2)
|
20
|
-
builder (~> 3.1)
|
21
|
-
erubi (~> 1.4)
|
22
|
-
rails-dom-testing (~> 2.0)
|
23
|
-
rails-html-sanitizer (~> 1.0, >= 1.0.3)
|
24
|
-
activemodel (5.2.2)
|
25
|
-
activesupport (= 5.2.2)
|
26
|
-
activerecord (5.2.2)
|
27
|
-
activemodel (= 5.2.2)
|
28
|
-
activesupport (= 5.2.2)
|
29
|
-
arel (>= 9.0)
|
30
|
-
activesupport (5.2.2)
|
31
|
-
concurrent-ruby (~> 1.0, >= 1.0.2)
|
32
|
-
i18n (>= 0.7, < 2)
|
33
|
-
minitest (~> 5.1)
|
34
|
-
tzinfo (~> 1.1)
|
35
|
-
arel (9.0.0)
|
36
|
-
builder (3.2.3)
|
37
|
-
coderay (1.1.2)
|
38
|
-
concurrent-ruby (1.1.4)
|
39
|
-
crass (1.0.4)
|
40
|
-
database_cleaner (1.7.0)
|
41
|
-
diff-lcs (1.3)
|
42
|
-
erubi (1.8.0)
|
43
|
-
i18n (1.5.1)
|
44
|
-
concurrent-ruby (~> 1.0)
|
45
|
-
loofah (2.2.3)
|
46
|
-
crass (~> 1.0.2)
|
47
|
-
nokogiri (>= 1.5.9)
|
48
|
-
method_source (0.9.0)
|
49
|
-
mini_portile2 (2.4.0)
|
50
|
-
minitest (5.11.3)
|
51
|
-
nokogiri (1.10.1)
|
52
|
-
mini_portile2 (~> 2.4.0)
|
53
|
-
pg (0.21.0)
|
54
|
-
pry (0.12.2)
|
55
|
-
coderay (~> 1.1.0)
|
56
|
-
method_source (~> 0.9.0)
|
57
|
-
rack (2.0.6)
|
58
|
-
rack-test (1.1.0)
|
59
|
-
rack (>= 1.0, < 3)
|
60
|
-
rails-dom-testing (2.0.3)
|
61
|
-
activesupport (>= 4.2.0)
|
62
|
-
nokogiri (>= 1.6)
|
63
|
-
rails-html-sanitizer (1.0.4)
|
64
|
-
loofah (~> 2.2, >= 2.2.2)
|
65
|
-
railties (5.2.2)
|
66
|
-
actionpack (= 5.2.2)
|
67
|
-
activesupport (= 5.2.2)
|
68
|
-
method_source
|
69
|
-
rake (>= 0.8.7)
|
70
|
-
thor (>= 0.19.0, < 2.0)
|
71
|
-
rake (10.5.0)
|
72
|
-
rspec (3.7.0)
|
73
|
-
rspec-core (~> 3.7.0)
|
74
|
-
rspec-expectations (~> 3.7.0)
|
75
|
-
rspec-mocks (~> 3.7.0)
|
76
|
-
rspec-core (3.7.1)
|
77
|
-
rspec-support (~> 3.7.0)
|
78
|
-
rspec-expectations (3.7.0)
|
79
|
-
diff-lcs (>= 1.2.0, < 2.0)
|
80
|
-
rspec-support (~> 3.7.0)
|
81
|
-
rspec-instafail (1.0.0)
|
82
|
-
rspec
|
83
|
-
rspec-mocks (3.7.0)
|
84
|
-
diff-lcs (>= 1.2.0, < 2.0)
|
85
|
-
rspec-support (~> 3.7.0)
|
86
|
-
rspec-support (3.7.1)
|
87
|
-
thor (0.20.3)
|
88
|
-
thread_safe (0.3.6)
|
89
|
-
tzinfo (1.2.5)
|
90
|
-
thread_safe (~> 0.1)
|
91
|
-
|
92
|
-
PLATFORMS
|
93
|
-
ruby
|
94
|
-
|
95
|
-
DEPENDENCIES
|
96
|
-
bundler (~> 1.16)
|
97
|
-
database_cleaner
|
98
|
-
pg (~> 0.19)
|
99
|
-
pry
|
100
|
-
rake (~> 10.0)
|
101
|
-
rspec (~> 3.0)
|
102
|
-
rspec-instafail
|
103
|
-
tablature!
|
104
|
-
|
105
|
-
BUNDLED WITH
|
106
|
-
1.17.2
|