real_data_tests 0.3.6 → 0.3.7

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 179a591f6a485c397255c0cbec27e18757e2f7fdc450f7292f279cd681f91e0b
4
- data.tar.gz: bb9b9f4f60b609f2ea8a901689b4b9b8d5ddfdc7d36e867c18ebbe24855cb5aa
3
+ metadata.gz: f325960594ac352b4fbaae4adafb38256bde54feed249140838971e61c5fcef1
4
+ data.tar.gz: d977dda68eac4fa8d13c82dc5a00bba7dd3b27e9c876ab5847a3b3b254cc7d4f
5
5
  SHA512:
6
- metadata.gz: a47d49d690958e70cd324ede48dadce7d3e9e7bd39471ee052879d6fe5646ad308aebbf05f79cb92ebe3c9b7ede94b0163c74efdddf3f518ef47518a489a2ee6
7
- data.tar.gz: a4c6a97cff1bd02096064fd1da67580dd9307ce29f4e7d5a8be4d82c9f352b97009ef1fc22eb555dc39b1b87599947680a61bc2bc376c2cd14a7f8cc5397892d
6
+ metadata.gz: 40c69c54f989318441e697487673f7c019907cddcea3d81fa9b5775964fc2a6a76994b97093465d57f26521813780292f58d28f11ed75638222b458a75e514f8
7
+ data.tar.gz: bce1cd39d64e2501b222135477c7e10d38769ae26b47827c3c76efb8d2651cdffae689ad3c8e2bb9bd0bdd1315e9f2dbfcdd3dd576079589c75d3d7585c2668c
data/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [0.3.7] - 2025-01-14
4
+ ### Fixed
5
+ - Corrected SQL value handling in native loader
6
+ - Fixed boolean value handling, particularly at the end of VALUES clauses
7
+ - Improved handling of NULL values and numbers
8
+ - Added proper whitespace cleaning for values
9
+ - Enhanced value type detection for correct quoting
10
+
3
11
  ## [0.3.6] - 2025-01-14
4
12
  ### Fixed
5
13
  - Further enhanced SQL statement handling in native loader
@@ -103,81 +103,83 @@ 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
135
-
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
106
+ def clean_sql_statement(statement)
107
+ # Extract the ON CONFLICT clause if it exists
108
+ statement, conflict_clause = extract_conflict_clause(statement)
109
+
110
+ # Handle VALUES clause formatting
111
+ if statement.include?('VALUES')
112
+ # Split into pre-VALUES and VALUES parts
113
+ parts = statement.split(/VALUES\s*\(/i, 2)
114
+ if parts.length == 2
115
+ # Clean and process the values
116
+ values = clean_values(parts[1].split(/\)\s*$/)[0])
117
+
118
+ # Reassemble the statement
119
+ statement = "#{parts[0]}VALUES (#{values})"
141
120
  end
121
+ end
122
+
123
+ # Add back the conflict clause if it existed
124
+ statement += " #{conflict_clause}" if conflict_clause
125
+ statement += ";"
126
+
127
+ statement
128
+ end
142
129
 
143
- statement
130
+ def extract_conflict_clause(statement)
131
+ if statement =~ /(.+?)(\s+ON\s+CONFLICT\s+.*?)(?:;?\s*$)/i
132
+ [$1, $2.strip]
133
+ else
134
+ [statement.sub(/;?\s*$/, ''), nil]
144
135
  end
136
+ end
145
137
 
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
138
+ def clean_values(values_str)
139
+ values = []
140
+ current_value = ''
141
+ in_quotes = false
142
+ nested_level = 0
143
+
144
+ values_str.chars.each do |char|
145
+ case char
146
+ when "'"
147
+ in_quotes = !in_quotes
148
+ current_value << char
149
+ when '{'
150
+ nested_level += 1
151
+ current_value << char
152
+ when '}'
153
+ nested_level -= 1
154
+ current_value << char
155
+ when ','
156
+ if !in_quotes && nested_level == 0
157
+ values << clean_value(current_value.strip)
158
+ current_value = ''
159
+ else
160
+ current_value << char
171
161
  end
162
+ else
172
163
  current_value << char
173
164
  end
165
+ end
166
+
167
+ values << clean_value(current_value.strip)
168
+ values.join(', ')
169
+ end
174
170
 
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
171
+ def clean_value(value)
172
+ return value if value.start_with?("'") # Already quoted
173
+ return value if value.start_with?("'{") # JSON object
174
+ return 'NULL' if value.upcase == 'NULL'
175
+ return value.downcase if ['true', 'false'].include?(value.downcase)
176
+ return value if value.match?(/^\d+$/) # Numbers
179
177
 
180
- values
178
+ if value.match?(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i)
179
+ "'#{value}'" # UUID
180
+ else
181
+ "'#{value}'" # Other strings
181
182
  end
183
+ end
182
184
  end
183
185
  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.7"
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.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kevin Dias