pgsync 0.5.2 → 0.6.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of pgsync might be problematic. Click here for more details.

@@ -1,46 +1,86 @@
1
1
  module PgSync
2
2
  module Utils
3
+ COLOR_CODES = {
4
+ red: 31,
5
+ green: 32,
6
+ yellow: 33
7
+ }
8
+
3
9
  def log(message = nil)
4
- $stderr.puts message
10
+ output.puts message
5
11
  end
6
12
 
7
- def colorize(message, color_code)
8
- if $stderr.tty?
9
- "\e[#{color_code}m#{message}\e[0m"
13
+ def colorize(message, color)
14
+ if output.tty?
15
+ "\e[#{COLOR_CODES[color]}m#{message}\e[0m"
10
16
  else
11
17
  message
12
18
  end
13
19
  end
14
20
 
15
- def config_file
16
- return @config_file if instance_variable_defined?(:@config_file)
21
+ def warning(message)
22
+ log colorize(message, :yellow)
23
+ end
24
+
25
+ def deprecated(message)
26
+ warning "[DEPRECATED] #{message}"
27
+ end
17
28
 
18
- @config_file =
19
- search_tree(
20
- if @options[:db]
21
- db_config_file(@options[:db])
22
- else
23
- @options[:config] || ".pgsync.yml"
24
- end
25
- )
29
+ def output
30
+ $stderr
26
31
  end
27
32
 
28
33
  def db_config_file(db)
29
- return unless db
30
34
  ".pgsync-#{db}.yml"
31
35
  end
32
36
 
33
- def search_tree(file)
34
- path = Dir.pwd
35
- # prevent infinite loop
36
- 20.times do
37
- absolute_file = File.join(path, file)
38
- if File.exist?(absolute_file)
39
- break absolute_file
37
+ def confirm_tables_exist(data_source, tasks, description)
38
+ tasks.map(&:table).each do |table|
39
+ unless data_source.table_exists?(table)
40
+ raise Error, "Table not found in #{description}: #{table}"
40
41
  end
41
- path = File.dirname(path)
42
- break if path == "/"
43
42
  end
44
43
  end
44
+
45
+ def first_schema
46
+ @first_schema ||= source.search_path.find { |sp| sp != "pg_catalog" }
47
+ end
48
+
49
+ def task_name(task)
50
+ friendly_name(task.table)
51
+ end
52
+
53
+ def friendly_name(table)
54
+ if table.schema == first_schema
55
+ table.name
56
+ else
57
+ table.full_name
58
+ end
59
+ end
60
+
61
+ def quote_ident_full(ident)
62
+ if ident.is_a?(Table)
63
+ [quote_ident(ident.schema), quote_ident(ident.name)].join(".")
64
+ else # temp table names are strings
65
+ quote_ident(ident)
66
+ end
67
+ end
68
+
69
+ def quote_ident(value)
70
+ PG::Connection.quote_ident(value)
71
+ end
72
+
73
+ def escape(value)
74
+ if value.is_a?(String)
75
+ "'#{quote_string(value)}'"
76
+ else
77
+ value
78
+ end
79
+ end
80
+
81
+ # activerecord
82
+ def quote_string(s)
83
+ s.gsub(/\\/, '\&\&').gsub(/'/, "''")
84
+ end
45
85
  end
46
86
  end
@@ -1,3 +1,3 @@
1
1
  module PgSync
2
- VERSION = "0.5.2"
2
+ VERSION = "0.6.1"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pgsync
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.2
4
+ version: 0.6.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Kane
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-03-28 00:00:00.000000000 Z
11
+ date: 2020-06-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: parallel
@@ -44,14 +44,14 @@ dependencies:
44
44
  requirements:
45
45
  - - ">="
46
46
  - !ruby/object:Gem::Version
47
- version: 4.2.0
47
+ version: 4.8.1
48
48
  type: :runtime
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: 4.2.0
54
+ version: 4.8.1
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: tty-spinner
57
57
  requirement: !ruby/object:Gem::Requirement
@@ -124,9 +124,12 @@ files:
124
124
  - lib/pgsync/client.rb
125
125
  - lib/pgsync/data_source.rb
126
126
  - lib/pgsync/init.rb
127
+ - lib/pgsync/schema_sync.rb
127
128
  - lib/pgsync/sync.rb
128
- - lib/pgsync/table_list.rb
129
+ - lib/pgsync/table.rb
129
130
  - lib/pgsync/table_sync.rb
131
+ - lib/pgsync/task.rb
132
+ - lib/pgsync/task_resolver.rb
130
133
  - lib/pgsync/utils.rb
131
134
  - lib/pgsync/version.rb
132
135
  homepage: https://github.com/ankane/pgsync
@@ -1,143 +0,0 @@
1
- module PgSync
2
- class TableList
3
- include Utils
4
-
5
- attr_reader :args, :opts, :source, :config
6
-
7
- def initialize(args, options, source, config)
8
- @args = args
9
- @opts = options
10
- @source = source
11
- @config = config
12
- end
13
-
14
- def tables
15
- tables = nil
16
-
17
- if opts[:groups]
18
- tables ||= Hash.new { |hash, key| hash[key] = {} }
19
- specified_groups = to_arr(opts[:groups])
20
- specified_groups.map do |tag|
21
- group, id = tag.split(":", 2)
22
- if (t = (config["groups"] || {})[group])
23
- add_tables(tables, t, id, args[1])
24
- else
25
- raise Error, "Group not found: #{group}"
26
- end
27
- end
28
- end
29
-
30
- if opts[:tables]
31
- tables ||= Hash.new { |hash, key| hash[key] = {} }
32
- to_arr(opts[:tables]).each do |tag|
33
- table, id = tag.split(":", 2)
34
- raise Error, "Cannot use parameters with tables" if id
35
- add_table(tables, table, id, args[1])
36
- end
37
- end
38
-
39
- if args[0]
40
- # could be a group, table, or mix
41
- tables ||= Hash.new { |hash, key| hash[key] = {} }
42
- specified_groups = to_arr(args[0])
43
- specified_groups.map do |tag|
44
- group, id = tag.split(":", 2)
45
- if (t = (config["groups"] || {})[group])
46
- add_tables(tables, t, id, args[1])
47
- else
48
- raise Error, "Cannot use parameters with tables" if id
49
- add_table(tables, group, id, args[1])
50
- end
51
- end
52
- end
53
-
54
- tables ||= begin
55
- exclude = to_arr(opts[:exclude])
56
- exclude = source.fully_resolve_tables(exclude).keys if exclude.any?
57
-
58
- tabs = source.tables
59
- unless opts[:all_schemas]
60
- schemas = Set.new(opts[:schemas] ? to_arr(opts[:schemas]) : source.search_path)
61
- tabs.select! { |t| schemas.include?(t.split(".", 2)[0]) }
62
- end
63
-
64
- Hash[(tabs - exclude).map { |k| [k, {}] }]
65
- end
66
-
67
- source.fully_resolve_tables(tables)
68
- end
69
-
70
- private
71
-
72
- def to_arr(value)
73
- if value.is_a?(Array)
74
- value
75
- else
76
- # Split by commas, but don't use commas inside double quotes
77
- # https://stackoverflow.com/questions/21105360/regex-find-comma-not-inside-quotes
78
- value.to_s.split(/(?!\B"[^"]*),(?![^"]*"\B)/)
79
- end
80
- end
81
-
82
- def add_tables(tables, t, id, boom)
83
- # if id
84
- # # TODO show group name and value
85
- # log colorize("`pgsync group:value` is deprecated and will have a different function in 0.6.0.", 33) # yellow
86
- # log colorize("Use `pgsync group --var 1=value` instead.", 33) # yellow
87
- # end
88
-
89
- t.each do |table|
90
- sql = nil
91
- if table.is_a?(Array)
92
- table, sql = table
93
- end
94
- add_table(tables, table, id, boom || sql)
95
- end
96
- end
97
-
98
- def add_table(tables, table, id, boom, wildcard = false)
99
- if table.include?("*") && !wildcard
100
- regex = Regexp.new('\A' + Regexp.escape(table).gsub('\*','[^\.]*') + '\z')
101
- t2 = source.tables.select { |t| regex.match(t) }
102
- t2.each do |tab|
103
- add_table(tables, tab, id, boom, true)
104
- end
105
- else
106
- tables[table] = {}
107
- if boom
108
- sql = boom.dup
109
- # vars must match \w
110
- missing_vars = sql.scan(/{\w+}/).map { |v| v[1..-2] }
111
-
112
- vars = {}
113
-
114
- # legacy
115
- if id
116
- vars["id"] = cast(id)
117
- vars["1"] = cast(id)
118
- end
119
-
120
- # opts[:var].each do |value|
121
- # k, v = value.split("=", 2)
122
- # vars[k] = v
123
- # end
124
-
125
- sql = boom.dup
126
- vars.each do |k, v|
127
- # only sub if in var list
128
- sql.gsub!("{#{k}}", cast(v)) if missing_vars.delete(k)
129
- end
130
-
131
- raise Error, "Missing variables: #{missing_vars.uniq.join(", ")}" if missing_vars.any?
132
-
133
- tables[table][:sql] = sql
134
- end
135
- end
136
- end
137
-
138
- # TODO quote vars in next major version
139
- def cast(value)
140
- value.to_s.gsub(/\A\"|\"\z/, '')
141
- end
142
- end
143
- end