real_data_tests 0.3.6 → 0.3.8

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 179a591f6a485c397255c0cbec27e18757e2f7fdc450f7292f279cd681f91e0b
4
- data.tar.gz: bb9b9f4f60b609f2ea8a901689b4b9b8d5ddfdc7d36e867c18ebbe24855cb5aa
3
+ metadata.gz: 573f1753777e04a6168a09385b8332cedbb4d521d11f1807012a25b8b846013c
4
+ data.tar.gz: b884098abbc9134a22479d5e9211a2d8bb153622022ba9116acb0057419cbe4a
5
5
  SHA512:
6
- metadata.gz: a47d49d690958e70cd324ede48dadce7d3e9e7bd39471ee052879d6fe5646ad308aebbf05f79cb92ebe3c9b7ede94b0163c74efdddf3f518ef47518a489a2ee6
7
- data.tar.gz: a4c6a97cff1bd02096064fd1da67580dd9307ce29f4e7d5a8be4d82c9f352b97009ef1fc22eb555dc39b1b87599947680a61bc2bc376c2cd14a7f8cc5397892d
6
+ metadata.gz: 1d4bcb84f7d3ab3ee0901ae46763c912f3c86935930cc17607d500ae7a2e26649f8c6ff629e8215437d8f08ae93d482870e253b294e84e720971c9bf681c7b50
7
+ data.tar.gz: 67cad3bda841d3e1de61d61dd30121ef3b6ddfc96a3162438a2b25f904185e6e4c59206d2626e6b40d44a72d123ed123e4073a4fdfe10d04fea807a8702bf689
data/CHANGELOG.md CHANGED
@@ -1,5 +1,21 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [0.3.8] - 2025-01-14
4
+ ### Fixed
5
+ - Enhanced SQL statement parsing in native loader
6
+ - Improved handling of complex ON CONFLICT clauses with multiple closing parentheses
7
+ - Fixed spacing issues between VALUES and ON CONFLICT clauses
8
+ - Enhanced regex pattern for more precise conflict clause extraction
9
+ - Added proper statement reassembly for complex SQL structures
10
+
11
+ ## [0.3.7] - 2025-01-14
12
+ ### Fixed
13
+ - Corrected SQL value handling in native loader
14
+ - Fixed boolean value handling, particularly at the end of VALUES clauses
15
+ - Improved handling of NULL values and numbers
16
+ - Added proper whitespace cleaning for values
17
+ - Enhanced value type detection for correct quoting
18
+
3
19
  ## [0.3.6] - 2025-01-14
4
20
  ### Fixed
5
21
  - Further enhanced SQL statement handling in native loader
@@ -103,81 +103,86 @@ module RealDataTests
103
103
  statements
104
104
  end
105
105
 
106
- def clean_sql_statement(statement)
107
- # Handle VALUES clause formatting
108
- if statement.include?('VALUES')
109
- # Split into pre-VALUES and VALUES parts
110
- parts = statement.split(/VALUES\s*\(/i, 2)
111
- if parts.length == 2
112
- # Get the column names from the first part
113
- column_names = parts[0].scan(/\((.*?)\)/).flatten.first&.split(',')&.map(&:strip) || []
114
-
115
- # Split values into individual items
116
- values_part = parts[1]
117
- values = split_values(values_part)
118
-
119
- # Process each value according to its column and position
120
- values.each_with_index do |value, i|
121
- # Skip if already properly quoted
122
- next if value.start_with?("'") && value.end_with?("'")
123
-
124
- # Quote UUIDs
125
- if value.match?(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i)
126
- values[i] = "'#{value}'"
127
- # Quote any non-NULL string values that contain spaces or special characters
128
- elsif !['NULL', 'true', 'false'].include?(value) &&
129
- !value.match?(/^\d+$/) && # not a number
130
- !value.start_with?("'{") && # not a JSON object
131
- !value.start_with?("'") # not already quoted
132
- values[i] = "'#{value}'"
133
- end
134
- end
106
+ def extract_conflict_clause(statement)
107
+ # Use a more precise regex that handles multiple closing parentheses
108
+ if statement =~ /(.+?\))\s*(ON\s+CONFLICT\s+.*?)(?:;?\s*$)/i
109
+ [$1, $2.strip]
110
+ else
111
+ [statement.sub(/;?\s*$/, ''), nil]
112
+ end
113
+ end
135
114
 
136
- # Reassemble the statement with any trailing ON CONFLICT clause
137
- remainder = values_part.match(/\)\s*(ON\s+CONFLICT.*?)(;?\s*$)/i)
138
- statement = parts[0] + 'VALUES (' + values.join(', ') + ')'
139
- statement += " #{remainder[1]};" if remainder
140
- end
141
- end
115
+ def clean_sql_statement(statement)
116
+ # Extract the ON CONFLICT clause if it exists
117
+ statement, conflict_clause = extract_conflict_clause(statement)
118
+
119
+ # Handle VALUES clause formatting
120
+ if statement.include?('VALUES')
121
+ # Split into pre-VALUES and VALUES parts
122
+ parts = statement.split(/VALUES\s*\(/i, 2)
123
+ if parts.length == 2
124
+ # Clean and process the values
125
+ values = clean_values(parts[1].split(/\)\s*$/)[0])
142
126
 
143
- statement
127
+ # Make sure we properly close the VALUES parentheses
128
+ statement = "#{parts[0]}VALUES (#{values})"
129
+ end
144
130
  end
145
131
 
146
- def split_values(values_part)
147
- values = []
148
- current_value = ''
149
- in_quotes = false
150
- in_json = false
151
- depth = 0
152
-
153
- values_part.chars.each_with_index do |char, i|
154
- case char
155
- when "'"
156
- # Toggle quote state if not escaped
157
- if i == 0 || values_part[i-1] != '\\'
158
- in_quotes = !in_quotes
159
- end
160
- when '{'
161
- depth += 1 unless in_quotes
162
- in_json = true unless in_quotes
163
- when '}'
164
- depth -= 1 unless in_quotes
165
- when ','
166
- if !in_quotes && depth == 0
167
- values << current_value.strip
168
- current_value = ''
169
- next
170
- end
132
+ # Add back the conflict clause if it existed
133
+ statement = "#{statement}#{conflict_clause ? ' ' + conflict_clause : ''}"
134
+
135
+ # Ensure the statement ends with a semicolon
136
+ statement += ";" unless statement.end_with?(';')
137
+
138
+ statement
139
+ end
140
+
141
+ def clean_values(values_str)
142
+ values = []
143
+ current_value = ''
144
+ in_quotes = false
145
+ nested_level = 0
146
+
147
+ values_str.chars.each do |char|
148
+ case char
149
+ when "'"
150
+ in_quotes = !in_quotes
151
+ current_value << char
152
+ when '{'
153
+ nested_level += 1
154
+ current_value << char
155
+ when '}'
156
+ nested_level -= 1
157
+ current_value << char
158
+ when ','
159
+ if !in_quotes && nested_level == 0
160
+ values << clean_value(current_value.strip)
161
+ current_value = ''
162
+ else
163
+ current_value << char
171
164
  end
165
+ else
172
166
  current_value << char
173
167
  end
168
+ end
169
+
170
+ values << clean_value(current_value.strip)
171
+ values.join(', ')
172
+ end
174
173
 
175
- # Add the last value (remove trailing ';' or ')')
176
- last_value = current_value.strip
177
- last_value = last_value[0..-2] if last_value.end_with?(';', ')')
178
- values << last_value
174
+ def clean_value(value)
175
+ return value if value.start_with?("'") # Already quoted
176
+ return value if value.start_with?("'{") # JSON object
177
+ return 'NULL' if value.upcase == 'NULL'
178
+ return value.downcase if ['true', 'false'].include?(value.downcase)
179
+ return value if value.match?(/^\d+$/) # Numbers
179
180
 
180
- values
181
+ if value.match?(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i)
182
+ "'#{value}'" # UUID
183
+ else
184
+ "'#{value}'" # Other strings
181
185
  end
186
+ end
182
187
  end
183
188
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RealDataTests
4
- VERSION = "0.3.6"
4
+ VERSION = "0.3.8"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: real_data_tests
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.6
4
+ version: 0.3.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kevin Dias