table_saw 0.5.0 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|