extralite 2.7.1 → 2.8.1
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/.github/workflows/test.yml +1 -1
- data/CHANGELOG.md +17 -4
- data/README.md +79 -42
- data/examples/kv_store.rb +1 -1
- data/examples/pubsub_store_polyphony.rb +7 -7
- data/examples/pubsub_store_threads.rb +3 -3
- data/ext/extralite/changeset.c +1 -1
- data/ext/extralite/common.c +27 -27
- data/ext/extralite/database.c +134 -61
- data/ext/extralite/extralite.h +10 -17
- data/ext/extralite/query.c +17 -17
- data/gemspec.rb +1 -1
- data/lib/extralite/version.rb +1 -1
- data/lib/extralite.rb +158 -3
- data/test/{perf_ary.rb → perf_array.rb} +1 -1
- data/test/perf_splat.rb +63 -0
- data/test/{perf_argv_transform.rb → perf_splat_transform.rb} +7 -7
- data/test/test_database.rb +193 -120
- data/test/test_iterator.rb +12 -12
- data/test/test_query.rb +92 -92
- metadata +7 -7
- data/lib/extralite/sqlite3_constants.rb +0 -157
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 49fbb44a887747091953d2ec2239050036dd1c5c37290d9f651521b47a84fdfb
|
4
|
+
data.tar.gz: 5200205e84f47abad1a9e3c936999edd77defa53e187941d81d50a91926cd520
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1fd77a5ebe191923ba6159eb79b6c60ac5c8311280a5a8513262e6ff6accf2020422a9394df25308718971b98ff25ab50409f50bf81c931cb41274f7401334e4
|
7
|
+
data.tar.gz: 0dde4d327858617ae1b3ad88432a705593303a312e93177a91c2fc25029cf505eaf952ce98a2cbbd4cced57d733a5a2c045cbf9d7909899c42972ca2c59e1cbd
|
data/.github/workflows/test.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,16 @@
|
|
1
|
+
## 2.8.1 2024-04-15
|
2
|
+
|
3
|
+
- Update bundled sqlite to version 3.45.3.
|
4
|
+
- Fix `Database#execute` for SQL ending with a comment.
|
5
|
+
[#72](https://github.com/digital-fabric/extralite/pull/72)
|
6
|
+
|
7
|
+
# 2.8 2024-03-10
|
8
|
+
|
9
|
+
- Improve documentation.
|
10
|
+
- Implement `Database#wal_checkpoint`.
|
11
|
+
- Rename query modes: `hash` (the default mode), `array`, `splat`, simplify querying APIs.
|
12
|
+
[#69](https://github.com/digital-fabric/extralite/pull/69)
|
13
|
+
|
1
14
|
# 2.7.1 2024-02-11
|
2
15
|
|
3
16
|
- Fix API docs.
|
@@ -6,11 +19,11 @@
|
|
6
19
|
|
7
20
|
- Improve progress handler API, add mode, period, tick options, global progress
|
8
21
|
handler. [#68](https://github.com/digital-fabric/extralite/pull/68)
|
9
|
-
- Rework `Database#initialize` options
|
10
|
-
- Add argv row mode (for passing column values as argv)
|
11
|
-
- Streamline and improve query methods
|
22
|
+
- Rework `Database#initialize` options.
|
23
|
+
- Add argv row mode (for passing column values as argv).
|
24
|
+
- Streamline and improve query methods.
|
12
25
|
[#67](https://github.com/digital-fabric/extralite/pull/67)
|
13
|
-
- Implement row transforms
|
26
|
+
- Implement row transforms.
|
14
27
|
|
15
28
|
# 2.6 2024-01-23
|
16
29
|
|
data/README.md
CHANGED
@@ -32,7 +32,7 @@ databases.
|
|
32
32
|
Extralite comes in two flavors: the `extralite` gem which uses the
|
33
33
|
system-installed sqlite3 library, and the `extralite-bundle` gem which bundles
|
34
34
|
the latest version of SQLite
|
35
|
-
([3.45.
|
35
|
+
([3.45.3](https://sqlite.org/releaselog/3_45_3.html)), offering access to the
|
36
36
|
latest features and enhancements.
|
37
37
|
|
38
38
|
## Features
|
@@ -141,10 +141,10 @@ single values, if you're just reading one column.
|
|
141
141
|
For that purpose, Extralite offers three different ways, or modes, of retrieving
|
142
142
|
records:
|
143
143
|
|
144
|
-
- `:hash`:
|
145
|
-
- `:
|
146
|
-
- `:
|
147
|
-
|
144
|
+
- `:hash`: retrieve each row as a hash (this is the default mode).
|
145
|
+
- `:array`: retrieve each row as an array.
|
146
|
+
- `:splat`: retrieve each row as one or more splatted values, without wrapping
|
147
|
+
them in a container (see [below](#the-splat-query-mode)).
|
148
148
|
|
149
149
|
Extralite provides separate methods for the different modes:
|
150
150
|
|
@@ -152,9 +152,9 @@ Extralite provides separate methods for the different modes:
|
|
152
152
|
# alias #query_hash
|
153
153
|
db.query('select 1') #=> [{ "1" => 1 }]
|
154
154
|
|
155
|
-
db.
|
155
|
+
db.query_array('select 1') #=> [[1]]
|
156
156
|
|
157
|
-
db.
|
157
|
+
db.query_splat('select 1') #=> [1]
|
158
158
|
```
|
159
159
|
|
160
160
|
Notice how all the return values above are arrays. This is because the different
|
@@ -163,19 +163,56 @@ get back a single row, use one of the `query_single_xxx` methods:
|
|
163
163
|
|
164
164
|
```ruby
|
165
165
|
# alias #query_single_hash
|
166
|
-
db.
|
166
|
+
db.query_single('select 1') #=> { "1" => 1 }
|
167
167
|
|
168
|
-
db.
|
168
|
+
db.query_single_array('select 1') #=> [1]
|
169
169
|
|
170
|
-
db.
|
170
|
+
db.query_single_splat('select 1') #=> 1
|
171
171
|
```
|
172
172
|
|
173
|
-
|
173
|
+
### Iterating Over Query Results with a Block
|
174
174
|
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
175
|
+
In addition to getting query results as an array of rows, you can also directly
|
176
|
+
iterate over the query results by providing a block to the different
|
177
|
+
`#query_xxx` methods:
|
178
|
+
|
179
|
+
```ruby
|
180
|
+
db.query('select * from foo') { |row| handle_row(row) }
|
181
|
+
```
|
182
|
+
|
183
|
+
### The Splat Query Mode
|
184
|
+
|
185
|
+
The splat query mode allows you to retrieve column values for each row without
|
186
|
+
wrapping them in a container. This is useful especially when performing queries
|
187
|
+
that return a single column:
|
188
|
+
|
189
|
+
```ruby
|
190
|
+
# When using the array mode we need to take unwrap the values
|
191
|
+
ids = db.query_array('select id from tasks where active = 1').map { |r| r.first }
|
192
|
+
|
193
|
+
# In splat mode we don't need to do that
|
194
|
+
ids = db.query_splat('select id from tasks where active = 1')
|
195
|
+
```
|
196
|
+
|
197
|
+
The splat mode is also useful when iterating over records with a block. The
|
198
|
+
column values are provided as splatted arguments to the given block:
|
199
|
+
|
200
|
+
```ruby
|
201
|
+
db.query_splat('select a, b, c from foo') do |a, b, c|
|
202
|
+
do_this_with(a, b)
|
203
|
+
do_that_with(c)
|
204
|
+
end
|
205
|
+
```
|
206
|
+
|
207
|
+
When iterating over records in this manner, the splat mode is slightly faster
|
208
|
+
than the array mode, and also reduces pressure on the Ruby GC since you avoid
|
209
|
+
allocating arrays or hashes to hold the column values.
|
210
|
+
|
211
|
+
## Parameter Binding
|
212
|
+
|
213
|
+
The `#execute` and `#query_xxx` methods accept parameters that can be bound to
|
214
|
+
the query, which means that their values will be used for each corresponding
|
215
|
+
place-holder (expressed using `?`) in the SQL statement:
|
179
216
|
|
180
217
|
```ruby
|
181
218
|
db.query('select x from my_table where y = ? and z = ?', 'foo', 'bar')
|
@@ -224,14 +261,14 @@ values:
|
|
224
261
|
- `String` (see below)
|
225
262
|
- nil
|
226
263
|
|
227
|
-
### Boolean
|
264
|
+
### Boolean Values
|
228
265
|
|
229
266
|
SQLite does not have a boolean data type. Extralite will automatically translate
|
230
267
|
bound parameter values of `true` or `false` to the integer values `1` and `0`,
|
231
268
|
respectively. Note that boolean values stored in the database will be fetched as
|
232
269
|
integers.
|
233
270
|
|
234
|
-
### String
|
271
|
+
### String Values
|
235
272
|
|
236
273
|
String parameter values are translated by Extralite to either `TEXT` or `BLOB`
|
237
274
|
values according to the string encoding used. Strings with an `ASCII-8BIT` are
|
@@ -269,12 +306,12 @@ db.query(transform, 'select * from foo')
|
|
269
306
|
#=> rows as instances of MyModel
|
270
307
|
```
|
271
308
|
|
272
|
-
When using the `
|
309
|
+
When using the `splat` mode, the different column values are passed as splatted
|
273
310
|
values to the transform proc:
|
274
311
|
|
275
312
|
```ruby
|
276
313
|
transform = ->(a, b, c) { { a:a, b: b, c: JSON.parse(c) } }
|
277
|
-
db.
|
314
|
+
db.query_splat(transform, 'select a, b, c from foo')
|
278
315
|
#=> transformed rows
|
279
316
|
```
|
280
317
|
|
@@ -325,16 +362,16 @@ three different modes: as a hash, an array or as individual column values. To
|
|
325
362
|
set the mode, you can use one of the `#prepare_xxx` methods:
|
326
363
|
|
327
364
|
```ruby
|
328
|
-
# hash mode
|
365
|
+
# hash mode (alias #prepare_hash)
|
329
366
|
db.prepare('select * from foo').to_a
|
330
367
|
#=> [{ x: 1, y: 2, z: 3}]
|
331
368
|
|
332
|
-
#
|
333
|
-
db.
|
369
|
+
# splat mode
|
370
|
+
db.prepare_splat('select x from foo').to_a
|
334
371
|
#=> [1]
|
335
372
|
|
336
|
-
#
|
337
|
-
db.
|
373
|
+
# array mode
|
374
|
+
db.prepare_array('select * from foo').to_a
|
338
375
|
#=> [[1, 2, 3]]
|
339
376
|
```
|
340
377
|
|
@@ -345,7 +382,7 @@ q = db.prepare('select * from foo')
|
|
345
382
|
q.to_a #=> [{ x: 1, y: 2, z: 3}]
|
346
383
|
|
347
384
|
q.mode #=> :hash
|
348
|
-
q.mode = :
|
385
|
+
q.mode = :array
|
349
386
|
q.to_a "=> [[1, 2, 3]]
|
350
387
|
```
|
351
388
|
|
@@ -368,12 +405,12 @@ query.next(10)
|
|
368
405
|
#=> [{ x: 1, y: 2, z: 3 }, { x: 4, y: 5, z: 6 }]
|
369
406
|
|
370
407
|
# Fetch the next row as an array
|
371
|
-
query = db.
|
408
|
+
query = db.prepare_array('select * from foo')
|
372
409
|
query.next
|
373
410
|
#=> [1, 2, 3]
|
374
411
|
|
375
412
|
# Fetch the next row as a single column
|
376
|
-
db.
|
413
|
+
db.prepare_splat('select z from foo').next
|
377
414
|
#=> 3
|
378
415
|
```
|
379
416
|
|
@@ -400,11 +437,11 @@ query = db.prepare('select * from foo')
|
|
400
437
|
query.each { |r| ... }
|
401
438
|
|
402
439
|
# iterate over records as arrays
|
403
|
-
query = db.
|
440
|
+
query = db.prepare_array('select * from foo')
|
404
441
|
query.each { |r| ... }
|
405
442
|
|
406
443
|
# iterate over records as single values
|
407
|
-
query = db.
|
444
|
+
query = db.prepare_splat('select a, b, c from foo')
|
408
445
|
query.each { |a, b, c| ... }
|
409
446
|
```
|
410
447
|
|
@@ -429,7 +466,7 @@ instantiate an iterator explicitly:
|
|
429
466
|
|
430
467
|
```ruby
|
431
468
|
# You need to pass the query to iterate over:
|
432
|
-
iterator = Extralite::Iterator(query)
|
469
|
+
iterator = Extralite::Iterator.new(query)
|
433
470
|
iterator.each { |r| ... }
|
434
471
|
```
|
435
472
|
|
@@ -437,7 +474,7 @@ iterator.each { |r| ... }
|
|
437
474
|
|
438
475
|
Prepared queries can automatically transform their result sets by setting a
|
439
476
|
transform block. The transform block receives values according to the query mode
|
440
|
-
(hash, array or
|
477
|
+
(hash, array or splat). To set a transform you can pass a block to one of the
|
441
478
|
`Database#prepare_xxx` methods, or use `Query#transform`:
|
442
479
|
|
443
480
|
```ruby
|
@@ -449,12 +486,12 @@ q = db.prepare('select * from items where id = ?')
|
|
449
486
|
q.transform { |h| Item.new(h) }
|
450
487
|
```
|
451
488
|
|
452
|
-
The same can be done for queries in `
|
489
|
+
The same can be done for queries in `splat` or `array` mode:
|
453
490
|
|
454
491
|
```ruby
|
455
|
-
db.
|
492
|
+
db.prepare_splat('select * from foo') { |a, b, c| a + b + c }
|
456
493
|
|
457
|
-
db.
|
494
|
+
db.prepare_array('select * from foo') { |a| a.map(&:to_s).join }
|
458
495
|
```
|
459
496
|
|
460
497
|
## Batch Execution of Queries
|
@@ -640,7 +677,7 @@ end
|
|
640
677
|
|
641
678
|
## Database Information
|
642
679
|
|
643
|
-
### Getting the
|
680
|
+
### Getting the List of Tables
|
644
681
|
|
645
682
|
To get the list of tables in a database, use the `#tables` method:
|
646
683
|
|
@@ -657,7 +694,7 @@ db.tables('foo')
|
|
657
694
|
#=> [...]
|
658
695
|
```
|
659
696
|
|
660
|
-
### Getting the
|
697
|
+
### Getting the Last Insert Row Id
|
661
698
|
|
662
699
|
```ruby
|
663
700
|
db.execute 'insert into foo values (?)', 42
|
@@ -665,7 +702,7 @@ db.last_insert_rowid
|
|
665
702
|
#=> 1
|
666
703
|
```
|
667
704
|
|
668
|
-
### Getting the
|
705
|
+
### Getting the Column Names for a Given Query
|
669
706
|
|
670
707
|
```ruby
|
671
708
|
db.columns('select a, b, c from foo')
|
@@ -1220,13 +1257,13 @@ code](https://github.com/digital-fabric/extralite/blob/main/test/perf_hash.rb)
|
|
1220
1257
|
### Rows as Arrays
|
1221
1258
|
|
1222
1259
|
[Benchmark source
|
1223
|
-
code](https://github.com/digital-fabric/extralite/blob/main/test/
|
1260
|
+
code](https://github.com/digital-fabric/extralite/blob/main/test/perf_array.rb)
|
1224
1261
|
|
1225
1262
|
|Row count|sqlite3 1.7.0|Extralite 2.5|Advantage|
|
1226
1263
|
|-:|-:|-:|-:|
|
1227
|
-
|10|
|
1228
|
-
|1K|
|
1229
|
-
|100K|
|
1264
|
+
|10|278.0K rows/s|493.6K rows/s|__1.78x__|
|
1265
|
+
|1K|608.6K rows/s|2692.2K rows/s|__4.42x__|
|
1266
|
+
|100K|502.9K rows/s|2564.0K rows/s|__5.10x__|
|
1230
1267
|
|
1231
1268
|
### Prepared Queries (Prepared Statements)
|
1232
1269
|
|
@@ -1239,7 +1276,7 @@ code](https://github.com/digital-fabric/extralite/blob/main/test/perf_hash_prepa
|
|
1239
1276
|
|1K|296.5K rows/s|2396.2K rows/s|__8.08x__|
|
1240
1277
|
|100K|145.9K rows/s|2107.3K rows/s|__14.45x__|
|
1241
1278
|
|
1242
|
-
As those benchmarks show, Extralite is capabale of reading up to 2.
|
1279
|
+
As those benchmarks show, Extralite is capabale of reading up to 2.7M rows per
|
1243
1280
|
second, and can be more than 14 times faster than the `sqlite3` gem.
|
1244
1281
|
|
1245
1282
|
Note that the benchmarks above were performed on synthetic data, in a
|
data/examples/kv_store.rb
CHANGED
@@ -24,7 +24,7 @@ class KVStore
|
|
24
24
|
end
|
25
25
|
|
26
26
|
def setup_queries
|
27
|
-
@q_get = @db.
|
27
|
+
@q_get = @db.prepare_splat('select value from kv where key = ?')
|
28
28
|
@q_set = @db.prepare('insert into kv (key, value) values($1, $2) on conflict (key) do update set value = $2')
|
29
29
|
end
|
30
30
|
|
@@ -42,7 +42,7 @@ class PubSub
|
|
42
42
|
|
43
43
|
def get_messages(&block)
|
44
44
|
# @db.execute('update subscribers set stamp = ? where id = ?', Time.now.to_i, @id)
|
45
|
-
@db.
|
45
|
+
@db.query_splat('delete from messages where subscriber_id = ? returning topic, message', @id, &block)
|
46
46
|
end
|
47
47
|
|
48
48
|
SCHEMA = <<~SQL
|
@@ -103,9 +103,9 @@ db2.pragma(journal_mode: :wal, synchronous: 1)
|
|
103
103
|
db3 = Extralite::Database.new(fn)
|
104
104
|
db3.pragma(journal_mode: :wal, synchronous: 1)
|
105
105
|
|
106
|
-
db1.on_progress
|
107
|
-
db2.on_progress
|
108
|
-
db3.on_progress
|
106
|
+
db1.on_progress { |b| b ? sleep(0.0001) : snooze }
|
107
|
+
db2.on_progress { |b| b ? sleep(0.0001) : snooze }
|
108
|
+
db3.on_progress { |b| b ? sleep(0.0001) : snooze }
|
109
109
|
|
110
110
|
producer = PubSub.new(db1)
|
111
111
|
producer.setup
|
@@ -163,7 +163,7 @@ end
|
|
163
163
|
|
164
164
|
db4 = Extralite::Database.new(fn)
|
165
165
|
db4.pragma(journal_mode: :wal, synchronous: 1)
|
166
|
-
db4.on_progress
|
166
|
+
db4.on_progress { |busy| busy ? sleep(0.05) : snooze }
|
167
167
|
|
168
168
|
last_t = Time.now
|
169
169
|
last_publish_count = 0
|
@@ -174,8 +174,8 @@ while true
|
|
174
174
|
elapsed = now - last_t
|
175
175
|
d_publish = publish_count - last_publish_count
|
176
176
|
d_receive = receive_count - last_receive_count
|
177
|
-
pending = db4.
|
178
|
-
puts "#{Time.now} publish: #{d_publish/elapsed}/s receive: #{d_receive/elapsed}/s pending: #{pending}"
|
177
|
+
pending = db4.query_single_splat('select count(*) from messages')
|
178
|
+
puts "#{Time.now} publish: #{(d_publish/elapsed).round}/s receive: #{(d_receive/elapsed).round}/s pending: #{pending} latency: #{pending / (d_receive/elapsed)}"
|
179
179
|
last_t = now
|
180
180
|
last_publish_count = publish_count
|
181
181
|
last_receive_count = receive_count
|
@@ -35,14 +35,14 @@ class PubSub
|
|
35
35
|
|
36
36
|
def get_messages(&block)
|
37
37
|
@db.transaction(:deferred) do
|
38
|
-
results = @db.
|
38
|
+
results = @db.query_array('select topic, message from messages where subscriber_id = ?', @id)
|
39
39
|
return [] if results.empty?
|
40
40
|
|
41
41
|
@db.execute('delete from messages where subscriber_id = ?', @id)
|
42
42
|
results
|
43
43
|
end
|
44
44
|
|
45
|
-
# messages = @db.
|
45
|
+
# messages = @db.query_array('delete from messages where subscriber_id = ? returning topic, message', @id)
|
46
46
|
# if block
|
47
47
|
# messages.each(&block)
|
48
48
|
# nil
|
@@ -196,7 +196,7 @@ while true
|
|
196
196
|
d_publish = publish_count - last_publish_count
|
197
197
|
d_receive = receive_count - last_receive_count
|
198
198
|
|
199
|
-
count = db4.
|
199
|
+
count = db4.query_single_splat('select count(*) from messages')
|
200
200
|
puts "#{Time.now} publish: #{d_publish/elapsed}/s receive: #{d_receive/elapsed}/s pending: #{count}"
|
201
201
|
last_t = now
|
202
202
|
last_publish_count = publish_count
|
data/ext/extralite/changeset.c
CHANGED
@@ -339,7 +339,7 @@ VALUE Changeset_to_a(VALUE self) {
|
|
339
339
|
|
340
340
|
// copied from: https://sqlite.org/sessionintro.html
|
341
341
|
static int xConflict(void *pCtx, int eConflict, sqlite3_changeset_iter *pIter){
|
342
|
-
|
342
|
+
long ret = (long)pCtx;
|
343
343
|
return ret;
|
344
344
|
}
|
345
345
|
|
data/ext/extralite/common.c
CHANGED
@@ -153,7 +153,7 @@ static inline VALUE row_to_hash(sqlite3_stmt *stmt, int column_count, VALUE colu
|
|
153
153
|
return row;
|
154
154
|
}
|
155
155
|
|
156
|
-
static inline VALUE
|
156
|
+
static inline VALUE row_to_array(sqlite3_stmt *stmt, int column_count) {
|
157
157
|
VALUE row = rb_ary_new2(column_count);
|
158
158
|
for (int i = 0; i < column_count; i++) {
|
159
159
|
VALUE value = get_column_value(stmt, i, sqlite3_column_type(stmt, i));
|
@@ -162,7 +162,7 @@ static inline VALUE row_to_ary(sqlite3_stmt *stmt, int column_count) {
|
|
162
162
|
return row;
|
163
163
|
}
|
164
164
|
|
165
|
-
static inline void
|
165
|
+
static inline void row_to_splat_values(sqlite3_stmt *stmt, int column_count, VALUE *values) {
|
166
166
|
for (int i = 0; i < column_count; i++) {
|
167
167
|
values[i] = get_column_value(stmt, i, sqlite3_column_type(stmt, i));
|
168
168
|
}
|
@@ -321,7 +321,7 @@ VALUE cleanup_stmt(query_ctx *ctx) {
|
|
321
321
|
return Qnil;
|
322
322
|
}
|
323
323
|
|
324
|
-
VALUE
|
324
|
+
VALUE safe_query_splat(query_ctx *ctx);
|
325
325
|
|
326
326
|
VALUE safe_query_hash(query_ctx *ctx) {
|
327
327
|
VALUE array = ROW_MULTI_P(ctx->row_mode) ? rb_ary_new() : Qnil;
|
@@ -369,13 +369,13 @@ VALUE safe_query_hash(query_ctx *ctx) {
|
|
369
369
|
RB_GC_GUARD(values[7])
|
370
370
|
|
371
371
|
#define ARGV_GET_ROW(ctx, column_count, argv_values, row, do_transform, return_rows) \
|
372
|
-
|
372
|
+
row_to_splat_values(ctx->stmt, column_count, argv_values); \
|
373
373
|
if (do_transform) \
|
374
374
|
row = rb_funcall2(ctx->transform_proc, ID_call, column_count, argv_values); \
|
375
375
|
else if (return_rows) \
|
376
376
|
row = column_count == 1 ? argv_values[0] : rb_ary_new_from_values(column_count, argv_values);
|
377
377
|
|
378
|
-
VALUE
|
378
|
+
VALUE safe_query_splat(query_ctx *ctx) {
|
379
379
|
VALUE array = ROW_MULTI_P(ctx->row_mode) ? rb_ary_new() : Qnil;
|
380
380
|
VALUE argv_values[MAX_ARGV_COLUMNS] = NIL_ARGV_VALUES;
|
381
381
|
VALUE row = Qnil;
|
@@ -413,7 +413,7 @@ VALUE safe_query_argv(query_ctx *ctx) {
|
|
413
413
|
return ROW_MULTI_P(ctx->row_mode) ? array : Qnil;
|
414
414
|
}
|
415
415
|
|
416
|
-
VALUE
|
416
|
+
VALUE safe_query_array(query_ctx *ctx) {
|
417
417
|
VALUE array = ROW_MULTI_P(ctx->row_mode) ? rb_ary_new() : Qnil;
|
418
418
|
VALUE row = Qnil;
|
419
419
|
int column_count = sqlite3_column_count(ctx->stmt);
|
@@ -421,7 +421,7 @@ VALUE safe_query_ary(query_ctx *ctx) {
|
|
421
421
|
int do_transform = !NIL_P(ctx->transform_proc);
|
422
422
|
|
423
423
|
while (stmt_iterate(ctx)) {
|
424
|
-
row =
|
424
|
+
row = row_to_array(ctx->stmt, column_count);
|
425
425
|
if (do_transform)
|
426
426
|
row = rb_funcall(ctx->transform_proc, ID_call, 1, row);
|
427
427
|
row_count++;
|
@@ -463,7 +463,7 @@ VALUE safe_query_single_row_hash(query_ctx *ctx) {
|
|
463
463
|
return row;
|
464
464
|
}
|
465
465
|
|
466
|
-
VALUE
|
466
|
+
VALUE safe_query_single_row_splat(query_ctx *ctx) {
|
467
467
|
VALUE argv_values[MAX_ARGV_COLUMNS] = NIL_ARGV_VALUES;
|
468
468
|
VALUE row = Qnil;
|
469
469
|
int column_count = sqlite3_column_count(ctx->stmt);
|
@@ -480,13 +480,13 @@ VALUE safe_query_single_row_argv(query_ctx *ctx) {
|
|
480
480
|
return row;
|
481
481
|
}
|
482
482
|
|
483
|
-
VALUE
|
483
|
+
VALUE safe_query_single_row_array(query_ctx *ctx) {
|
484
484
|
int column_count = sqlite3_column_count(ctx->stmt);
|
485
485
|
VALUE row = Qnil;
|
486
486
|
int do_transform = !NIL_P(ctx->transform_proc);
|
487
487
|
|
488
488
|
if (stmt_iterate(ctx)) {
|
489
|
-
row =
|
489
|
+
row = row_to_array(ctx->stmt, column_count);
|
490
490
|
if (do_transform)
|
491
491
|
row = rb_funcall(ctx->transform_proc, ID_call, 1, row);
|
492
492
|
}
|
@@ -498,8 +498,8 @@ VALUE safe_query_single_row_ary(query_ctx *ctx) {
|
|
498
498
|
enum batch_mode {
|
499
499
|
BATCH_EXECUTE,
|
500
500
|
BATCH_QUERY_HASH,
|
501
|
-
|
502
|
-
|
501
|
+
BATCH_QUERY_SPLAT,
|
502
|
+
BATCH_QUERY_ARRAY,
|
503
503
|
};
|
504
504
|
|
505
505
|
static inline VALUE batch_iterate_hash(query_ctx *ctx) {
|
@@ -522,14 +522,14 @@ static inline VALUE batch_iterate_hash(query_ctx *ctx) {
|
|
522
522
|
return rows;
|
523
523
|
}
|
524
524
|
|
525
|
-
static inline VALUE
|
525
|
+
static inline VALUE batch_iterate_array(query_ctx *ctx) {
|
526
526
|
VALUE rows = rb_ary_new();
|
527
527
|
VALUE row = Qnil;
|
528
528
|
int column_count = sqlite3_column_count(ctx->stmt);
|
529
529
|
int do_transform = !NIL_P(ctx->transform_proc);
|
530
530
|
|
531
531
|
while (stmt_iterate(ctx)) {
|
532
|
-
row =
|
532
|
+
row = row_to_array(ctx->stmt, column_count);
|
533
533
|
if (do_transform)
|
534
534
|
row = rb_funcall(ctx->transform_proc, ID_call, 1, row);
|
535
535
|
rb_ary_push(rows, row);
|
@@ -540,7 +540,7 @@ static inline VALUE batch_iterate_ary(query_ctx *ctx) {
|
|
540
540
|
return rows;
|
541
541
|
}
|
542
542
|
|
543
|
-
static inline VALUE
|
543
|
+
static inline VALUE batch_iterate_splat(query_ctx *ctx) {
|
544
544
|
VALUE rows = rb_ary_new();
|
545
545
|
VALUE argv_values[MAX_ARGV_COLUMNS] = NIL_ARGV_VALUES;
|
546
546
|
VALUE row = Qnil;
|
@@ -568,11 +568,11 @@ static inline void batch_iterate(query_ctx *ctx, enum batch_mode mode, VALUE *ro
|
|
568
568
|
case BATCH_QUERY_HASH:
|
569
569
|
*rows = batch_iterate_hash(ctx);
|
570
570
|
break;
|
571
|
-
case
|
572
|
-
*rows =
|
571
|
+
case BATCH_QUERY_SPLAT:
|
572
|
+
*rows = batch_iterate_splat(ctx);
|
573
573
|
break;
|
574
|
-
case
|
575
|
-
*rows =
|
574
|
+
case BATCH_QUERY_ARRAY:
|
575
|
+
*rows = batch_iterate_array(ctx);
|
576
576
|
break;
|
577
577
|
}
|
578
578
|
}
|
@@ -715,21 +715,21 @@ VALUE safe_batch_query(query_ctx *ctx) {
|
|
715
715
|
switch (ctx->query_mode) {
|
716
716
|
case QUERY_HASH:
|
717
717
|
return batch_run(ctx, BATCH_QUERY_HASH);
|
718
|
-
case
|
719
|
-
return batch_run(ctx,
|
720
|
-
case
|
721
|
-
return batch_run(ctx,
|
718
|
+
case QUERY_SPLAT:
|
719
|
+
return batch_run(ctx, BATCH_QUERY_SPLAT);
|
720
|
+
case QUERY_ARRAY:
|
721
|
+
return batch_run(ctx, BATCH_QUERY_ARRAY);
|
722
722
|
default:
|
723
723
|
rb_raise(cError, "Invalid query mode (safe_batch_query)");
|
724
724
|
}
|
725
725
|
}
|
726
726
|
|
727
|
-
VALUE
|
728
|
-
return batch_run(ctx,
|
727
|
+
VALUE safe_batch_query_array(query_ctx *ctx) {
|
728
|
+
return batch_run(ctx, BATCH_QUERY_ARRAY);
|
729
729
|
}
|
730
730
|
|
731
|
-
VALUE
|
732
|
-
return batch_run(ctx,
|
731
|
+
VALUE safe_batch_query_splat(query_ctx *ctx) {
|
732
|
+
return batch_run(ctx, BATCH_QUERY_SPLAT);
|
733
733
|
}
|
734
734
|
|
735
735
|
VALUE safe_query_columns(query_ctx *ctx) {
|