quote-sql 0.0.6 → 0.0.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 +4 -4
- data/README.md +6 -10
- data/lib/quote_sql/formater.rb +3 -3
- data/lib/quote_sql/quoter.rb +53 -30
- data/lib/quote_sql/test.rb +150 -11
- data/lib/quote_sql/version.rb +1 -1
- data/lib/quote_sql.rb +44 -38
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cfe070af9a81f751ed10ef8ace30bf5e44a3efb54cff04f2eb5cc137b7fbc0f1
|
4
|
+
data.tar.gz: 8c8ec59ca80a8c72ceee6567da4beb5f79c96a63e16d945694fed26ea695feca
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 03d69b9b3256cd22762844dc98c31ce2223c673079488d7175078dd82406d8031673368871a2a920ecda17ea68beb79c87f3208d56b1e770c4ba15583fafc648
|
7
|
+
data.tar.gz: b6d9f335cdcaf0e597f3118090451059220ebd9e540eda483f546301ad148bfebc35150a73a72c6dc54a39f537e8aa9b854970a975218226a26af3ed6add75c0
|
data/README.md
CHANGED
@@ -26,7 +26,7 @@ Best Martin
|
|
26
26
|
`QuoteSql.new("SELECT %field").quote(field: "abc").to_sql`
|
27
27
|
=> SELECT 'abc'
|
28
28
|
|
29
|
-
`QuoteSql.new("SELECT %
|
29
|
+
`QuoteSql.new("SELECT %field::TEXT").quote(field: 9).to_sql`
|
30
30
|
=> SELECT 9::TEXT
|
31
31
|
|
32
32
|
### Rails models
|
@@ -58,11 +58,8 @@ Values are be ordered in sequence of columns. Missing value entries are substitu
|
|
58
58
|
ON CONFLICT ("id") DO NOTHING
|
59
59
|
|
60
60
|
### Columns from a list
|
61
|
-
`QuoteSql.new("SELECT %columns").quote(columns: [:a, "b.c", d:
|
62
|
-
=> SELECT "a","b"."c",
|
63
|
-
|
64
|
-
`QuoteSql.new("SELECT %columns").quote(columns: [:a, "b.c", d: {e: field, nil: false}]).to_sql`
|
65
|
-
=> SELECT "a","b"."c",jsonb_strip_nulls(jsonb_build_object('e', 1)) AS d
|
61
|
+
`QuoteSql.new("SELECT %columns FROM %table").quote(table: "foo", columns: [:a, "b", "foo.c", {d: :e}]).to_sql`
|
62
|
+
=> SELECT "foo"."a","b"."foo"."c", "foo"."e" AS d
|
66
63
|
|
67
64
|
## Executing
|
68
65
|
### Getting the results
|
@@ -72,6 +69,7 @@ Values are be ordered in sequence of columns. Missing value entries are substitu
|
|
72
69
|
### Binds
|
73
70
|
You can use binds ($1, $2, ...) in the SQL and add arguments to the result call
|
74
71
|
`QuoteSql.new('SELECT $1 AS a').result(1)`
|
72
|
+
=> [{:a=>1}]
|
75
73
|
|
76
74
|
#### using JSON
|
77
75
|
|
@@ -111,10 +109,8 @@ All can be preceded by additional letters and underscore e.g. `%foo_bar_column`
|
|
111
109
|
A database typecast is added to fields ending with double underscore and a valid db data type
|
112
110
|
with optional array dimension
|
113
111
|
|
114
|
-
- `%
|
115
|
-
- `%
|
116
|
-
- `%array__text1` => adds a `::TEXT[]` (TO BE IMPLEMENTED)
|
117
|
-
- `%array__text2` => adds a `::TEXT[][]` (TO BE IMPLEMENTED)
|
112
|
+
- `%field::jsonb` => treats the field as jsonb when casted
|
113
|
+
- `%array::text[]` => treats an array like a text array, default is JSONB
|
118
114
|
|
119
115
|
### Quoting
|
120
116
|
- Any value of the standard mixins are quoted with these exceptions
|
data/lib/quote_sql/formater.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'niceql'
|
1
2
|
class QuoteSql
|
2
3
|
module Formater
|
3
4
|
PG_FORMAT_BIN = `which pg_format`.chomp.presence
|
@@ -9,15 +10,14 @@ class QuoteSql
|
|
9
10
|
|
10
11
|
def to_formatted_sql
|
11
12
|
sql = respond_to?(:to_sql) ? to_sql : to_s
|
12
|
-
Niceql::Prettifier.prettify_sql(sql)
|
13
|
+
Niceql::Prettifier.prettify_sql(sql.gsub(/(?<=[^%])%(?=\S)/, "%%"))
|
13
14
|
|
14
15
|
# IO.popen(PG_FORMAT_BIN, "r+", err: "/dev/null") do |f|
|
15
16
|
# f.write(sql)
|
16
17
|
# f.close_write
|
17
18
|
# f.read
|
18
19
|
# end
|
19
|
-
|
20
|
-
sql
|
20
|
+
|
21
21
|
end
|
22
22
|
|
23
23
|
alias to_sqf to_formatted_sql
|
data/lib/quote_sql/quoter.rb
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
class QuoteSql
|
2
2
|
class Quoter
|
3
|
-
def initialize(qsql, key, quotable)
|
3
|
+
def initialize(qsql, key, cast, quotable)
|
4
4
|
@qsql = qsql
|
5
|
-
@key, @quotable = key, quotable
|
5
|
+
@key, @cast, @quotable = key, cast, quotable
|
6
6
|
@name = key.sub(/_[^_]+$/, '') if key["_"]
|
7
7
|
end
|
8
8
|
|
9
|
-
attr_reader :key, :quotable, :name
|
9
|
+
attr_reader :key, :quotable, :name, :cast
|
10
10
|
|
11
11
|
def quotes
|
12
12
|
@qsql.quotes
|
@@ -227,42 +227,65 @@ class QuoteSql
|
|
227
227
|
end
|
228
228
|
end
|
229
229
|
|
230
|
-
def cast
|
231
|
-
|
232
|
-
m[2..].sub(CASTS) { _1.tr("_", " ") }
|
233
|
-
end
|
234
|
-
end
|
235
|
-
|
236
|
-
def json?
|
237
|
-
!!key[/(^|_)(jsonb?)$/]
|
230
|
+
def json?(cast = self.cast)
|
231
|
+
cast.to_s[/jsonb?$/i]
|
238
232
|
end
|
239
233
|
|
240
|
-
private def _quote(item = @quotable
|
241
|
-
|
242
|
-
if cast
|
243
|
-
rv << "::#{cast.upcase}"
|
244
|
-
rv << "[]" * rv.depth if rv[/^ARRAY/]
|
245
|
-
end
|
246
|
-
Raw.sql rv
|
234
|
+
private def _quote(item = @quotable)
|
235
|
+
Raw.sql QuoteSql.quote(item)
|
247
236
|
end
|
248
237
|
|
249
238
|
private def _quote_column_name(name)
|
250
239
|
Raw.sql name.scan(/(?:^|")?([^."]+)/).map { QuoteSql.quote_column_name _1 }.join(".")
|
251
240
|
end
|
252
241
|
|
253
|
-
def
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
else
|
263
|
-
return Raw.sql item.to_sql if item.respond_to? :to_sql
|
264
|
-
_quote(item)
|
242
|
+
private def _quote_array(items)
|
243
|
+
rv = items.map do |i|
|
244
|
+
if i.is_a?(Array)
|
245
|
+
_quote_array(i)
|
246
|
+
elsif self.cast[/jsonb?/i]
|
247
|
+
_quote(i.to_json)
|
248
|
+
else
|
249
|
+
quote(i)
|
250
|
+
end
|
265
251
|
end
|
252
|
+
"[#{rv.join(",")}]"
|
253
|
+
end
|
254
|
+
|
255
|
+
def quote_hash(item)
|
256
|
+
item.compact! if item.delete(nil) == false
|
257
|
+
case self.cast
|
258
|
+
when /hstore/i
|
259
|
+
_quote(item.map { "#{_1}=>#{_2.nil? ? 'NULL' : _2}"}.join(","))
|
260
|
+
when NilClass,""
|
261
|
+
"#{_quote(item.to_json)}::JSONB"
|
262
|
+
when /jsonb?/i
|
263
|
+
_quote(item.to_json)
|
264
|
+
end
|
265
|
+
end
|
266
|
+
|
267
|
+
def quote(item = @quotable, cast = nil)
|
268
|
+
Raw.sql case item.class.to_s
|
269
|
+
when "Arel::Nodes::SqlLiteral", "QuoteSql::Raw"
|
270
|
+
item
|
271
|
+
when "Array"
|
272
|
+
if json? or self.cast.blank?
|
273
|
+
rv = _quote(item.to_json)
|
274
|
+
self.cast.present? ? rv : "#{rv}::JSONB"
|
275
|
+
else
|
276
|
+
"ARRAY#{_quote_array(item)}"
|
277
|
+
end
|
278
|
+
when "Hash"
|
279
|
+
quote_hash(item)
|
280
|
+
else
|
281
|
+
if item.respond_to? :to_sql
|
282
|
+
item.to_sql
|
283
|
+
elsif json?
|
284
|
+
_quote(item.to_json)
|
285
|
+
else
|
286
|
+
_quote(item)
|
287
|
+
end
|
288
|
+
end
|
266
289
|
end
|
267
290
|
|
268
291
|
def column_names(item = @quotable)
|
data/lib/quote_sql/test.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
class QuoteSql::Test
|
2
2
|
private
|
3
|
+
|
3
4
|
def test_columns
|
4
5
|
expected <<~SQL
|
5
6
|
SELECT x, "a", "b", "c", "d"
|
@@ -124,29 +125,59 @@ class QuoteSql::Test
|
|
124
125
|
expected <<~SQL
|
125
126
|
SELECT * FROM json_to_recordset('[{"a":1,"b":"foo"},{"a":"2"}]') as "x" ("a" int, "b" text)
|
126
127
|
SQL
|
127
|
-
"SELECT * FROM %x_json".quote_sql(x_casts: {a: "int", b: "text"}, x_json: [{ a: 1, b: 'foo'}, {a: '2', c: 'bar'}])
|
128
|
+
"SELECT * FROM %x_json".quote_sql(x_casts: { a: "int", b: "text" }, x_json: [{ a: 1, b: 'foo' }, { a: '2', c: 'bar' }])
|
128
129
|
end
|
129
130
|
|
130
131
|
def test_json_insert
|
131
132
|
expected <<~SQL
|
132
|
-
|
133
|
+
INSERT INTO users (name, color) SELECT * from json_to_recordset('[{"name":"auge","color":"#611333"}]') AS "x"("name" text,"color" text)
|
133
134
|
SQL
|
134
|
-
x_json = {"first_name"=>nil, "last_name"=>nil, "stripe_id"=>nil, "credits"=>nil, "avatar"=>nil, "name"=>"auge", "color"=>"#611333", "founder"=>nil, "language"=>nil, "country"=>nil, "data"=>{}, "created_at"=>"2020-11-19T09:30:18.670Z", "updated_at"=>"2020-11-19T09:40:00.063Z"}
|
135
|
-
"INSERT INTO users (name, color) SELECT * from %x_json".quote_sql(x_casts: {name: "text", color: "text"}, x_json:)
|
135
|
+
x_json = { "first_name" => nil, "last_name" => nil, "stripe_id" => nil, "credits" => nil, "avatar" => nil, "name" => "auge", "color" => "#611333", "founder" => nil, "language" => nil, "country" => nil, "data" => {}, "created_at" => "2020-11-19T09:30:18.670Z", "updated_at" => "2020-11-19T09:40:00.063Z" }
|
136
|
+
"INSERT INTO users (name, color) SELECT * from %x_json".quote_sql(x_casts: { name: "text", color: "text" }, x_json:)
|
136
137
|
end
|
137
138
|
|
138
139
|
def test_from_json_bind
|
139
140
|
expected <<~SQL
|
140
|
-
|
141
|
+
Select * From json_to_recordset($1) AS "x"("a" int,"b" text,"c" boolean)
|
141
142
|
SQL
|
142
|
-
QuoteSQL("Select * From %x_json", x_json: 1, x_casts: {a: "int", b: "text", c: "boolean"})
|
143
|
+
QuoteSQL("Select * From %x_json", x_json: 1, x_casts: { a: "int", b: "text", c: "boolean" })
|
143
144
|
end
|
144
145
|
|
145
146
|
def test_insert_json_bind
|
146
147
|
expected <<~SQL
|
147
|
-
|
148
|
+
INSERT INTO table ("a","b","c") Select * From json_to_recordset($1) AS "x"("a" int,"b" text,"c" boolean)
|
149
|
+
SQL
|
150
|
+
QuoteSQL("INSERT INTO table (%x_columns) Select * From %x_json", x_json: 1, x_casts: { a: "int", b: "text", c: "boolean" })
|
151
|
+
end
|
152
|
+
|
153
|
+
def test_cast_values
|
154
|
+
expected <<~SQL
|
155
|
+
SELECT
|
156
|
+
'abc'::TEXT,
|
157
|
+
'"abc"'::JSON,
|
158
|
+
'["cde",null,"fgh"]'::JSONB,
|
159
|
+
ARRAY['cde', NULL, 'fgh']::TEXT[],
|
160
|
+
ARRAY['"cde"', 'null', '"fgh"']::JSON[],
|
161
|
+
'{"foo":"bar","go":1,"strip_null":null}'::JSONB not_compact,
|
162
|
+
'{"foo":"bar","go":1}'::JSON compact,
|
163
|
+
'foo=>bar,go=>1,strip_null=>NULL'::HSTORE,
|
164
|
+
ARRAY[[1,2,3],[1,2,3]]::INT[][]
|
165
|
+
SQL
|
166
|
+
array1 = array2 = array3 = ["cde", nil, "fgh"]
|
167
|
+
array4 = [[1,2,3], [1,2,3]]
|
168
|
+
hash = { foo: "bar", "go": 1, strip_null: nil }
|
169
|
+
QuoteSQL(<<~SQL, field1: 'abc', array1:, array2:, array3:, array4:, hash: ,not_compact: hash, compact: hash.merge(nil => false))
|
170
|
+
SELECT
|
171
|
+
%field1::TEXT,
|
172
|
+
%field1::JSON,
|
173
|
+
%array1,
|
174
|
+
%array2::TEXT[],
|
175
|
+
%array3::JSON[],
|
176
|
+
%not_compact not_compact,
|
177
|
+
%compact::JSON compact,
|
178
|
+
%hash::HSTORE,
|
179
|
+
%array4::INT[][]
|
148
180
|
SQL
|
149
|
-
QuoteSQL("INSERT INTO table (%x_columns) Select * From %x_json", x_json: 1, x_casts: {a: "int", b: "text", c: "boolean"})
|
150
181
|
end
|
151
182
|
|
152
183
|
# def test_q3
|
@@ -172,7 +203,6 @@ class QuoteSql::Test
|
|
172
203
|
# )
|
173
204
|
# end
|
174
205
|
|
175
|
-
|
176
206
|
public
|
177
207
|
|
178
208
|
def all
|
@@ -193,10 +223,12 @@ class QuoteSql::Test
|
|
193
223
|
tables = @test.tables.to_h { [[_1, "table"].compact.join("_"), _2] }
|
194
224
|
columns = @test.instance_variable_get(:@columns).to_h { [[_1, "columns"].compact.join("_"), _2] }
|
195
225
|
rv += [
|
196
|
-
"QuoteSql.new(\"#{@test.original}\").quote(#{{**tables, **columns, **@test.quotes }.inspect}).to_sql", "🎯 #{expected}", "✅ #{sql}"]
|
226
|
+
"QuoteSql.new(\"#{@test.original}\").quote(#{{ **tables, **columns, **@test.quotes }.inspect}).to_sql", "🎯 #{expected}", "✅ #{sql}"]
|
197
227
|
@success << rv if @success
|
198
228
|
else
|
199
229
|
rv += [@test.inspect, "🎯 #{expected}", "❌ #{sql}"]
|
230
|
+
rv << sql.gsub(/\s+/, "")&.downcase&.strip
|
231
|
+
rv << expected&.gsub(/\s+/, "")&.downcase&.strip
|
200
232
|
@fail << rv if @fail
|
201
233
|
end
|
202
234
|
rescue => exc
|
@@ -228,4 +260,111 @@ class QuoteSql::Test
|
|
228
260
|
end
|
229
261
|
end
|
230
262
|
|
231
|
-
|
263
|
+
def datatype
|
264
|
+
errors = {}
|
265
|
+
success = []
|
266
|
+
spaces = ->(*) { " " * (rand(4) + 1) }
|
267
|
+
|
268
|
+
DATATYPES.each_line(chomp: true) do |line|
|
269
|
+
|
270
|
+
l = line.gsub(/\s+/, &spaces).gsub(/(?<=\()\d+|\d+(?=\))/) { "#{spaces.call}#{rand(10) + 1}#{spaces.call}" }.gsub(/\(/) { "#{spaces.call}(" }
|
271
|
+
|
272
|
+
m = "jgj hsgjhsgfjh ag %field::#{l} asldfalskjdfl".match(QuoteSql::CASTS)
|
273
|
+
if m.present? and l == m[1]
|
274
|
+
success << line
|
275
|
+
else
|
276
|
+
errors[line] = m&.to_a
|
277
|
+
end
|
278
|
+
line = line + "[]"*(rand(3) + 1)
|
279
|
+
m = "jgj hsgjhsgfjh ag %field::#{line} asldfalskjdfl".match(QuoteSql::CASTS)
|
280
|
+
if m.present? and line == m[1] + m[2]
|
281
|
+
success << line
|
282
|
+
else
|
283
|
+
errors[line] = m&.to_a
|
284
|
+
end
|
285
|
+
end
|
286
|
+
puts success.sort.inspect
|
287
|
+
ap errors
|
288
|
+
end
|
289
|
+
|
290
|
+
DATATYPES = <<-DATATYPES
|
291
|
+
bigint
|
292
|
+
int8
|
293
|
+
bigserial
|
294
|
+
serial8
|
295
|
+
bit
|
296
|
+
bit (1)
|
297
|
+
bit varying
|
298
|
+
varbit
|
299
|
+
bit varying (2)
|
300
|
+
varbit (2)
|
301
|
+
boolean
|
302
|
+
bool
|
303
|
+
box
|
304
|
+
bytea
|
305
|
+
character
|
306
|
+
char
|
307
|
+
character (1)
|
308
|
+
char (1)
|
309
|
+
character varying
|
310
|
+
varchar
|
311
|
+
character varying (1)
|
312
|
+
varchar (1)
|
313
|
+
cidr
|
314
|
+
circle
|
315
|
+
date
|
316
|
+
double precision
|
317
|
+
float8
|
318
|
+
inet
|
319
|
+
integer
|
320
|
+
int
|
321
|
+
int4
|
322
|
+
interval
|
323
|
+
interval (1)
|
324
|
+
json
|
325
|
+
jsonb
|
326
|
+
line
|
327
|
+
lseg
|
328
|
+
macaddr
|
329
|
+
macaddr8
|
330
|
+
money
|
331
|
+
numeric
|
332
|
+
numeric(10,3)
|
333
|
+
decimal
|
334
|
+
decimal(10,3)
|
335
|
+
path
|
336
|
+
pg_lsn
|
337
|
+
pg_snapshot
|
338
|
+
point
|
339
|
+
polygon
|
340
|
+
real
|
341
|
+
float4
|
342
|
+
smallint
|
343
|
+
int2
|
344
|
+
smallserial
|
345
|
+
serial
|
346
|
+
serial2
|
347
|
+
serial4
|
348
|
+
text
|
349
|
+
time
|
350
|
+
time(1)
|
351
|
+
time without time zone
|
352
|
+
time(1) without time zone
|
353
|
+
time with time zone
|
354
|
+
time(2) with time zone
|
355
|
+
timetz
|
356
|
+
timestamp
|
357
|
+
timestamp(1)
|
358
|
+
timestamp without time zone
|
359
|
+
timestamp(1) without time zone
|
360
|
+
timestamp with time zone
|
361
|
+
timestamp(1) with time zone
|
362
|
+
timestamptz
|
363
|
+
tsquery
|
364
|
+
tsvector
|
365
|
+
txid_snapshot
|
366
|
+
uuid
|
367
|
+
xml
|
368
|
+
DATATYPES
|
369
|
+
|
370
|
+
end
|
data/lib/quote_sql/version.rb
CHANGED
data/lib/quote_sql.rb
CHANGED
@@ -3,25 +3,30 @@ Dir.glob(__FILE__.sub(/\.rb$/, "/*.rb")).each { require(_1) unless _1[/(deprecat
|
|
3
3
|
# Tool to build and run SQL queries easier
|
4
4
|
class QuoteSql
|
5
5
|
|
6
|
+
|
6
7
|
DATA_TYPES_RE = %w(
|
7
|
-
(
|
8
|
-
|
8
|
+
(?>character\\s+varying|bit\\s+varying|character|varbit|varchar|char|bit|interval)(?>\\s*\\(\\s*\\d+\\s*\\))?
|
9
|
+
(?>numeric|decimal)(?>\\s*\\(\\s*\\d+\\s*,\\s*\\d+\\s*\\))?
|
10
|
+
timestamptz timetz
|
11
|
+
time(?>stamp)?(?>\\s*\\(\\s*\\d+\\s*\\))?(?>\\s+with(?>out)?\\s+time\\s+zone)?
|
12
|
+
integer
|
13
|
+
(?>small|big)(?>int|serial)
|
14
|
+
bool(?>ean)? box bytea cidr circle date
|
9
15
|
(?:date|int[48]|num|ts(?:tz)?)(?:multi)?range
|
10
16
|
macaddr8?
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
time(stamp)?(_\\(\d+\\))?(_with(out)?_time_zone)?
|
17
|
+
ts(?>query|vector)
|
18
|
+
float[48]
|
19
|
+
(?:int|serial)[248]?
|
20
|
+
double\\s+precision
|
21
|
+
jsonb json
|
22
|
+
inet
|
23
|
+
line lseg money path
|
24
|
+
pg_lsn pg_snapshot txid_snapshot
|
25
|
+
point polygon real text
|
26
|
+
uuid xml hstore
|
22
27
|
).join("|")
|
23
28
|
|
24
|
-
CASTS = Regexp.new("
|
29
|
+
CASTS = Regexp.new("::(#{DATA_TYPES_RE})((?:\\s*\\[\\s*\\d?\\s*\\])*)", "i")
|
25
30
|
|
26
31
|
def self.conn
|
27
32
|
raise ArgumentError, "You need to define a database connection function"
|
@@ -152,11 +157,8 @@ time(stamp)?(_\\(\d+\\))?(_with(out)?_time_zone)?
|
|
152
157
|
def key_matches
|
153
158
|
@sql.scan(MIXIN_RE).map do |full, *key|
|
154
159
|
key = key.compact[0]
|
155
|
-
if m = key.match(/^(.+)#{CASTS}/i)
|
156
|
-
_, key, cast = m.to_a
|
157
|
-
end
|
158
160
|
has_quote = @quotes.key?(key.to_sym) || key.match?(/(table|columns)$/)
|
159
|
-
[full, key,
|
161
|
+
[full, key, has_quote]
|
160
162
|
end
|
161
163
|
end
|
162
164
|
|
@@ -166,27 +168,28 @@ time(stamp)?(_\\(\d+\\))?(_with(out)?_time_zone)?
|
|
166
168
|
loop do
|
167
169
|
s = StringScanner.new(@sql)
|
168
170
|
sql = ""
|
169
|
-
key_matches.each do |key_match, key,
|
170
|
-
s.scan_until(/(.*?)#{key_match}(
|
171
|
-
matched, pre,
|
172
|
-
if m = key.match(/^bind(\d+)?/im)
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
171
|
+
key_matches.each do |key_match, key, has_quote|
|
172
|
+
s.scan_until(/(.*?)#{key_match}(#{CASTS}?)/im)
|
173
|
+
matched, pre, cast = s.matched, s[1], s[2]
|
174
|
+
# if m = key.match(/^bind(\d+)?/im)
|
175
|
+
# if m[1].present?
|
176
|
+
# bind_num = m[1].to_i
|
177
|
+
# @binds[bind_num - 1] ||= cast
|
178
|
+
# raise "bind #{bind_num} already set to #{@binds[bind_num - 1]}" unless @binds[bind_num - 1] == cast
|
179
|
+
# else
|
180
|
+
# @binds << cast
|
181
|
+
# bind_num = @binds.length
|
182
|
+
# end
|
183
|
+
#
|
184
|
+
# matched = "#{pre}$#{bind_num}#{"::#{cast}" if cast.present?}#{post}"
|
185
|
+
# els
|
186
|
+
if has_quote
|
187
|
+
quoted = quoter(key, cast)
|
185
188
|
unresolved.delete key
|
186
189
|
if (i = quoted.scan MIXIN_RE).present?
|
187
190
|
unresolved += i.map(&:last)
|
188
191
|
end
|
189
|
-
matched = "#{pre}#{quoted}#{
|
192
|
+
matched = "#{pre}#{quoted}#{cast}"
|
190
193
|
end
|
191
194
|
rescue TypeError
|
192
195
|
ensure
|
@@ -200,8 +203,8 @@ time(stamp)?(_\\(\d+\\))?(_with(out)?_time_zone)?
|
|
200
203
|
self
|
201
204
|
end
|
202
205
|
|
203
|
-
def quoter(key)
|
204
|
-
quoter = @resolved[key.to_sym] = Quoter.new(self, key, @quotes[key.to_sym])
|
206
|
+
def quoter(key, cast)
|
207
|
+
quoter = @resolved[key.to_sym] = Quoter.new(self, key, cast, @quotes[key.to_sym])
|
205
208
|
quoter.to_sql
|
206
209
|
rescue TypeError => exc
|
207
210
|
@resolved[key.to_sym] = exc
|
@@ -224,8 +227,11 @@ time(stamp)?(_\\(\d+\\))?(_with(out)?_time_zone)?
|
|
224
227
|
|
225
228
|
def self.test(which = :all)
|
226
229
|
require __dir__ + "/quote_sql/test.rb"
|
227
|
-
|
230
|
+
case which
|
231
|
+
when :all
|
228
232
|
Test.new.all
|
233
|
+
when :datatype
|
234
|
+
Test.new.datatype
|
229
235
|
else
|
230
236
|
Test.new.run(which)
|
231
237
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: quote-sql
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Martin Kufner
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-02-
|
11
|
+
date: 2024-02-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: niceql
|