extralite 0.4 → 0.5

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: 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