real_data_tests 0.3.14 → 0.3.15
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/real_data_tests/rspec_helper.rb +110 -49
- data/lib/real_data_tests/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9b6d2be28f1fa0fc3982e0d8bb4927ea8f25eb1701d0c77059ec6a4059cb33ee
|
4
|
+
data.tar.gz: 19f5865fbb86760845c079a5b46ba49231533a33a91596e2b7c73438ca3941eb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6d68fbb46440b6950ec57363bbd995ea64503c41c9c66955ad1ad28b9338f51798a7aad945238e0a61c7654651a365b80056b3108e4dff1d2486b5c77cfad91c
|
7
|
+
data.tar.gz: e82c24d4082fb0d5e4e56e6de6cfd0e7130029057f2fa993e4f9bffdc2c5583bde94ee7c224535890f7e74ae01d8dd08ad670e2daef20041d572bf9845955fe8
|
@@ -1,5 +1,38 @@
|
|
1
1
|
module RealDataTests
|
2
2
|
module RSpecHelper
|
3
|
+
class SqlBlock
|
4
|
+
attr_reader :type, :content, :table_name
|
5
|
+
|
6
|
+
def initialize(content)
|
7
|
+
@content = content.strip
|
8
|
+
@type = determine_block_type
|
9
|
+
@table_name = extract_table_name if @type == :insert
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def determine_block_type
|
15
|
+
case @content
|
16
|
+
when /\AINSERT INTO/i
|
17
|
+
:insert
|
18
|
+
when /\ACOPY.*FROM stdin/i
|
19
|
+
:copy
|
20
|
+
when /\AALTER TABLE/i
|
21
|
+
:alter
|
22
|
+
when /\ASET/i
|
23
|
+
:set
|
24
|
+
else
|
25
|
+
:other
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def extract_table_name
|
30
|
+
if @content =~ /INSERT INTO\s+"?([^\s"(]+)"?\s/i
|
31
|
+
$1
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
3
36
|
def load_real_test_data(name)
|
4
37
|
dump_path = File.join(RealDataTests.configuration.dump_path, "#{name}.sql")
|
5
38
|
raise Error, "Test data file not found: #{dump_path}" unless File.exist?(dump_path)
|
@@ -17,11 +50,13 @@ module RealDataTests
|
|
17
50
|
end
|
18
51
|
end
|
19
52
|
|
20
|
-
# Native Ruby implementation
|
21
53
|
def load_real_test_data_native(name)
|
22
54
|
dump_path = File.join(RealDataTests.configuration.dump_path, "#{name}.sql")
|
23
55
|
raise Error, "Test data file not found: #{dump_path}" unless File.exist?(dump_path)
|
24
56
|
|
57
|
+
sql_content = File.read(dump_path)
|
58
|
+
blocks = parse_sql_blocks(sql_content)
|
59
|
+
|
25
60
|
ActiveRecord::Base.transaction do
|
26
61
|
connection = ActiveRecord::Base.connection
|
27
62
|
|
@@ -29,17 +64,8 @@ module RealDataTests
|
|
29
64
|
connection.execute('SET session_replication_role = replica;')
|
30
65
|
|
31
66
|
begin
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
statements.each_with_index do |statement, index|
|
36
|
-
begin
|
37
|
-
cleaned_statement = clean_sql_statement(statement)
|
38
|
-
puts "Executing Statement ##{index + 1}: #{cleaned_statement}" # Debug log
|
39
|
-
connection.execute(cleaned_statement)
|
40
|
-
rescue ActiveRecord::StatementInvalid => e
|
41
|
-
raise Error, "Error executing statement ##{index + 1}: #{e.message}\nSQL: #{cleaned_statement}"
|
42
|
-
end
|
67
|
+
blocks.each_with_index do |block, index|
|
68
|
+
execute_block(block, index + 1, blocks.length)
|
43
69
|
end
|
44
70
|
ensure
|
45
71
|
connection.execute('SET session_replication_role = DEFAULT;')
|
@@ -64,6 +90,78 @@ module RealDataTests
|
|
64
90
|
options.join(" ")
|
65
91
|
end
|
66
92
|
|
93
|
+
def parse_sql_blocks(content)
|
94
|
+
blocks = []
|
95
|
+
current_block = []
|
96
|
+
in_copy_block = false
|
97
|
+
|
98
|
+
content.each_line do |line|
|
99
|
+
line = line.strip
|
100
|
+
next if line.empty? || line.start_with?('--')
|
101
|
+
|
102
|
+
if line.upcase.start_with?('COPY') && line.upcase.include?('FROM stdin')
|
103
|
+
in_copy_block = true
|
104
|
+
current_block << line
|
105
|
+
elsif line == '\.' && in_copy_block
|
106
|
+
in_copy_block = false
|
107
|
+
current_block << line
|
108
|
+
blocks << SqlBlock.new(current_block.join("\n"))
|
109
|
+
current_block = []
|
110
|
+
elsif in_copy_block
|
111
|
+
current_block << line
|
112
|
+
else
|
113
|
+
# Handle regular SQL statements
|
114
|
+
current_block << line
|
115
|
+
if line.end_with?(';') && !in_copy_block
|
116
|
+
blocks << SqlBlock.new(current_block.join("\n"))
|
117
|
+
current_block = []
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
# Add any remaining block
|
123
|
+
blocks << SqlBlock.new(current_block.join("\n")) unless current_block.empty?
|
124
|
+
blocks
|
125
|
+
end
|
126
|
+
|
127
|
+
def execute_block(block, index, total)
|
128
|
+
case block.type
|
129
|
+
when :insert
|
130
|
+
execute_insert_block(block, index, total)
|
131
|
+
when :copy
|
132
|
+
execute_copy_block(block, index, total)
|
133
|
+
else
|
134
|
+
execute_regular_block(block, index, total)
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
def execute_insert_block(block, index, total)
|
139
|
+
puts "Executing INSERT block #{index}/#{total} for table: #{block.table_name}"
|
140
|
+
statement = normalize_insert_statement(block.content)
|
141
|
+
ActiveRecord::Base.connection.execute(statement)
|
142
|
+
end
|
143
|
+
|
144
|
+
def execute_copy_block(block, index, total)
|
145
|
+
puts "Executing COPY block #{index}/#{total}"
|
146
|
+
ActiveRecord::Base.connection.execute(block.content)
|
147
|
+
end
|
148
|
+
|
149
|
+
def execute_regular_block(block, index, total)
|
150
|
+
puts "Executing block #{index}/#{total} of type: #{block.type}"
|
151
|
+
ActiveRecord::Base.connection.execute(block.content)
|
152
|
+
end
|
153
|
+
|
154
|
+
def normalize_insert_statement(statement)
|
155
|
+
# Handle ON CONFLICT clauses properly
|
156
|
+
if statement =~ /(.*?)\s+(ON\s+CONFLICT.*?)\s*;\s*\z/i
|
157
|
+
main_insert = $1
|
158
|
+
conflict_clause = $2
|
159
|
+
"#{main_insert} #{conflict_clause};"
|
160
|
+
else
|
161
|
+
statement
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
67
165
|
def split_sql_statements(sql)
|
68
166
|
statements = []
|
69
167
|
current_statement = ''
|
@@ -206,41 +304,4 @@ module RealDataTests
|
|
206
304
|
end
|
207
305
|
end
|
208
306
|
end
|
209
|
-
|
210
|
-
def import
|
211
|
-
@logger.info "Starting SQL import..."
|
212
|
-
|
213
|
-
ActiveRecord::Base.transaction do
|
214
|
-
begin
|
215
|
-
# Disable foreign key checks and triggers temporarily
|
216
|
-
ActiveRecord::Base.connection.execute('SET session_replication_role = replica;')
|
217
|
-
|
218
|
-
# Split the SQL content into individual statements
|
219
|
-
statements = split_sql_statements(@sql_content)
|
220
|
-
|
221
|
-
statements.each_with_index do |statement, index|
|
222
|
-
next if statement.strip.empty?
|
223
|
-
|
224
|
-
begin
|
225
|
-
@logger.info "Executing statement #{index + 1} of #{statements.length}"
|
226
|
-
cleaned_statement = clean_sql_statement(statement)
|
227
|
-
ActiveRecord::Base.connection.execute(cleaned_statement)
|
228
|
-
rescue ActiveRecord::StatementInvalid => e
|
229
|
-
@logger.error "Error executing statement #{index + 1}: #{e.message}"
|
230
|
-
@logger.error "Statement: #{cleaned_statement[0..100]}..."
|
231
|
-
raise
|
232
|
-
end
|
233
|
-
end
|
234
|
-
|
235
|
-
@logger.info "Successfully imported all SQL statements"
|
236
|
-
rescue StandardError => e
|
237
|
-
@logger.error "Error during import: #{e.message}"
|
238
|
-
@logger.error e.backtrace.join("\n")
|
239
|
-
raise
|
240
|
-
ensure
|
241
|
-
# Re-enable foreign key checks and triggers
|
242
|
-
ActiveRecord::Base.connection.execute('SET session_replication_role = DEFAULT;')
|
243
|
-
end
|
244
|
-
end
|
245
|
-
end
|
246
307
|
end
|