real_data_tests 0.3.14 → 0.3.15
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/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
|