real_data_tests 0.3.15 → 0.3.16
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 +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
|
|