table_saw 2.10.0 → 3.0.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 +4 -4
- data/.github/workflows/ruby.yml +4 -3
- data/.rubocop.yml +4 -1
- data/.tool-versions +1 -1
- data/Appraisals +4 -4
- data/Gemfile +9 -0
- data/Gemfile.lock +82 -75
- data/README.md +158 -22
- data/gemfiles/activerecord_6.1.0.gemfile +9 -0
- data/gemfiles/activerecord_6.1.0.gemfile.lock +79 -75
- data/gemfiles/activerecord_7.0.0.gemfile +17 -0
- data/gemfiles/activerecord_7.0.0.gemfile.lock +162 -0
- data/lib/table_saw/create_dump_file.rb +1 -1
- data/lib/table_saw/foreign_key.rb +1 -1
- data/lib/table_saw/manifest.rb +1 -1
- data/lib/table_saw/variable_interpolation.rb +37 -0
- data/lib/table_saw/version.rb +1 -1
- data/lib/table_saw.rb +1 -0
- data/table_saw.gemspec +2 -11
- metadata +9 -135
- data/.ruby-gemset +0 -1
- data/.ruby-version +0 -1
- data/gemfiles/activerecord_6.0.0.gemfile +0 -8
- data/gemfiles/activerecord_6.0.0.gemfile.lock +0 -159
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 5e8e8f428d4b3d28ddec794d07a0d052e6280bfd96ee0b58735b3bcefa5a7bee
|
|
4
|
+
data.tar.gz: 64249bc2ae252e9b361c32b376f1679837ac1fd82bde70b11eda9fad66050a00
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 11b993bf2a9f723783b3f67648af15b794b807678db845b6c57b1ac8e5b57762ac41a3c1530696f5f3f99d6a7649061a22a88267aab23fb4e5cf158533f014e6
|
|
7
|
+
data.tar.gz: 84eb90d309a2dc4a8ddd04c4898c748f81f6c2f62223780b9e5d272913d2e990c840880e49e17dbe8832726b0eb6ea38f7f21970a44fd49ebd85d3b7e12b91e6
|
data/.github/workflows/ruby.yml
CHANGED
|
@@ -10,11 +10,12 @@ jobs:
|
|
|
10
10
|
strategy:
|
|
11
11
|
matrix:
|
|
12
12
|
ruby:
|
|
13
|
-
- '
|
|
14
|
-
- '3.
|
|
13
|
+
- '3.0.5'
|
|
14
|
+
- '3.1.4'
|
|
15
|
+
- '3.2.2'
|
|
15
16
|
activerecord:
|
|
16
|
-
- '6.0.0'
|
|
17
17
|
- '6.1.0'
|
|
18
|
+
- '7.0.0'
|
|
18
19
|
|
|
19
20
|
env:
|
|
20
21
|
BUNDLE_GEMFILE: ${{ github.workspace }}/gemfiles/activerecord_${{ matrix.activerecord }}.gemfile
|
data/.rubocop.yml
CHANGED
|
@@ -2,7 +2,7 @@ require: rubocop-rspec
|
|
|
2
2
|
|
|
3
3
|
AllCops:
|
|
4
4
|
NewCops: enable
|
|
5
|
-
TargetRubyVersion:
|
|
5
|
+
TargetRubyVersion: 3.0
|
|
6
6
|
Exclude:
|
|
7
7
|
- gemfiles/*
|
|
8
8
|
|
|
@@ -34,6 +34,9 @@ Style/EmptyMethod:
|
|
|
34
34
|
Style/ExponentialNotation:
|
|
35
35
|
Enabled: true
|
|
36
36
|
|
|
37
|
+
Style/FetchEnvVar:
|
|
38
|
+
Enabled: false
|
|
39
|
+
|
|
37
40
|
Style/FormatStringToken:
|
|
38
41
|
EnforcedStyle: template
|
|
39
42
|
|
data/.tool-versions
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
ruby 3.
|
|
1
|
+
ruby 3.2.2
|
data/Appraisals
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
appraise 'activerecord-6.0.0' do
|
|
4
|
-
gem 'activerecord', '~> 6.0', '< 6.1'
|
|
5
|
-
end
|
|
6
|
-
|
|
7
3
|
appraise 'activerecord-6.1.0' do
|
|
8
4
|
gem 'activerecord', '~> 6.1', '< 6.2'
|
|
9
5
|
end
|
|
6
|
+
|
|
7
|
+
appraise 'activerecord-7.0.0' do
|
|
8
|
+
gem 'activerecord', '~> 7.0', '< 7.1'
|
|
9
|
+
end
|
data/Gemfile
CHANGED
|
@@ -6,3 +6,12 @@ source 'https://rubygems.org'
|
|
|
6
6
|
gemspec
|
|
7
7
|
|
|
8
8
|
gem 'appraisal'
|
|
9
|
+
gem 'bundler', '~> 2.0'
|
|
10
|
+
gem 'combustion', '~> 1.3'
|
|
11
|
+
gem 'database_cleaner', '~> 2'
|
|
12
|
+
gem 'pry'
|
|
13
|
+
gem 'rake', '13.0.3'
|
|
14
|
+
gem 'rspec', '~> 3.0'
|
|
15
|
+
gem 'rubocop-rspec', '~> 2.3'
|
|
16
|
+
gem 'scenic', '~> 1.5'
|
|
17
|
+
gem 'simplecov', '~> 0.16'
|
data/Gemfile.lock
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
table_saw (
|
|
4
|
+
table_saw (3.0.0)
|
|
5
5
|
activerecord (>= 5.2)
|
|
6
6
|
pg
|
|
7
7
|
thor
|
|
@@ -9,131 +9,138 @@ PATH
|
|
|
9
9
|
GEM
|
|
10
10
|
remote: https://rubygems.org/
|
|
11
11
|
specs:
|
|
12
|
-
actionpack (
|
|
13
|
-
actionview (=
|
|
14
|
-
activesupport (=
|
|
15
|
-
rack (~> 2.0, >= 2.
|
|
12
|
+
actionpack (7.0.5)
|
|
13
|
+
actionview (= 7.0.5)
|
|
14
|
+
activesupport (= 7.0.5)
|
|
15
|
+
rack (~> 2.0, >= 2.2.4)
|
|
16
16
|
rack-test (>= 0.6.3)
|
|
17
17
|
rails-dom-testing (~> 2.0)
|
|
18
18
|
rails-html-sanitizer (~> 1.0, >= 1.2.0)
|
|
19
|
-
actionview (
|
|
20
|
-
activesupport (=
|
|
19
|
+
actionview (7.0.5)
|
|
20
|
+
activesupport (= 7.0.5)
|
|
21
21
|
builder (~> 3.1)
|
|
22
22
|
erubi (~> 1.4)
|
|
23
23
|
rails-dom-testing (~> 2.0)
|
|
24
24
|
rails-html-sanitizer (~> 1.1, >= 1.2.0)
|
|
25
|
-
activemodel (
|
|
26
|
-
activesupport (=
|
|
27
|
-
activerecord (
|
|
28
|
-
activemodel (=
|
|
29
|
-
activesupport (=
|
|
30
|
-
activesupport (
|
|
25
|
+
activemodel (7.0.5)
|
|
26
|
+
activesupport (= 7.0.5)
|
|
27
|
+
activerecord (7.0.5)
|
|
28
|
+
activemodel (= 7.0.5)
|
|
29
|
+
activesupport (= 7.0.5)
|
|
30
|
+
activesupport (7.0.5)
|
|
31
31
|
concurrent-ruby (~> 1.0, >= 1.0.2)
|
|
32
32
|
i18n (>= 1.6, < 2)
|
|
33
33
|
minitest (>= 5.1)
|
|
34
34
|
tzinfo (~> 2.0)
|
|
35
|
-
|
|
36
|
-
appraisal (2.4.0)
|
|
35
|
+
appraisal (2.4.1)
|
|
37
36
|
bundler
|
|
38
37
|
rake
|
|
39
38
|
thor (>= 0.14.0)
|
|
40
39
|
ast (2.4.2)
|
|
41
40
|
builder (3.2.4)
|
|
42
41
|
coderay (1.1.3)
|
|
43
|
-
combustion (1.3.
|
|
42
|
+
combustion (1.3.7)
|
|
44
43
|
activesupport (>= 3.0.0)
|
|
45
44
|
railties (>= 3.0.0)
|
|
46
45
|
thor (>= 0.14.6)
|
|
47
|
-
concurrent-ruby (1.
|
|
46
|
+
concurrent-ruby (1.2.2)
|
|
48
47
|
crass (1.0.6)
|
|
49
|
-
database_cleaner (2.0.
|
|
50
|
-
database_cleaner-active_record (
|
|
51
|
-
database_cleaner-active_record (2.0
|
|
48
|
+
database_cleaner (2.0.2)
|
|
49
|
+
database_cleaner-active_record (>= 2, < 3)
|
|
50
|
+
database_cleaner-active_record (2.1.0)
|
|
52
51
|
activerecord (>= 5.a)
|
|
53
52
|
database_cleaner-core (~> 2.0.0)
|
|
54
53
|
database_cleaner-core (2.0.1)
|
|
55
|
-
diff-lcs (1.
|
|
54
|
+
diff-lcs (1.5.0)
|
|
56
55
|
docile (1.4.0)
|
|
57
|
-
erubi (1.
|
|
58
|
-
i18n (1.
|
|
56
|
+
erubi (1.12.0)
|
|
57
|
+
i18n (1.13.0)
|
|
59
58
|
concurrent-ruby (~> 1.0)
|
|
60
|
-
|
|
59
|
+
json (2.6.3)
|
|
60
|
+
loofah (2.21.3)
|
|
61
61
|
crass (~> 1.0.2)
|
|
62
|
-
nokogiri (>= 1.
|
|
62
|
+
nokogiri (>= 1.12.0)
|
|
63
63
|
method_source (1.0.0)
|
|
64
|
-
mini_portile2 (2.
|
|
65
|
-
minitest (5.
|
|
66
|
-
nokogiri (1.
|
|
67
|
-
mini_portile2 (~> 2.
|
|
64
|
+
mini_portile2 (2.8.2)
|
|
65
|
+
minitest (5.18.0)
|
|
66
|
+
nokogiri (1.15.2)
|
|
67
|
+
mini_portile2 (~> 2.8.2)
|
|
68
68
|
racc (~> 1.4)
|
|
69
|
-
parallel (1.
|
|
70
|
-
parser (3.
|
|
69
|
+
parallel (1.23.0)
|
|
70
|
+
parser (3.2.2.1)
|
|
71
71
|
ast (~> 2.4.1)
|
|
72
|
-
pg (1.
|
|
73
|
-
pry (0.14.
|
|
72
|
+
pg (1.5.3)
|
|
73
|
+
pry (0.14.2)
|
|
74
74
|
coderay (~> 1.1)
|
|
75
75
|
method_source (~> 1.0)
|
|
76
|
-
racc (1.
|
|
77
|
-
rack (2.2.
|
|
78
|
-
rack-test (
|
|
79
|
-
rack (>= 1.
|
|
76
|
+
racc (1.6.2)
|
|
77
|
+
rack (2.2.7)
|
|
78
|
+
rack-test (2.1.0)
|
|
79
|
+
rack (>= 1.3)
|
|
80
80
|
rails-dom-testing (2.0.3)
|
|
81
81
|
activesupport (>= 4.2.0)
|
|
82
82
|
nokogiri (>= 1.6)
|
|
83
|
-
rails-html-sanitizer (1.
|
|
84
|
-
loofah (~> 2.
|
|
85
|
-
railties (
|
|
86
|
-
actionpack (=
|
|
87
|
-
activesupport (=
|
|
83
|
+
rails-html-sanitizer (1.5.0)
|
|
84
|
+
loofah (~> 2.19, >= 2.19.1)
|
|
85
|
+
railties (7.0.5)
|
|
86
|
+
actionpack (= 7.0.5)
|
|
87
|
+
activesupport (= 7.0.5)
|
|
88
88
|
method_source
|
|
89
|
-
rake (>=
|
|
89
|
+
rake (>= 12.2)
|
|
90
90
|
thor (~> 1.0)
|
|
91
|
-
|
|
91
|
+
zeitwerk (~> 2.5)
|
|
92
|
+
rainbow (3.1.1)
|
|
92
93
|
rake (13.0.3)
|
|
93
|
-
regexp_parser (2.
|
|
94
|
+
regexp_parser (2.8.0)
|
|
94
95
|
rexml (3.2.5)
|
|
95
|
-
rspec (3.
|
|
96
|
-
rspec-core (~> 3.
|
|
97
|
-
rspec-expectations (~> 3.
|
|
98
|
-
rspec-mocks (~> 3.
|
|
99
|
-
rspec-core (3.
|
|
100
|
-
rspec-support (~> 3.
|
|
101
|
-
rspec-expectations (3.
|
|
96
|
+
rspec (3.12.0)
|
|
97
|
+
rspec-core (~> 3.12.0)
|
|
98
|
+
rspec-expectations (~> 3.12.0)
|
|
99
|
+
rspec-mocks (~> 3.12.0)
|
|
100
|
+
rspec-core (3.12.2)
|
|
101
|
+
rspec-support (~> 3.12.0)
|
|
102
|
+
rspec-expectations (3.12.3)
|
|
102
103
|
diff-lcs (>= 1.2.0, < 2.0)
|
|
103
|
-
rspec-support (~> 3.
|
|
104
|
-
rspec-mocks (3.
|
|
104
|
+
rspec-support (~> 3.12.0)
|
|
105
|
+
rspec-mocks (3.12.5)
|
|
105
106
|
diff-lcs (>= 1.2.0, < 2.0)
|
|
106
|
-
rspec-support (~> 3.
|
|
107
|
-
rspec-support (3.
|
|
108
|
-
rubocop (1.
|
|
107
|
+
rspec-support (~> 3.12.0)
|
|
108
|
+
rspec-support (3.12.0)
|
|
109
|
+
rubocop (1.51.0)
|
|
110
|
+
json (~> 2.3)
|
|
109
111
|
parallel (~> 1.10)
|
|
110
|
-
parser (>= 3.
|
|
112
|
+
parser (>= 3.2.0.0)
|
|
111
113
|
rainbow (>= 2.2.2, < 4.0)
|
|
112
114
|
regexp_parser (>= 1.8, < 3.0)
|
|
113
|
-
rexml
|
|
114
|
-
rubocop-ast (>= 1.
|
|
115
|
+
rexml (>= 3.2.5, < 4.0)
|
|
116
|
+
rubocop-ast (>= 1.28.0, < 2.0)
|
|
115
117
|
ruby-progressbar (~> 1.7)
|
|
116
|
-
unicode-display_width (>=
|
|
117
|
-
rubocop-ast (1.
|
|
118
|
-
parser (>= 3.
|
|
119
|
-
rubocop-
|
|
120
|
-
rubocop (~> 1.
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
118
|
+
unicode-display_width (>= 2.4.0, < 3.0)
|
|
119
|
+
rubocop-ast (1.28.1)
|
|
120
|
+
parser (>= 3.2.1.0)
|
|
121
|
+
rubocop-capybara (2.18.0)
|
|
122
|
+
rubocop (~> 1.41)
|
|
123
|
+
rubocop-factory_bot (2.23.1)
|
|
124
|
+
rubocop (~> 1.33)
|
|
125
|
+
rubocop-rspec (2.22.0)
|
|
126
|
+
rubocop (~> 1.33)
|
|
127
|
+
rubocop-capybara (~> 2.17)
|
|
128
|
+
rubocop-factory_bot (~> 2.22)
|
|
129
|
+
ruby-progressbar (1.13.0)
|
|
130
|
+
scenic (1.7.0)
|
|
124
131
|
activerecord (>= 4.0.0)
|
|
125
132
|
railties (>= 4.0.0)
|
|
126
|
-
simplecov (0.
|
|
133
|
+
simplecov (0.22.0)
|
|
127
134
|
docile (~> 1.1)
|
|
128
135
|
simplecov-html (~> 0.11)
|
|
129
136
|
simplecov_json_formatter (~> 0.1)
|
|
130
137
|
simplecov-html (0.12.3)
|
|
131
|
-
simplecov_json_formatter (0.1.
|
|
132
|
-
thor (1.
|
|
133
|
-
tzinfo (2.0.
|
|
138
|
+
simplecov_json_formatter (0.1.4)
|
|
139
|
+
thor (1.2.2)
|
|
140
|
+
tzinfo (2.0.6)
|
|
134
141
|
concurrent-ruby (~> 1.0)
|
|
135
|
-
unicode-display_width (2.
|
|
136
|
-
zeitwerk (2.
|
|
142
|
+
unicode-display_width (2.4.2)
|
|
143
|
+
zeitwerk (2.6.8)
|
|
137
144
|
|
|
138
145
|
PLATFORMS
|
|
139
146
|
ruby
|
|
@@ -152,4 +159,4 @@ DEPENDENCIES
|
|
|
152
159
|
table_saw!
|
|
153
160
|
|
|
154
161
|
BUNDLED WITH
|
|
155
|
-
2.
|
|
162
|
+
2.4.13
|
data/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
[](https://codeclimate.com/github/hasghari/table_saw/maintainability)
|
|
3
3
|
[](https://codeclimate.com/github/hasghari/table_saw/test_coverage)
|
|
4
4
|
|
|
5
|
-
#
|
|
5
|
+
# table-saw
|
|
6
6
|
|
|
7
7
|
This gem creates a PSQL dump file (data only) from a Postgres database by only dumping a subset of data defined by a
|
|
8
8
|
manifest file.
|
|
@@ -50,52 +50,188 @@ Options:
|
|
|
50
50
|
-o, [--output=OUTPUT] # Default value is 'output.dump'
|
|
51
51
|
```
|
|
52
52
|
|
|
53
|
-
|
|
53
|
+
### Manifest
|
|
54
|
+
|
|
55
|
+
The manifest is a YAML file that describes the dataset to be exported to a dump file. At the top level, the manifest
|
|
56
|
+
file supports 4 nodes:
|
|
57
|
+
|
|
58
|
+
- [variables](#variables)
|
|
59
|
+
- [tables](#tables)
|
|
60
|
+
- [has_many](#has_many)
|
|
61
|
+
- [foreign_keys](#foreign_keys)
|
|
62
|
+
|
|
63
|
+
The examples that follow assume you have a database set up as follows:
|
|
64
|
+
```sql
|
|
65
|
+
CREATE TABLE authors (
|
|
66
|
+
id bigint NOT NULL,
|
|
67
|
+
name character varying NOT NULL,
|
|
68
|
+
PRIMARY KEY (id)
|
|
69
|
+
);
|
|
70
|
+
|
|
71
|
+
CREATE TABLE books (
|
|
72
|
+
id bigint NOT NULL,
|
|
73
|
+
author_id bigint NOT NULL,
|
|
74
|
+
name character varying NOT NULL,
|
|
75
|
+
votes integer DEFAULT 0 NOT NULL,
|
|
76
|
+
PRIMARY KEY (id),
|
|
77
|
+
CONSTRAINT fk_author FOREIGN KEY (author_id) REFERENCES authors(id)
|
|
78
|
+
);
|
|
79
|
+
|
|
80
|
+
INSERT INTO authors (id, name) VALUES (1, 'Dan Brown');
|
|
81
|
+
INSERT INTO authors (id, name) VALUES (2, 'J. K. Rowling');
|
|
82
|
+
|
|
83
|
+
INSERT INTO books (id, author_id, name, votes) VALUES (1, 1, 'Angels and Demons', 10);
|
|
84
|
+
INSERT INTO books (id, author_id, name, votes) VALUES (2, 1, 'Digital Fortress', 35);
|
|
85
|
+
INSERT INTO books (id, author_id, name, votes) VALUES (3, 1, 'The Da Vinci Code', 50);
|
|
86
|
+
INSERT INTO books (id, author_id, name, votes) VALUES (4, 2, 'Philosopher''s Stone', 55);
|
|
87
|
+
INSERT INTO books (id, author_id, name, votes) VALUES (5, 2, 'Chamber of Secrets', 5);
|
|
88
|
+
INSERT INTO books (id, author_id, name, votes) VALUES (6, 2, 'Prisoner of Azkaban', 25);
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
#### variables
|
|
92
|
+
Variables allow you parameterize the queries in the manifest. You can use the `%{variable}` substitution pattern in your
|
|
93
|
+
query strings:
|
|
54
94
|
|
|
55
95
|
```yaml
|
|
56
96
|
variables:
|
|
57
|
-
author_id:
|
|
97
|
+
author_id: 2
|
|
58
98
|
tables:
|
|
59
99
|
- table: books
|
|
60
100
|
query: "select * from books where author_id = %{author_id}"
|
|
61
101
|
```
|
|
62
102
|
|
|
63
|
-
|
|
64
|
-
`authors` table where `id = 24`.
|
|
65
|
-
|
|
66
|
-
Assuming there is a `chapters` table with a foreign key reference of `book_id` to the `books` table, the above manifest
|
|
67
|
-
file will **not** automatically retrieve those records. If `chapters` records are also desired, there a couple ways to
|
|
68
|
-
accomplish this:
|
|
103
|
+
Additionally, you can now use the `%{variable}` substitution pattern in other variables:
|
|
69
104
|
|
|
70
105
|
```yaml
|
|
71
106
|
variables:
|
|
72
|
-
author_id:
|
|
107
|
+
author_id: '1,3,4',
|
|
108
|
+
book_ids: 'select * from books where author_id in (%{author_id})'
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
#### tables
|
|
112
|
+
This is where you list the specific tables that you want to export. If you only specify the `table` without providing a
|
|
113
|
+
`query`, then the **entire** table will be exported. However, if you specify a `query`, then only rows matching that
|
|
114
|
+
query will be exported:
|
|
115
|
+
|
|
116
|
+
```yaml
|
|
73
117
|
tables:
|
|
74
118
|
- table: books
|
|
75
|
-
query: "select * from books where author_id =
|
|
119
|
+
query: "select * from books where author_id = 2"
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
The above manifest will only export rows from the `books` table where `author_id = 2`. In addition, due to the
|
|
123
|
+
foreign key constraint defined from `books(author_id)` to `authors(id)`, table-saw will automatically export the row
|
|
124
|
+
from the `authors` table where `id = 2` in order to preserve referential integrity.
|
|
125
|
+
|
|
126
|
+
The above manifest can alternatively be written as follows where exactly the same rows would be exported:
|
|
127
|
+
|
|
128
|
+
```yaml
|
|
129
|
+
tables:
|
|
130
|
+
- table: authors
|
|
131
|
+
query: "select * from authors where id = 2"
|
|
132
|
+
has_many:
|
|
133
|
+
- books
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
Notice we have to explicitly list the `has_many` association to the `books` table. Since `authors` does not have a
|
|
137
|
+
dependency on `books` to preserve referential integrity, table-saw by design will not export the associated `books`
|
|
138
|
+
rows in order to keep the output dump file as small as possible. In other words, if we eliminate the `has_many` node
|
|
139
|
+
from the manifest above, table-saw will only export a single author with `id = 2`.
|
|
140
|
+
|
|
141
|
+
#### has_many
|
|
142
|
+
This is where we define which optional associations we want to export for each table:
|
|
143
|
+
|
|
144
|
+
```yaml
|
|
145
|
+
tables:
|
|
146
|
+
- table: authors
|
|
147
|
+
query: "select * from authors where id = 1"
|
|
148
|
+
- table: books
|
|
149
|
+
query: "select * from books where id = 6"
|
|
76
150
|
has_many:
|
|
77
|
-
|
|
78
|
-
-
|
|
151
|
+
authors:
|
|
152
|
+
- books
|
|
79
153
|
```
|
|
80
154
|
|
|
81
|
-
|
|
155
|
+
The above manifest would export the following rows:
|
|
156
|
+
|
|
157
|
+
* authors:
|
|
158
|
+
- `id = 1` because of the explicit query in the manifest
|
|
159
|
+
- `id = 2` because it is the `author_id` for `books` with `id = 6`
|
|
160
|
+
|
|
161
|
+
* books:
|
|
162
|
+
- `id = [1, 2, 3]` due to the `has_many` association for `authors` with `id = 1`
|
|
163
|
+
- `id = [4, 5, 6]` due to the `has_many` association for `authors` with `id = 2`
|
|
164
|
+
|
|
165
|
+
Now, if instead of defining the `has_many` node at the top level, we define it under the `authors` table as follows:
|
|
82
166
|
|
|
83
167
|
```yaml
|
|
84
|
-
variables:
|
|
85
|
-
author_id: 24
|
|
86
168
|
tables:
|
|
87
|
-
- table:
|
|
88
|
-
query: "select * from
|
|
169
|
+
- table: authors
|
|
170
|
+
query: "select * from authors where id = 1"
|
|
171
|
+
has_many:
|
|
172
|
+
- books
|
|
173
|
+
- table: books
|
|
174
|
+
query: "select * from books where id = 6"
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
The above manifest would export the following rows:
|
|
178
|
+
|
|
179
|
+
* authors:
|
|
180
|
+
- `id = 1` because of the explicit query in the manifest
|
|
181
|
+
- `id = 2` because it is the `author_id` for `books` with `id = 6`
|
|
182
|
+
|
|
183
|
+
* books:
|
|
184
|
+
- `id = [1, 2, 3]` due to the `has_many` association for `authors` with `id = 1`
|
|
185
|
+
- `id = 6` due to the explicit query in the manifest
|
|
186
|
+
|
|
187
|
+
One potential pitfall with using `has_many` is that you end up pulling in too many associated rows when all you wanted
|
|
188
|
+
was a limited number. table-saw allows you to specify a `scope` and `limit`:
|
|
189
|
+
|
|
190
|
+
```yaml
|
|
191
|
+
tables:
|
|
192
|
+
- table: authors
|
|
193
|
+
query: "select * from authors where id = 1"
|
|
194
|
+
- table: books
|
|
195
|
+
query: "select * from books where id = 6"
|
|
196
|
+
has_many:
|
|
197
|
+
authors:
|
|
198
|
+
- books:
|
|
199
|
+
scope: "votes > 30"
|
|
200
|
+
limit: 1
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
The above manifest would export the following rows:
|
|
204
|
+
|
|
205
|
+
* authors:
|
|
206
|
+
- `id = 1` because of the explicit query in the manifest
|
|
207
|
+
- `id = 2` because it is the `author_id` for `books` with `id = 6`
|
|
208
|
+
|
|
209
|
+
* books:
|
|
210
|
+
- Either `id = 2` or `id = 3` for `author_id = 1` since they both have `vote > 30` and the limit of 1 will randomly
|
|
211
|
+
choose one of them
|
|
212
|
+
- Only `id = 4` for `author_id = 2` since it's the only book for that author with `vote > 30`
|
|
213
|
+
|
|
214
|
+
#### foreign_keys
|
|
215
|
+
By default, table-saw will query the Postgres `information_schema` to look up the foreign key constraints and determine
|
|
216
|
+
whether it needs to export associated rows. However, if your database schema does not define foreign key constraints for
|
|
217
|
+
the tables you would like to export, you can manually define them in the manifest. Assuming we had not defined any
|
|
218
|
+
foreign key constraints for the `books` table, we could specify it in the manifest as follows:
|
|
219
|
+
|
|
220
|
+
```yaml
|
|
221
|
+
foreign_keys:
|
|
222
|
+
- from_table: books
|
|
223
|
+
from_column: author_id
|
|
224
|
+
to_table: authors
|
|
225
|
+
to_column: id
|
|
89
226
|
```
|
|
90
227
|
|
|
91
|
-
|
|
92
|
-
the `authors`, `books` and `chapters` tables.
|
|
228
|
+
## Dump and Restore
|
|
93
229
|
|
|
94
230
|
Once your dump file has been created, you can import the data using `psql`:
|
|
95
231
|
|
|
96
232
|
```bash
|
|
97
|
-
table-saw dump -m manifest.yml -o
|
|
98
|
-
psql -h localhost -U postgres -d library <
|
|
233
|
+
table-saw dump -m manifest.yml -o library.dump
|
|
234
|
+
psql -h localhost -U postgres -d library < library.dump
|
|
99
235
|
```
|
|
100
236
|
|
|
101
237
|
## Development
|
|
@@ -3,6 +3,15 @@
|
|
|
3
3
|
source "https://rubygems.org"
|
|
4
4
|
|
|
5
5
|
gem "appraisal"
|
|
6
|
+
gem "bundler", "~> 2.0"
|
|
7
|
+
gem "combustion", "~> 1.3"
|
|
8
|
+
gem "database_cleaner", "~> 2"
|
|
9
|
+
gem "pry"
|
|
10
|
+
gem "rake", "13.0.3"
|
|
11
|
+
gem "rspec", "~> 3.0"
|
|
12
|
+
gem "rubocop-rspec", "~> 2.3"
|
|
13
|
+
gem "scenic", "~> 1.5"
|
|
14
|
+
gem "simplecov", "~> 0.16"
|
|
6
15
|
gem "activerecord", "~> 6.1", "< 6.2"
|
|
7
16
|
|
|
8
17
|
gemspec path: "../"
|