active_record_sql_exporter 0.2.8 → 0.2.9
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/active_record/sql_exporter.rb +75 -66
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1c44c585e477da643c57579a3ef10570114c0ff4
|
4
|
+
data.tar.gz: fdbba556edb6b9f70379c4713282e5bae63eb122
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c782f7eb0a7173f0a3927f922d9dc2f250278698640ef1f3fcbcf3abe24e03008c7d28f82ed477fee133007cc5f4e4cdfbb50c730fe9f3bc7efdef6b4a690718
|
7
|
+
data.tar.gz: 3b41f151a4084d599b9801ec24961e46c139b988024618b838443f55d4f1848fff28cff681063963a62c4580fb2c88ed93d259e84b41f38c9df0f6cf13b8621a
|
@@ -2,7 +2,7 @@
|
|
2
2
|
module ActiveRecord::SqlExporter
|
3
3
|
class NestedException < ArgumentError
|
4
4
|
attr_accessor :old_exception, :klass
|
5
|
-
def initialize(
|
5
|
+
def initialize(old_exception, klass, key)
|
6
6
|
@old_exception = old_exception
|
7
7
|
@klass = klass
|
8
8
|
@key = key
|
@@ -14,29 +14,35 @@ module ActiveRecord::SqlExporter
|
|
14
14
|
end
|
15
15
|
end
|
16
16
|
# ------------------------------------------------------------------ included?
|
17
|
-
def included?(
|
18
|
-
klass.include(
|
19
|
-
klass.extend(
|
17
|
+
def included?(klass)
|
18
|
+
klass.include(InstanceMethods)
|
19
|
+
klass.extend(ClassMethods)
|
20
|
+
return if klass.respond_to?(:quote_value)
|
21
|
+
class_eval <<-EOC
|
22
|
+
def self.quote_value(*args)
|
23
|
+
connection.quote_value(*args)
|
24
|
+
end
|
25
|
+
EOC
|
20
26
|
end
|
21
27
|
##############################################################################
|
22
28
|
# FileWriter
|
23
29
|
##############################################################################
|
24
30
|
class FileWriter
|
25
31
|
# --------------------------------------------------------------- initialize
|
26
|
-
def initialize(
|
32
|
+
def initialize(file)
|
27
33
|
@file = file
|
28
34
|
end
|
29
35
|
# ------------------------------------------------------------------------ +
|
30
|
-
def +(
|
31
|
-
@file.write(
|
36
|
+
def +(s)
|
37
|
+
@file.write(s)
|
32
38
|
return self
|
33
39
|
end
|
34
40
|
end
|
35
41
|
|
36
42
|
module ClassMethods
|
37
43
|
# ---------------------------------------------------------- build_check_sql
|
38
|
-
def build_check_sql(
|
39
|
-
"IF( NOT EXISTS( SELECT * FROM #{quoted_table_name} WHERE #{connection.quote_column_name(primary_key)} = #{quote_value(id, columns_hash[primary_key])}
|
44
|
+
def build_check_sql(id)
|
45
|
+
"IF( NOT EXISTS( SELECT * FROM #{quoted_table_name} WHERE #{connection.quote_column_name(primary_key)} = #{quote_value(id, columns_hash[primary_key])}) THEN ROLLBACK; END IF;\n"
|
40
46
|
end
|
41
47
|
end
|
42
48
|
|
@@ -44,17 +50,17 @@ module ActiveRecord::SqlExporter
|
|
44
50
|
CREATION_NODE = 1
|
45
51
|
EXISTENCE_CHECK_NODE = 2
|
46
52
|
UPDATE_NODE = 3
|
47
|
-
# --------------------- pretend_to_sql(
|
48
|
-
def print_relation_tree(
|
53
|
+
# --------------------- pretend_to_sql(args = {}, classes_to_ignore = [])
|
54
|
+
def print_relation_tree(args = {}, classes_to_ignore = [])
|
49
55
|
tree = {}
|
50
|
-
_print_relation(
|
51
|
-
return if classes_to_ignore.include?(
|
56
|
+
_print_relation(tree, classes_to_ignore)
|
57
|
+
return if classes_to_ignore.include?(self.class)
|
52
58
|
end
|
53
59
|
# ------------------------------------------------------------------- to_sql
|
54
|
-
def to_backup_sql(
|
60
|
+
def to_backup_sql(args = {}, classes_to_ignore = [])
|
55
61
|
tree = {}
|
56
|
-
build_export_tree(
|
57
|
-
sql = args[:file] ? ActiveRecord::SqlExporter::FileWriter.new(
|
62
|
+
build_export_tree(tree, classes_to_ignore)
|
63
|
+
sql = args[:file] ? ActiveRecord::SqlExporter::FileWriter.new(args[:file]) : ''
|
58
64
|
unless args[:no_transaction]
|
59
65
|
sql += "BEGIN;"
|
60
66
|
end
|
@@ -63,16 +69,16 @@ module ActiveRecord::SqlExporter
|
|
63
69
|
node = tree[klass][id]
|
64
70
|
begin
|
65
71
|
if node[:type] == EXISTENCE_CHECK_NODE
|
66
|
-
sql += klass.constantize.build_check_sql(
|
72
|
+
sql += klass.constantize.build_check_sql(id)
|
67
73
|
elsif node[:type] == CREATION_NODE
|
68
74
|
if id
|
69
|
-
object = klass.constantize.find(
|
75
|
+
object = klass.constantize.find(id)
|
70
76
|
sql += object.sql_restore_string
|
71
77
|
end
|
72
78
|
elsif node[:type] == UPDATE_NODE
|
73
79
|
if id
|
74
|
-
object = klass.constantize.find(
|
75
|
-
sql += object.update_sql_string(
|
80
|
+
object = klass.constantize.find(id)
|
81
|
+
sql += object.update_sql_string(node[:key])
|
76
82
|
end
|
77
83
|
end
|
78
84
|
rescue Encoding::UndefinedConversionError
|
@@ -83,17 +89,20 @@ module ActiveRecord::SqlExporter
|
|
83
89
|
sql += "COMMIT;" unless args[:no_transaction]
|
84
90
|
return sql
|
85
91
|
end
|
86
|
-
|
87
|
-
|
88
|
-
|
92
|
+
##############################################################################
|
93
|
+
|
94
|
+
protected
|
95
|
+
|
96
|
+
##############################################################################
|
89
97
|
# -------------------------------------------------------- update_sql_string
|
90
|
-
def update_sql_string(
|
98
|
+
def update_sql_string(key_name)
|
91
99
|
data = []
|
92
100
|
self.class.columns.map do |x|
|
93
101
|
next if is_primary_key_field?(x)
|
94
|
-
data << "#{self.class.connection.quote_column_name(
|
102
|
+
data << "#{self.class.connection.quote_column_name(x.name)}=#{self.class.connection.quote(read_attribute(x.name))}"
|
95
103
|
end
|
96
|
-
|
104
|
+
quoted_id = self.class.quote_value(id, self.class.columns_hash[self.class.primary_key])
|
105
|
+
"UPDATE #{self.class.quoted_table_name} SET #{data.join(',')} WHERE #{self.class.connection.quote_column_name(self.class.primary_key)} = #{quoted_id};\n"
|
97
106
|
end
|
98
107
|
|
99
108
|
def is_primary_key_field?(col)
|
@@ -101,12 +110,12 @@ module ActiveRecord::SqlExporter
|
|
101
110
|
end
|
102
111
|
|
103
112
|
# ------------------------------------------------------- sql_restore_string
|
104
|
-
def sql_restore_string(
|
113
|
+
def sql_restore_string(args = {})
|
105
114
|
columns = self.class.columns.map do |x|
|
106
|
-
self.class.connection.quote_column_name(
|
115
|
+
self.class.connection.quote_column_name(x.name)
|
107
116
|
end
|
108
117
|
values = self.class.columns.map do |x|
|
109
|
-
self.class.connection.quote(
|
118
|
+
self.class.connection.quote(read_attribute(x.name))
|
110
119
|
end
|
111
120
|
|
112
121
|
sql = "\nINSERT INTO #{self.class.quoted_table_name} (#{columns.join(',')}) VALUES (#{values.join(',')})"
|
@@ -121,16 +130,16 @@ module ActiveRecord::SqlExporter
|
|
121
130
|
return sql
|
122
131
|
end
|
123
132
|
# -------------------------------------------------------- build_export_tree
|
124
|
-
def build_export_tree(
|
125
|
-
return if classes_to_ignore.include?(
|
126
|
-
if tree[self.class.name].nil? || (
|
127
|
-
self.add_to_tree(
|
128
|
-
expand_tree_with_relations(
|
133
|
+
def build_export_tree(tree = {}, classes_to_ignore = [])
|
134
|
+
return if classes_to_ignore.include?(self.class)
|
135
|
+
if tree[self.class.name].nil? || (tree[self.class.name] && (tree[self.class.name][id].nil? || tree[self.class.name][id][:type] == EXISTENCE_CHECK_NODE))
|
136
|
+
self.add_to_tree(tree, CREATION_NODE)
|
137
|
+
expand_tree_with_relations(tree, self.class.reflections, classes_to_ignore)
|
129
138
|
end
|
130
139
|
return tree
|
131
140
|
end
|
132
141
|
# ------------------------------------------------------------- add_to_tree
|
133
|
-
def add_to_tree(
|
142
|
+
def add_to_tree(tree, type, options = {})
|
134
143
|
tree[self.class.name] ||= {}
|
135
144
|
node = tree[self.class.name][self.id]
|
136
145
|
if node.nil? || node[:type] == EXISTENCE_CHECK_NODE
|
@@ -141,17 +150,17 @@ module ActiveRecord::SqlExporter
|
|
141
150
|
end
|
142
151
|
# ---------------------------------------------------------- build_check_sql
|
143
152
|
def build_check_sql
|
144
|
-
"IF( NOT EXISTS( SELECT * FROM #{self.class.quoted_table_name} WHERE #{self.class.connection.quote_column_name(self.class.primary_key)} = #{quote_value(id)}
|
153
|
+
"IF( NOT EXISTS( SELECT * FROM #{self.class.quoted_table_name} WHERE #{self.class.connection.quote_column_name(self.class.primary_key)} = #{quote_value(id)}) THEN ROLLBACK; END IF;\n"
|
145
154
|
end
|
146
155
|
# ---------------------------------------- convert_has_many_relations_to_sql
|
147
|
-
def expand_tree_with_relations(
|
156
|
+
def expand_tree_with_relations(tree, reflections, classes_to_ignore)
|
148
157
|
reflections.each_pair do |key, value|
|
149
|
-
next if value.options[:dependent] && ![:destroy, :nullify].include?(
|
158
|
+
next if value.options[:dependent] && ![:destroy, :nullify].include?(value.options[:dependent])
|
150
159
|
if value.options[:polymorphic]
|
151
|
-
next if classes_to_ignore.include?(
|
160
|
+
next if classes_to_ignore.include?(send(key).class)
|
152
161
|
else
|
153
162
|
begin
|
154
|
-
next if classes_to_ignore.include?(
|
163
|
+
next if classes_to_ignore.include?(value.klass)
|
155
164
|
rescue
|
156
165
|
raise "Problem in a #{self.class.name} with #{key} = #{value}"
|
157
166
|
end
|
@@ -159,33 +168,33 @@ module ActiveRecord::SqlExporter
|
|
159
168
|
case value.macro
|
160
169
|
when :has_one
|
161
170
|
begin
|
162
|
-
singleton_method(
|
163
|
-
e.build_export_tree(
|
171
|
+
singleton_method(key) do |e|
|
172
|
+
e.build_export_tree(tree, classes_to_ignore)
|
164
173
|
end
|
165
174
|
rescue NestedException => ex
|
166
|
-
raise NestedException.new(
|
175
|
+
raise NestedException.new(ex.old_exception, "#{self.class.name}.#{ex.klass}", key)
|
167
176
|
rescue Exception => ex
|
168
|
-
raise NestedException.new(
|
177
|
+
raise NestedException.new(ex, self.class.name, key)
|
169
178
|
end
|
170
179
|
when :has_many, :has_and_belongs_to_many
|
171
180
|
begin
|
172
|
-
records = send(
|
181
|
+
records = send(key)
|
173
182
|
if value.options[:dependent] == :nullify
|
174
183
|
records.each do |record|
|
175
|
-
record.add_to_tree(
|
184
|
+
record.add_to_tree(tree, UPDATE_NODE, key: value.association_primary_key)
|
176
185
|
end
|
177
186
|
else
|
178
|
-
records.each{ |x| x.build_export_tree(
|
187
|
+
records.each{ |x| x.build_export_tree(tree, classes_to_ignore) }
|
179
188
|
end
|
180
189
|
rescue NestedException => ex
|
181
|
-
raise NestedException.new(
|
190
|
+
raise NestedException.new(ex.old_exception, "#{self.class.name}.#{ex.klass}", key)
|
182
191
|
rescue Exception => ex
|
183
192
|
raise ex
|
184
|
-
raise NestedException.new(
|
193
|
+
raise NestedException.new(ex, self.class.name, key)
|
185
194
|
end
|
186
195
|
when :belongs_to
|
187
|
-
singleton_method(
|
188
|
-
e.add_to_tree(
|
196
|
+
singleton_method(key) do |e|
|
197
|
+
e.add_to_tree(tree, EXISTENCE_CHECK_NODE)
|
189
198
|
end
|
190
199
|
else
|
191
200
|
raise "Unhandled reflection: #{value.macro}"
|
@@ -194,41 +203,41 @@ module ActiveRecord::SqlExporter
|
|
194
203
|
return tree
|
195
204
|
end
|
196
205
|
# ----------------------------------------------------------- print_relation
|
197
|
-
def _print_relation(
|
198
|
-
if tree[self.class.name].nil? || (
|
206
|
+
def _print_relation(tree, classes_to_ignore, indent_depth = 0)
|
207
|
+
if tree[self.class.name].nil? || (tree[self.class.name] && (tree[self.class.name][id].nil? || tree[self.class.name][id][:type] == EXISTENCE_CHECK_NODE))
|
199
208
|
puts "%s%s - %d" % ["\t" * indent_depth, self.class.name, self.id]
|
200
|
-
self.add_to_tree(
|
201
|
-
_print_reflection_relations(
|
209
|
+
self.add_to_tree(tree, CREATION_NODE)
|
210
|
+
_print_reflection_relations(tree, self.class.reflections, classes_to_ignore, indent_depth + 1)
|
202
211
|
end
|
203
212
|
end
|
204
213
|
# ---------------------------------------- convert_has_many_relations_to_sql
|
205
|
-
def _print_reflection_relations(
|
214
|
+
def _print_reflection_relations(tree, reflections, classes_to_ignore, indent_level = 1)
|
206
215
|
reflections.each_pair do |key, value|
|
207
|
-
next if value.options[:dependent] && ![:destroy, :nullify].include?(
|
216
|
+
next if value.options[:dependent] && ![:destroy, :nullify].include?(value.options[:dependent])
|
208
217
|
if value.options[:polymorphic]
|
209
|
-
next if classes_to_ignore.include?(
|
218
|
+
next if classes_to_ignore.include?(send(key).class)
|
210
219
|
else
|
211
220
|
begin
|
212
|
-
next if classes_to_ignore.include?(
|
221
|
+
next if classes_to_ignore.include?(value.klass)
|
213
222
|
rescue
|
214
223
|
raise "Problem in a #{self.class.name} with #{key} = #{value}"
|
215
224
|
end
|
216
225
|
end
|
217
226
|
case value.macro
|
218
227
|
when :has_one
|
219
|
-
singleton_method(
|
220
|
-
e._print_relation(
|
228
|
+
singleton_method(key) do |e|
|
229
|
+
e._print_relation(tree, classes_to_ignore, indent_level)
|
221
230
|
end
|
222
231
|
when :has_many, :has_and_belongs_to_many
|
223
|
-
records = send(
|
232
|
+
records = send(key)
|
224
233
|
if value.options[:dependent] == :nullify
|
225
234
|
records.each do |record|
|
226
|
-
record.add_to_tree(
|
235
|
+
record.add_to_tree(tree, UPDATE_NODE, key: value.primary_key_name)
|
227
236
|
puts "%s%s [UPDATE] - %d" % ["\t" * indent_level, record.class.name, record.id]
|
228
237
|
end
|
229
238
|
else
|
230
239
|
records.each do |x|
|
231
|
-
x._print_relation(
|
240
|
+
x._print_relation(tree, classes_to_ignore, indent_level)
|
232
241
|
end
|
233
242
|
end
|
234
243
|
when :belongs_to
|
@@ -238,8 +247,8 @@ module ActiveRecord::SqlExporter
|
|
238
247
|
end
|
239
248
|
end
|
240
249
|
# --------------------------------------------------------- singleton_method
|
241
|
-
def singleton_method(
|
242
|
-
if v = self.send(
|
250
|
+
def singleton_method(key)
|
251
|
+
if v = self.send(key)
|
243
252
|
yield v
|
244
253
|
end
|
245
254
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: active_record_sql_exporter
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.9
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Adam Palmblad
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2018-01-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|