extralite 0.4 → 0.5

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: 8cdf5b562230dd1dc2e3dcc4083836c6d61ac4bfd51fdc12d7129ff57dc36148
4
- data.tar.gz: 1db604b9d586ed4f3ca45516ad25ed73c4d668407616c5657372074a7d0d13a8
3
+ metadata.gz: 8fa0672decf076e478bfd52359196baecbcf837e00cec91c7f9cf963b103af68
4
+ data.tar.gz: e54364225b96fc355a8198eab73c7a27848a672e04479a7eed06f724991ae238
5
5
  SHA512:
6
- metadata.gz: bca80a7a86e23651cf7c672a74bbc423b696b080155a1932378af4028d282260b079754d99c0e6e52e1ab7bd2ca9417c67fe285af8bcd7e090c9b4d764f0f6a5
7
- data.tar.gz: 74f35b4542eda30a6944403b1ea46d329a64deacf75a023bdae1ff718f7b0cce01278ffbc1e67f2a7a865d8fca44788454329d2aaedad69b402692c059ca8e90
6
+ metadata.gz: 9606a7e0154d61adc29150161a44018638f7e05a3c17f4f8e8b992e166ad0cd46705cb4eab2e9e6f7cc7f4d9eece8406e468822ff8a84116ff6f58cc493a89dd
7
+ data.tar.gz: fa5e4e1425187986ec097990f84ae103428645f94caaa41471305b414c78f15fb9522311b4eb50d40bc91c715f9e20e1c2fac18c0fd02892b41e75994602691d
data/CHANGELOG.md CHANGED
@@ -1,3 +1,7 @@
1
+ ## 0.5 2021-05-25
2
+
3
+ - Implement `Database#query_single_row`
4
+
1
5
  ## 0.4 2021-05-24
2
6
 
3
7
  - Add support for loading extensions
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- extralite (0.4)
4
+ extralite (0.5)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
data/README.md CHANGED
@@ -5,8 +5,8 @@ class with a minimal set of methods to interact with an SQLite3 database.
5
5
 
6
6
  ### Features
7
7
 
8
- - A variety of ways to get back query results: row as hash, row as array, single
9
- column, single value.
8
+ - A variety of methods for different data access patterns: row as hash, row as array, single
9
+ single row, single column, single value.
10
10
  - Iterate over records with a block, or collect records into an array.
11
11
  - Parameter binding.
12
12
  - Get last insert rowid.
@@ -34,6 +34,9 @@ db.query_ary('select 1, 2, 3') #=> [[1, 2, 3]]
34
34
  db.query_ary('select 1, 2, 3') { |r| p r }
35
35
  # [1, 2, 3]
36
36
 
37
+ # get a single row as a hash
38
+ db.query_single_column("select 1 as foo") #=> { :foo => 1 }
39
+
37
40
  # get single column query results as array of values
38
41
  db.query_single_column('select 42') #=> [42]
39
42
  # or iterate over results
@@ -3,6 +3,7 @@
3
3
  #include "../sqlite3/sqlite3.h"
4
4
 
5
5
  VALUE cError;
6
+ ID ID_STRIP;
6
7
 
7
8
  typedef struct Database_t {
8
9
  sqlite3 *sqlite3_db;
@@ -127,6 +128,15 @@ static inline VALUE row_to_hash(sqlite3_stmt *stmt, int column_count, VALUE colu
127
128
  return row;
128
129
  }
129
130
 
131
+ static inline VALUE row_to_ary(sqlite3_stmt *stmt, int column_count) {
132
+ VALUE row = rb_ary_new2(column_count);
133
+ for (int i = 0; i < column_count; i++) {
134
+ VALUE value = get_column_value(stmt, i, sqlite3_column_type(stmt, i));
135
+ rb_ary_push(row, value);
136
+ }
137
+ return row;
138
+ }
139
+
130
140
  inline void prepare_multi_stmt(sqlite3 *db, sqlite3_stmt **stmt, VALUE sql) {
131
141
  const char *rest = 0;
132
142
  const char *ptr = RSTRING_PTR(sql);
@@ -165,7 +175,9 @@ VALUE Database_query_hash(int argc, VALUE *argv, VALUE self) {
165
175
  VALUE sql;
166
176
 
167
177
  rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
168
- sql = argv[0];
178
+ sql = rb_funcall(argv[0], ID_STRIP, 0);
179
+ if (RSTRING_LEN(sql) == 0) return Qnil;
180
+
169
181
  GetDatabase(self, db);
170
182
 
171
183
  prepare_multi_stmt(db->sqlite3_db, &stmt, sql);
@@ -203,15 +215,6 @@ step:
203
215
  return result;
204
216
  }
205
217
 
206
- static inline VALUE row_to_ary(sqlite3_stmt *stmt, int column_count) {
207
- VALUE row = rb_ary_new2(column_count);
208
- for (int i = 0; i < column_count; i++) {
209
- VALUE value = get_column_value(stmt, i, sqlite3_column_type(stmt, i));
210
- rb_ary_push(row, value);
211
- }
212
- return row;
213
- }
214
-
215
218
  VALUE Database_query_ary(int argc, VALUE *argv, VALUE self) {
216
219
  int rc;
217
220
  sqlite3_stmt* stmt;
@@ -223,7 +226,8 @@ VALUE Database_query_ary(int argc, VALUE *argv, VALUE self) {
223
226
  VALUE sql;
224
227
 
225
228
  rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
226
- sql = argv[0];
229
+ sql = rb_funcall(argv[0], ID_STRIP, 0);
230
+ if (RSTRING_LEN(sql) == 0) return Qnil;
227
231
  GetDatabase(self, db);
228
232
 
229
233
  prepare_multi_stmt(db->sqlite3_db, &stmt, sql);
@@ -257,6 +261,47 @@ step:
257
261
  return result;
258
262
  }
259
263
 
264
+ VALUE Database_query_single_row(int argc, VALUE *argv, VALUE self) {
265
+ int rc;
266
+ sqlite3_stmt* stmt;
267
+ int column_count;
268
+ Database_t *db;
269
+ VALUE sql;
270
+ VALUE row = Qnil;
271
+ VALUE column_names;
272
+
273
+ rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
274
+ sql = rb_funcall(argv[0], ID_STRIP, 0);
275
+ if (RSTRING_LEN(sql) == 0) return Qnil;
276
+
277
+ GetDatabase(self, db);
278
+
279
+ prepare_multi_stmt(db->sqlite3_db, &stmt, sql);
280
+ bind_all_parameters(stmt, argc, argv);
281
+ column_count = sqlite3_column_count(stmt);
282
+ column_names = get_column_names(stmt, column_count);
283
+
284
+ rc = sqlite3_step(stmt);
285
+ switch (rc) {
286
+ case SQLITE_ROW:
287
+ row = row_to_hash(stmt, column_count, column_names);
288
+ break;
289
+ case SQLITE_DONE:
290
+ break;
291
+ case SQLITE_BUSY:
292
+ rb_raise(cError, "Database is busy");
293
+ case SQLITE_ERROR:
294
+ rb_raise(cError, "%s", sqlite3_errmsg(db->sqlite3_db));
295
+ default:
296
+ rb_raise(cError, "Invalid return code for sqlite3_step: %d", rc);
297
+ }
298
+
299
+ sqlite3_finalize(stmt);
300
+ RB_GC_GUARD(row);
301
+ RB_GC_GUARD(column_names);
302
+ return row;
303
+ }
304
+
260
305
  VALUE Database_query_single_column(int argc, VALUE *argv, VALUE self) {
261
306
  int rc;
262
307
  sqlite3_stmt* stmt;
@@ -268,7 +313,9 @@ VALUE Database_query_single_column(int argc, VALUE *argv, VALUE self) {
268
313
  VALUE value;
269
314
 
270
315
  rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
271
- sql = argv[0];
316
+ sql = rb_funcall(argv[0], ID_STRIP, 0);
317
+ if (RSTRING_LEN(sql) == 0) return Qnil;
318
+
272
319
  GetDatabase(self, db);
273
320
 
274
321
  prepare_multi_stmt(db->sqlite3_db, &stmt, sql);
@@ -281,7 +328,6 @@ VALUE Database_query_single_column(int argc, VALUE *argv, VALUE self) {
281
328
  if (!yield_to_block) result = rb_ary_new();
282
329
  step:
283
330
  rc = sqlite3_step(stmt);
284
- printf("rc=%d\n", rc);
285
331
  switch (rc) {
286
332
  case SQLITE_ROW:
287
333
  value = get_column_value(stmt, 0, sqlite3_column_type(stmt, 0));
@@ -315,7 +361,9 @@ VALUE Database_query_single_value(int argc, VALUE *argv, VALUE self) {
315
361
  VALUE value = Qnil;
316
362
 
317
363
  rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
318
- sql = argv[0];
364
+ sql = rb_funcall(argv[0], ID_STRIP, 0);
365
+ if (RSTRING_LEN(sql) == 0) return Qnil;
366
+
319
367
  GetDatabase(self, db);
320
368
 
321
369
  prepare_multi_stmt(db->sqlite3_db, &stmt, sql);
@@ -329,6 +377,8 @@ VALUE Database_query_single_value(int argc, VALUE *argv, VALUE self) {
329
377
  case SQLITE_ROW:
330
378
  value = get_column_value(stmt, 0, sqlite3_column_type(stmt, 0));
331
379
  break;
380
+ case SQLITE_DONE:
381
+ break;
332
382
  case SQLITE_BUSY:
333
383
  rb_raise(cError, "Database is busy");
334
384
  case SQLITE_ERROR:
@@ -400,6 +450,7 @@ void Init_Extralite() {
400
450
  rb_define_method(cDatabase, "query", Database_query_hash, -1);
401
451
  rb_define_method(cDatabase, "query_hash", Database_query_hash, -1);
402
452
  rb_define_method(cDatabase, "query_ary", Database_query_ary, -1);
453
+ rb_define_method(cDatabase, "query_single_row", Database_query_single_row, -1);
403
454
  rb_define_method(cDatabase, "query_single_column", Database_query_single_column, -1);
404
455
  rb_define_method(cDatabase, "query_single_value", Database_query_single_value, -1);
405
456
 
@@ -410,4 +461,5 @@ void Init_Extralite() {
410
461
  rb_define_method(cDatabase, "load_extension", Database_load_extension, 1);
411
462
 
412
463
  cError = rb_define_class_under(mExtralite, "Error", rb_eRuntimeError);
464
+ ID_STRIP = rb_intern("strip");
413
465
  }
@@ -1,3 +1,3 @@
1
1
  module Extralite
2
- VERSION = '0.4'
2
+ VERSION = '0.5'
3
3
  end
@@ -19,26 +19,49 @@ class DatabaseTest < MiniTest::Test
19
19
  def test_query
20
20
  r = @db.query('select * from t')
21
21
  assert_equal [{x: 1, y: 2, z: 3}, {x: 4, y: 5, z: 6}], r
22
+
23
+ r = @db.query('select * from t where x = 2')
24
+ assert_equal [], r
22
25
  end
23
26
 
24
27
  def test_query_hash
25
28
  r = @db.query_hash('select * from t')
26
29
  assert_equal [{x: 1, y: 2, z: 3}, {x: 4, y: 5, z: 6}], r
30
+
31
+ r = @db.query_hash('select * from t where x = 2')
32
+ assert_equal [], r
27
33
  end
28
34
 
29
35
  def test_query_ary
30
36
  r = @db.query_ary('select * from t')
31
37
  assert_equal [[1, 2, 3], [4, 5, 6]], r
38
+
39
+ r = @db.query_ary('select * from t where x = 2')
40
+ assert_equal [], r
41
+ end
42
+
43
+ def test_query_single_row
44
+ r = @db.query_single_row('select * from t order by x desc limit 1')
45
+ assert_equal({ x: 4, y: 5, z: 6 }, r)
46
+
47
+ r = @db.query_single_row('select * from t where x = 2')
48
+ assert_nil r
32
49
  end
33
50
 
34
51
  def test_query_single_column
35
52
  r = @db.query_single_column('select y from t')
36
53
  assert_equal [2, 5], r
37
- end
54
+
55
+ r = @db.query_single_column('select y from t where x = 2')
56
+ assert_equal [], r
57
+ end
38
58
 
39
59
  def test_query_single_value
40
60
  r = @db.query_single_value('select z from t order by Z desc limit 1')
41
61
  assert_equal 6, r
62
+
63
+ r = @db.query_single_value('select z from t where x = 2')
64
+ assert_nil r
42
65
  end
43
66
 
44
67
  def test_transaction_active?
@@ -54,4 +77,12 @@ class DatabaseTest < MiniTest::Test
54
77
 
55
78
  assert_equal [1, 4, 'a', 'd'], @db.query_single_column('select x from t order by x')
56
79
  end
80
+
81
+ def test_empty_sql
82
+ r = @db.query(' ')
83
+ assert_nil r
84
+
85
+ r = @db.query('select 1 as foo; ')
86
+ assert_equal [{ foo: 1 }], r
87
+ end
57
88
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: extralite
3
3
  version: !ruby/object:Gem::Version
4
- version: '0.4'
4
+ version: '0.5'
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sharon Rosner
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-05-24 00:00:00.000000000 Z
11
+ date: 2021-05-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake-compiler