real_data_tests 0.3.15 → 0.3.16
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 +91 -22
- 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: fbf98b8c1c4b72e614a490731c40ff4f56c36eb14b4b13cf19fc13b7c3022fe3
|
4
|
+
data.tar.gz: '029a17e72f0a42f34eae153cbf4a212e185100027e438b8a9e48efb112b7e349'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 854233f093058fe510b0c37409a6a4c3445a2c65a70dc9c862d3a8eaec12a535ba435b354a5348b8e4f41bf15291caacabcb1d9b4274b506f02d1baeec97e2b0
|
7
|
+
data.tar.gz: ce700cb666714010f2622307da5321fac568eb32afbaf6795121d855e6e47409047192a0c38d3b0ed1f3b8e82d109988135c7c8b6a6cfb63c6e8e274c79a686e
|
@@ -90,36 +90,80 @@ module RealDataTests
|
|
90
90
|
options.join(" ")
|
91
91
|
end
|
92
92
|
|
93
|
+
class SqlBlock
|
94
|
+
attr_reader :type, :content, :table_name
|
95
|
+
|
96
|
+
def initialize(content)
|
97
|
+
@content = content.strip
|
98
|
+
@type = determine_block_type
|
99
|
+
@table_name = extract_table_name if @type == :insert
|
100
|
+
end
|
101
|
+
|
102
|
+
private
|
103
|
+
|
104
|
+
def determine_block_type
|
105
|
+
if @content.match?(/\AINSERT INTO/i)
|
106
|
+
:insert
|
107
|
+
elsif @content.match?(/\ACOPY.*FROM stdin/i)
|
108
|
+
:copy
|
109
|
+
elsif @content.match?(/\AALTER TABLE/i)
|
110
|
+
:alter
|
111
|
+
elsif @content.match?(/\ASET/i)
|
112
|
+
:set
|
113
|
+
else
|
114
|
+
:other
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
def extract_table_name
|
119
|
+
if @content =~ /INSERT INTO\s+"?([^\s"(]+)"?\s/i
|
120
|
+
$1
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
93
125
|
def parse_sql_blocks(content)
|
94
126
|
blocks = []
|
95
127
|
current_block = []
|
96
128
|
in_copy_block = false
|
97
129
|
|
98
130
|
content.each_line do |line|
|
99
|
-
line = line.
|
100
|
-
|
131
|
+
line = line.chomp
|
132
|
+
|
133
|
+
# Skip empty lines and comments unless in COPY block
|
134
|
+
next if !in_copy_block && (line.empty? || line.start_with?('--'))
|
101
135
|
|
102
|
-
|
136
|
+
# Handle start of COPY block
|
137
|
+
if !in_copy_block && line.upcase.match?(/\ACOPY.*FROM stdin/i)
|
138
|
+
current_block = [line]
|
103
139
|
in_copy_block = true
|
140
|
+
next
|
141
|
+
end
|
142
|
+
|
143
|
+
# Handle end of COPY block
|
144
|
+
if in_copy_block && line == '\\.'
|
104
145
|
current_block << line
|
105
|
-
|
146
|
+
blocks << SqlBlock.new(current_block.join("\n"))
|
147
|
+
current_block = []
|
106
148
|
in_copy_block = false
|
149
|
+
next
|
150
|
+
end
|
151
|
+
|
152
|
+
# Accumulate lines in COPY block
|
153
|
+
if in_copy_block
|
107
154
|
current_block << line
|
155
|
+
next
|
156
|
+
end
|
157
|
+
|
158
|
+
# Handle regular SQL statements
|
159
|
+
current_block << line
|
160
|
+
if line.end_with?(';')
|
108
161
|
blocks << SqlBlock.new(current_block.join("\n"))
|
109
162
|
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
163
|
end
|
120
164
|
end
|
121
165
|
|
122
|
-
#
|
166
|
+
# Handle any remaining block
|
123
167
|
blocks << SqlBlock.new(current_block.join("\n")) unless current_block.empty?
|
124
168
|
blocks
|
125
169
|
end
|
@@ -137,8 +181,24 @@ module RealDataTests
|
|
137
181
|
|
138
182
|
def execute_insert_block(block, index, total)
|
139
183
|
puts "Executing INSERT block #{index}/#{total} for table: #{block.table_name}"
|
140
|
-
|
141
|
-
|
184
|
+
# Don't modify statements that already end with semicolon
|
185
|
+
statement = if block.content.strip.end_with?(';')
|
186
|
+
block.content
|
187
|
+
else
|
188
|
+
"#{block.content};"
|
189
|
+
end
|
190
|
+
|
191
|
+
begin
|
192
|
+
ActiveRecord::Base.connection.execute(statement)
|
193
|
+
rescue ActiveRecord::StatementInvalid => e
|
194
|
+
if e.message.include?('syntax error at or near "ON"')
|
195
|
+
# Try alternative formatting for ON CONFLICT
|
196
|
+
modified_statement = statement.gsub(/\)\s+ON\s+CONFLICT/, ') ON CONFLICT')
|
197
|
+
ActiveRecord::Base.connection.execute(modified_statement)
|
198
|
+
else
|
199
|
+
raise
|
200
|
+
end
|
201
|
+
end
|
142
202
|
end
|
143
203
|
|
144
204
|
def execute_copy_block(block, index, total)
|
@@ -152,13 +212,22 @@ module RealDataTests
|
|
152
212
|
end
|
153
213
|
|
154
214
|
def normalize_insert_statement(statement)
|
155
|
-
#
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
215
|
+
# First clean up any excess whitespace around parentheses
|
216
|
+
statement = statement.gsub(/\(\s+/, '(')
|
217
|
+
.gsub(/\s+\)/, ')')
|
218
|
+
.gsub(/\)\s+ON\s+CONFLICT/, ') ON CONFLICT')
|
219
|
+
|
220
|
+
# Ensure proper spacing around ON CONFLICT
|
221
|
+
if statement =~ /(.*?)\s*ON\s+CONFLICT\s+(.*?)\s*(?:DO\s+.*?)?\s*;\s*\z/i
|
222
|
+
base = $1.strip
|
223
|
+
conflict_part = $2.strip
|
224
|
+
action_part = $3&.strip || 'DO NOTHING'
|
225
|
+
|
226
|
+
# Rebuild the statement with consistent formatting
|
227
|
+
"#{base} ON CONFLICT #{conflict_part} #{action_part};"
|
160
228
|
else
|
161
|
-
|
229
|
+
# If no ON CONFLICT clause, just clean up the spacing
|
230
|
+
statement.strip.sub(/;?\s*$/, ';')
|
162
231
|
end
|
163
232
|
end
|
164
233
|
|