table_saw 0.5.0 → 1.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/Gemfile.lock +1 -1
- data/lib/table_saw/connection.rb +6 -0
- data/lib/table_saw/dependency_graph/add_directive.rb +4 -0
- data/lib/table_saw/dependency_graph/belongs_to_directives.rb +7 -7
- data/lib/table_saw/dependency_graph/build.rb +2 -6
- data/lib/table_saw/dependency_graph/dump_table.rb +10 -6
- data/lib/table_saw/dependency_graph/has_many_directives.rb +13 -10
- data/lib/table_saw/dependency_graph.rb +0 -1
- data/lib/table_saw/information_schema.rb +25 -0
- data/lib/table_saw/manifest.rb +8 -10
- data/lib/table_saw/queries/foreign_key_relationships.rb +1 -3
- data/lib/table_saw/queries/materialized_views.rb +3 -3
- data/lib/table_saw/queries/primary_keys.rb +20 -0
- data/lib/table_saw/queries/serial_sequences.rb +2 -4
- data/lib/table_saw/queries.rb +1 -1
- data/lib/table_saw/version.rb +1 -1
- data/lib/table_saw.rb +5 -0
- metadata +4 -4
- data/lib/table_saw/dependency_graph/context.rb +0 -42
- data/lib/table_saw/queries/no_id_tables.rb +0 -20
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cf3632df0d6aab24f6fc503091fd5b571c4d755fd5bddbb31a31830eb5a8aba0
|
4
|
+
data.tar.gz: 3937c874285d79c122603e8f19d4ca0739a13b4713f251209c87e8fc6cf2ffab
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0c2f657b780d21fb9f53879f1bc99425517d19c56784dfbb980f3518ddf026d93bea02a11bd1ead2827666ed0b970916fc5c74f13fd9258a2b11bbb797b2e433
|
7
|
+
data.tar.gz: 77b8c86389378273c1b39a1a4fbbe7217c25dd9db576724f44621712e01d495038f7dd2f6a763ae46bcac0487f9cf1c240dcbc1a392f08017f5f4ba1771d7bae
|
data/Gemfile.lock
CHANGED
data/lib/table_saw/connection.rb
CHANGED
@@ -3,10 +3,9 @@
|
|
3
3
|
module TableSaw
|
4
4
|
module DependencyGraph
|
5
5
|
class BelongsToDirectives
|
6
|
-
attr_reader :
|
6
|
+
attr_reader :directive
|
7
7
|
|
8
|
-
def initialize(
|
9
|
-
@context = context
|
8
|
+
def initialize(directive)
|
10
9
|
@directive = directive
|
11
10
|
end
|
12
11
|
|
@@ -19,7 +18,7 @@ module TableSaw
|
|
19
18
|
private
|
20
19
|
|
21
20
|
def associations
|
22
|
-
|
21
|
+
TableSaw.information_schema.belongs_to.fetch(directive.table_name, {})
|
23
22
|
end
|
24
23
|
|
25
24
|
def ids
|
@@ -31,9 +30,10 @@ module TableSaw
|
|
31
30
|
def query_result
|
32
31
|
return [] unless directive.selectable?
|
33
32
|
|
34
|
-
|
35
|
-
format('select %{columns} from %{table_name} where
|
36
|
-
|
33
|
+
TableSaw::Connection.exec(
|
34
|
+
format('select %{columns} from %{table_name} where %{primary_key} in (%{ids})',
|
35
|
+
primary_key: directive.primary_key, columns: associations.keys.join(','),
|
36
|
+
table_name: directive.table_name, ids: directive.ids.join(','))
|
37
37
|
)
|
38
38
|
end
|
39
39
|
end
|
@@ -32,19 +32,15 @@ module TableSaw
|
|
32
32
|
if record
|
33
33
|
dir.partial? ? record.fetch_associations(dir) : []
|
34
34
|
else
|
35
|
-
TableSaw::DependencyGraph::DumpTable.new(
|
35
|
+
TableSaw::DependencyGraph::DumpTable.new(manifest: manifest, name: dir.table_name, partial: dir.partial?)
|
36
36
|
.tap { |table| records[dir.table_name] = table }.fetch_associations(dir)
|
37
37
|
end
|
38
38
|
end
|
39
39
|
|
40
|
-
def context
|
41
|
-
@context ||= TableSaw::DependencyGraph::Context.new(manifest)
|
42
|
-
end
|
43
|
-
|
44
40
|
def select_ids(table)
|
45
41
|
return [] unless table.partial?
|
46
42
|
|
47
|
-
|
43
|
+
TableSaw::Connection.exec(table.query).map { |row| row[TableSaw.information_schema.primary_keys[table.name]] }
|
48
44
|
end
|
49
45
|
end
|
50
46
|
end
|
@@ -3,10 +3,10 @@
|
|
3
3
|
module TableSaw
|
4
4
|
module DependencyGraph
|
5
5
|
class DumpTable
|
6
|
-
attr_reader :
|
6
|
+
attr_reader :manifest, :name, :partial, :ids
|
7
7
|
|
8
|
-
def initialize(
|
9
|
-
@
|
8
|
+
def initialize(manifest:, name:, partial: true)
|
9
|
+
@manifest = manifest
|
10
10
|
@name = name
|
11
11
|
@partial = partial
|
12
12
|
@ids = Set.new
|
@@ -14,7 +14,7 @@ module TableSaw
|
|
14
14
|
|
15
15
|
def copy_statement
|
16
16
|
if partial
|
17
|
-
"select * from #{name} where
|
17
|
+
"select * from #{name} where #{primary_key} in (#{ids.to_a.join(',')})"
|
18
18
|
else
|
19
19
|
"select * from #{name}"
|
20
20
|
end
|
@@ -29,11 +29,15 @@ module TableSaw
|
|
29
29
|
private
|
30
30
|
|
31
31
|
def fetch_belongs_to(directive)
|
32
|
-
TableSaw::DependencyGraph::BelongsToDirectives.new(
|
32
|
+
TableSaw::DependencyGraph::BelongsToDirectives.new(directive).call
|
33
33
|
end
|
34
34
|
|
35
35
|
def fetch_has_many(directive)
|
36
|
-
TableSaw::DependencyGraph::HasManyDirectives.new(
|
36
|
+
TableSaw::DependencyGraph::HasManyDirectives.new(manifest, directive).call
|
37
|
+
end
|
38
|
+
|
39
|
+
def primary_key
|
40
|
+
TableSaw.information_schema.primary_keys[name]
|
37
41
|
end
|
38
42
|
end
|
39
43
|
end
|
@@ -3,17 +3,19 @@
|
|
3
3
|
module TableSaw
|
4
4
|
module DependencyGraph
|
5
5
|
class HasManyDirectives
|
6
|
-
attr_reader :
|
6
|
+
attr_reader :manifest, :directive
|
7
7
|
|
8
|
-
def initialize(
|
9
|
-
@
|
8
|
+
def initialize(manifest, directive)
|
9
|
+
@manifest = manifest
|
10
10
|
@directive = directive
|
11
11
|
end
|
12
12
|
|
13
13
|
def call
|
14
14
|
valid_associations.map do |table, column|
|
15
15
|
TableSaw::DependencyGraph::AddDirective.new(
|
16
|
-
table,
|
16
|
+
table,
|
17
|
+
ids: query_result(table, column).map { |r| r[TableSaw.information_schema.primary_keys[table]] },
|
18
|
+
partial: directive.partial?
|
17
19
|
)
|
18
20
|
end
|
19
21
|
end
|
@@ -21,23 +23,24 @@ module TableSaw
|
|
21
23
|
private
|
22
24
|
|
23
25
|
def associations
|
24
|
-
|
26
|
+
TableSaw.information_schema.has_many.fetch(directive.table_name, [])
|
25
27
|
end
|
26
28
|
|
27
29
|
def valid_associations
|
28
30
|
associations.select do |table, _column|
|
29
|
-
next false if directive.partial? &&
|
31
|
+
next false if directive.partial? && !TableSaw.information_schema.primary_keys.key?(table)
|
30
32
|
|
31
|
-
|
33
|
+
manifest.has_many_mapping.fetch(directive.table_name, []).include?(table)
|
32
34
|
end
|
33
35
|
end
|
34
36
|
|
35
37
|
def query_result(table, column)
|
36
38
|
return [] unless directive.selectable?
|
37
39
|
|
38
|
-
|
39
|
-
format('select
|
40
|
-
|
40
|
+
TableSaw::Connection.exec(
|
41
|
+
format('select %{primary_key} from %{table} where %{column} in (%{ids})',
|
42
|
+
primary_key: TableSaw.information_schema.primary_keys[table], table: table, column: column,
|
43
|
+
ids: directive.ids.join(','))
|
41
44
|
)
|
42
45
|
end
|
43
46
|
end
|
@@ -3,6 +3,5 @@
|
|
3
3
|
require 'table_saw/dependency_graph/add_directive'
|
4
4
|
require 'table_saw/dependency_graph/belongs_to_directives'
|
5
5
|
require 'table_saw/dependency_graph/build'
|
6
|
-
require 'table_saw/dependency_graph/context'
|
7
6
|
require 'table_saw/dependency_graph/dump_table'
|
8
7
|
require 'table_saw/dependency_graph/has_many_directives'
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module TableSaw
|
4
|
+
class InformationSchema
|
5
|
+
def belongs_to
|
6
|
+
foreign_key_relationships.belongs_to
|
7
|
+
end
|
8
|
+
|
9
|
+
# rubocop:disable Naming/PredicateName
|
10
|
+
def has_many
|
11
|
+
foreign_key_relationships.has_many
|
12
|
+
end
|
13
|
+
# rubocop:enable Naming/PredicateName
|
14
|
+
|
15
|
+
def primary_keys
|
16
|
+
@primary_keys ||= TableSaw::Queries::PrimaryKeys.new.call
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def foreign_key_relationships
|
22
|
+
@foreign_key_relationships ||= TableSaw::Queries::ForeignKeyRelationships.new
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
data/lib/table_saw/manifest.rb
CHANGED
@@ -19,18 +19,10 @@ module TableSaw
|
|
19
19
|
alias name table
|
20
20
|
|
21
21
|
def query
|
22
|
-
|
23
|
-
format(config['query'], variables.transform_keys(&:to_sym))
|
24
|
-
else
|
25
|
-
"select id from #{table}"
|
26
|
-
end
|
27
|
-
end
|
22
|
+
return unless partial?
|
28
23
|
|
29
|
-
|
30
|
-
def has_many
|
31
|
-
config.fetch('has_many', [])
|
24
|
+
format(config['query'], variables.transform_keys(&:to_sym))
|
32
25
|
end
|
33
|
-
# rubocop:enable Naming/PredicateName
|
34
26
|
|
35
27
|
def partial?
|
36
28
|
config.key?('query')
|
@@ -58,5 +50,11 @@ module TableSaw
|
|
58
50
|
memo[t.name] = t
|
59
51
|
end
|
60
52
|
end
|
53
|
+
|
54
|
+
# rubocop:disable Naming/PredicateName
|
55
|
+
def has_many_mapping
|
56
|
+
@has_many_mapping ||= config.fetch('has_many', {})
|
57
|
+
end
|
58
|
+
# rubocop:enable Naming/PredicateName
|
61
59
|
end
|
62
60
|
end
|
@@ -3,10 +3,10 @@
|
|
3
3
|
module TableSaw
|
4
4
|
module Queries
|
5
5
|
class MaterializedViews
|
6
|
+
QUERY = 'select matviewname from pg_matviews order by matviewname'
|
7
|
+
|
6
8
|
def call
|
7
|
-
TableSaw::Connection.
|
8
|
-
conn.exec('select matviewname from pg_matviews order by matviewname').map { |row| row['matviewname'] }
|
9
|
-
end
|
9
|
+
TableSaw::Connection.exec(QUERY).map { |row| row['matviewname'] }
|
10
10
|
end
|
11
11
|
end
|
12
12
|
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module TableSaw
|
4
|
+
module Queries
|
5
|
+
class PrimaryKeys
|
6
|
+
QUERY = <<~SQL
|
7
|
+
select tc.table_name, kcu.column_name
|
8
|
+
from information_schema.table_constraints tc
|
9
|
+
join information_schema.key_column_usage kcu using (constraint_schema, constraint_name)
|
10
|
+
where tc.constraint_type = 'PRIMARY KEY';
|
11
|
+
SQL
|
12
|
+
|
13
|
+
def call
|
14
|
+
TableSaw::Connection.exec(QUERY).each_with_object({}) do |row, memo|
|
15
|
+
memo[row['table_name']] = row['column_name']
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -18,10 +18,8 @@ module TableSaw
|
|
18
18
|
SerialSequence = Struct.new(:name, :table, :column)
|
19
19
|
|
20
20
|
def call
|
21
|
-
TableSaw::Connection.
|
22
|
-
|
23
|
-
memo[row['table']] = SerialSequence.new(row['sequence'], row['table'], row['column'])
|
24
|
-
end
|
21
|
+
TableSaw::Connection.exec(QUERY).each_with_object({}) do |row, memo|
|
22
|
+
memo[row['table']] = SerialSequence.new(row['sequence'], row['table'], row['column'])
|
25
23
|
end
|
26
24
|
end
|
27
25
|
end
|
data/lib/table_saw/queries.rb
CHANGED
@@ -2,6 +2,6 @@
|
|
2
2
|
|
3
3
|
require 'table_saw/queries/foreign_key_relationships'
|
4
4
|
require 'table_saw/queries/materialized_views'
|
5
|
-
require 'table_saw/queries/
|
5
|
+
require 'table_saw/queries/primary_keys'
|
6
6
|
require 'table_saw/queries/serial_sequences'
|
7
7
|
require 'table_saw/queries/table_columns'
|
data/lib/table_saw/version.rb
CHANGED
data/lib/table_saw.rb
CHANGED
@@ -3,6 +3,7 @@
|
|
3
3
|
require 'table_saw/configuration'
|
4
4
|
require 'table_saw/connection'
|
5
5
|
require 'table_saw/dependency_graph'
|
6
|
+
require 'table_saw/information_schema'
|
6
7
|
require 'table_saw/manifest'
|
7
8
|
require 'table_saw/queries'
|
8
9
|
|
@@ -20,4 +21,8 @@ module TableSaw
|
|
20
21
|
end
|
21
22
|
end
|
22
23
|
end
|
24
|
+
|
25
|
+
def self.information_schema
|
26
|
+
@information_schema ||= TableSaw::InformationSchema.new
|
27
|
+
end
|
23
28
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: table_saw
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Hamed Asghari
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-
|
11
|
+
date: 2019-07-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: connection_pool
|
@@ -223,14 +223,14 @@ files:
|
|
223
223
|
- lib/table_saw/dependency_graph/add_directive.rb
|
224
224
|
- lib/table_saw/dependency_graph/belongs_to_directives.rb
|
225
225
|
- lib/table_saw/dependency_graph/build.rb
|
226
|
-
- lib/table_saw/dependency_graph/context.rb
|
227
226
|
- lib/table_saw/dependency_graph/dump_table.rb
|
228
227
|
- lib/table_saw/dependency_graph/has_many_directives.rb
|
228
|
+
- lib/table_saw/information_schema.rb
|
229
229
|
- lib/table_saw/manifest.rb
|
230
230
|
- lib/table_saw/queries.rb
|
231
231
|
- lib/table_saw/queries/foreign_key_relationships.rb
|
232
232
|
- lib/table_saw/queries/materialized_views.rb
|
233
|
-
- lib/table_saw/queries/
|
233
|
+
- lib/table_saw/queries/primary_keys.rb
|
234
234
|
- lib/table_saw/queries/serial_sequences.rb
|
235
235
|
- lib/table_saw/queries/table_columns.rb
|
236
236
|
- lib/table_saw/version.rb
|
@@ -1,42 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module TableSaw
|
4
|
-
module DependencyGraph
|
5
|
-
class Context
|
6
|
-
attr_reader :manifest
|
7
|
-
|
8
|
-
def initialize(manifest)
|
9
|
-
@manifest = manifest
|
10
|
-
end
|
11
|
-
|
12
|
-
def belongs_to
|
13
|
-
foreign_key_relationships.belongs_to
|
14
|
-
end
|
15
|
-
|
16
|
-
# rubocop:disable Naming/PredicateName
|
17
|
-
def has_many
|
18
|
-
foreign_key_relationships.has_many
|
19
|
-
end
|
20
|
-
|
21
|
-
def has_many_mapping
|
22
|
-
@has_many_mapping ||= manifest.tables.transform_values(&:has_many)
|
23
|
-
end
|
24
|
-
|
25
|
-
# rubocop:enable Naming/PredicateName
|
26
|
-
|
27
|
-
def foreign_key_relationships
|
28
|
-
@foreign_key_relationships ||= TableSaw::Queries::ForeignKeyRelationships.new
|
29
|
-
end
|
30
|
-
|
31
|
-
def tables_with_no_ids
|
32
|
-
@tables_with_no_ids ||= TableSaw::Queries::NoIdTables.new.call
|
33
|
-
end
|
34
|
-
|
35
|
-
def perform_query(sql)
|
36
|
-
TableSaw::Connection.with do |conn|
|
37
|
-
conn.exec(sql)
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
@@ -1,20 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module TableSaw
|
4
|
-
module Queries
|
5
|
-
class NoIdTables
|
6
|
-
QUERY = <<~SQL
|
7
|
-
select t.table_name
|
8
|
-
from information_schema.tables t left outer join information_schema.table_constraints tc
|
9
|
-
on t.table_name = tc.table_name and tc.constraint_type = 'PRIMARY KEY'
|
10
|
-
where t.table_schema = 'public' and table_type = 'BASE TABLE' and tc.table_name IS NULL
|
11
|
-
SQL
|
12
|
-
|
13
|
-
def call
|
14
|
-
TableSaw::Connection.with do |conn|
|
15
|
-
conn.exec(QUERY)
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|