extralite 1.7 → 1.10

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: cf088c359bb74b23020c8cb290cb6c65d06cedd885e4421c3e81f3c21a31ca33
4
- data.tar.gz: a14199c2f5d07068a1a57eb0b24119964aa7a9960f23e6cb58bac39fe535dbfa
3
+ metadata.gz: e1dbf79f19c8e1a1b31da57db9e1b20eb32efed2a510dfd1a19df048ecdf6532
4
+ data.tar.gz: 633afbfd7042dedb38a5275d525bf9876a8cd194e6b6f95db183d78019c53816
5
5
  SHA512:
6
- metadata.gz: '009ccdd0998a39df02718feeecf981eb03dbf55d0dd6b2d0b8bcfb66754a0ec8fcc2ee9e4e9a2b421a63ed6fa89ae29f7c748ca370d32dae2199a01e50febabc'
7
- data.tar.gz: e0fc9eb0f8a69dd2017c4d821430a861535fecc2c51e937c58d471098cc0c815867f514a357e2a0572eb848e02e97fac9454116b3cac2ff21abb0e479241552e
6
+ metadata.gz: 9987a2e1b14e9213a289d04d79a0914e6d3a843c5af94e4d57d6839f193b8294b57b280141dd4784419d9f920d8b1ee32f9a21efee56a85ff524128bc4262aed
7
+ data.tar.gz: 2b53f9dd796f37e7c901f88b5bfe2b28463c0465ff5aaf0ade160b1ecf95f0beb7b0cd56496e3c76bd4f754ef7649bf8a704ff7eb94053a7b7f1b1099cf31a5b
@@ -0,0 +1 @@
1
+ github: ciconia
data/CHANGELOG.md CHANGED
@@ -1,3 +1,15 @@
1
+ ## 1.10 2021-12-15
2
+
3
+ - Fix mutliple parameter binding with hash
4
+
5
+ ## 1.9 2021-12-15
6
+
7
+ - Add support for reading BLOBs
8
+
9
+ ## 1.8.2 2021-12-15
10
+
11
+ - Add documentation
12
+
1
13
  ## 1.7 2021-12-13
2
14
 
3
15
  - Add extralite Sequel adapter
data/Gemfile.lock CHANGED
@@ -1,60 +1,37 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- extralite (1.7)
4
+ extralite (1.10)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
8
8
  specs:
9
- ast (2.4.2)
10
- coderay (1.1.3)
11
9
  docile (1.4.0)
12
10
  json (2.5.1)
13
- method_source (1.0.0)
14
- minitest (5.14.4)
15
- parallel (1.20.1)
16
- parser (3.0.1.1)
17
- ast (~> 2.4.1)
18
- pry (0.13.1)
19
- coderay (~> 1.1)
20
- method_source (~> 1.0)
21
- rainbow (3.0.0)
22
- rake (13.0.3)
23
- rake-compiler (1.1.1)
11
+ minitest (5.15.0)
12
+ rake (13.0.6)
13
+ rake-compiler (1.1.6)
24
14
  rake
25
- regexp_parser (2.1.1)
26
- rexml (3.2.5)
27
- rubocop (0.85.1)
28
- parallel (~> 1.10)
29
- parser (>= 2.7.0.1)
30
- rainbow (>= 2.2.2, < 4.0)
31
- regexp_parser (>= 1.7)
32
- rexml
33
- rubocop-ast (>= 0.0.3)
34
- ruby-progressbar (~> 1.7)
35
- unicode-display_width (>= 1.4.0, < 2.0)
36
- rubocop-ast (1.5.0)
37
- parser (>= 3.0.1.1)
38
- ruby-progressbar (1.11.0)
39
15
  sequel (5.51.0)
40
16
  simplecov (0.17.1)
41
17
  docile (~> 1.1)
42
18
  json (>= 1.8, < 3)
43
19
  simplecov-html (~> 0.10.0)
44
20
  simplecov-html (0.10.2)
45
- unicode-display_width (1.7.0)
21
+ webrick (1.7.0)
22
+ yard (0.9.27)
23
+ webrick (~> 1.7.0)
46
24
 
47
25
  PLATFORMS
48
26
  ruby
49
27
 
50
28
  DEPENDENCIES
51
29
  extralite!
52
- minitest (= 5.14.4)
53
- pry (= 0.13.1)
54
- rake-compiler (= 1.1.1)
55
- rubocop (= 0.85.1)
30
+ minitest (= 5.15.0)
31
+ rake-compiler (= 1.1.6)
56
32
  sequel (= 5.51.0)
57
33
  simplecov (= 0.17.1)
34
+ yard (= 0.9.27)
58
35
 
59
36
  BUNDLED WITH
60
37
  2.1.4
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # Extralite - a Ruby gem for working with SQLite3 databases
1
+ # Extralite - a fast Ruby gem for working with SQLite3 databases
2
2
 
3
3
  [![Gem Version](https://badge.fury.io/rb/extralite.svg)](http://rubygems.org/gems/extralite)
4
4
  [![Modulation Test](https://github.com/digital-fabric/extralite/workflows/Tests/badge.svg)](https://github.com/digital-fabric/extralite/actions?query=workflow%3ATests)
@@ -6,9 +6,9 @@
6
6
 
7
7
  ## What is Extralite?
8
8
 
9
- Extralite is an extra-lightweight (less than 430 lines of C-code) SQLite3
10
- wrapper for Ruby. It provides a single class with a minimal set of methods to
11
- interact with an SQLite3 database.
9
+ Extralite is a fast, extra-lightweight (less than 460 lines of C-code) SQLite3
10
+ wrapper for Ruby. It provides a single class with a minimal set of methods for
11
+ interacting with an SQLite3 database.
12
12
 
13
13
  ## Features
14
14
 
@@ -73,7 +73,7 @@ db.query('select * from foo where bar = :bar', 'bar' => 42)
73
73
  db.query('select * from foo where bar = :bar', ':bar' => 42)
74
74
 
75
75
  # get last insert rowid
76
- rowid = db.last_insert_id
76
+ rowid = db.last_insert_rowid
77
77
 
78
78
  # get number of rows changed in last query
79
79
  number_of_rows_affected = db.changes
@@ -127,7 +127,7 @@ Here's a table summarizing the differences between the two gems:
127
127
  |custom collations|yes|no|
128
128
  |custom aggregate functions|yes|no|
129
129
  |Multithread friendly|no|[yes](#what-about-concurrency)|
130
- |Code size|~2650LoC|~500LoC|
130
+ |Code size|~2650LoC|~530LoC|
131
131
  |Performance|1x|1.5x to 12.5x (see [below](#performance))|
132
132
 
133
133
  ## What about concurrency?
@@ -140,23 +140,33 @@ performance:
140
140
 
141
141
  ## Performance
142
142
 
143
- A benchmark script is
144
- [included](https://github.com/digital-fabric/extralite/blob/main/test/perf.rb),
145
- creating a table of various row counts, then fetching the entire table using
146
- either `sqlite3` or `extralite`. This benchmark shows Extralite to be up to 12.5
147
- times faster than `sqlite3` when fetching a large number of rows. Here are the
148
- results (using the `sqlite3` gem performance as baseline):
143
+ A benchmark script is included, creating a table of various row counts, then
144
+ fetching the entire table using either `sqlite3` or `extralite`. This benchmark
145
+ shows Extralite to be up to 12.5 times faster than `sqlite3` when fetching a
146
+ large number of rows. Here are the [results for fetching rows as hashes](https://github.com/digital-fabric/extralite/blob/main/test/perf_hash.rb):
149
147
 
150
- |Row count|sqlite3-ruby (baseline)|Extralite (relative - rounded)|
151
- |-:|-:|-:|
152
- |10|1x|1.5x|
153
- |1K|1x|7x|
154
- |100K|1x|12.5x|
148
+ |Row count|sqlite3-ruby|Extralite|Advantage|
149
+ |-:|-:|-:|-:|
150
+ |10|57620 rows/s|95340 rows/s|__1.65x__|
151
+ |1K|286.8K rows/s|2106.4 rows/s|__7.35x__|
152
+ |100K|181K rows/s|2275.3K rows/s|__12.53x__|
153
+
154
+ When [fetching rows as arrays](https://github.com/digital-fabric/extralite/blob/main/test/perf_ary.rb) Extralite also significantly outperforms sqlite3-ruby:
155
+
156
+ |Row count|sqlite3-ruby|Extralite|Advantage|
157
+ |-:|-:|-:|-:|
158
+ |10|64365 rows/s|94031 rows/s|__1.46x__|
159
+ |1K|498.9K rows/s|2478.2K rows/s|__4.97x__|
160
+ |100K|441.1K rows/s|3023.4K rows/s|__6.85x__|
155
161
 
156
162
  (If you're interested in checking this yourself, just run the script and let me
157
- know if your results are different.)
163
+ know if your results are better/worse.)
164
+
165
+ As those benchmarks show, Extralite is capabale of reading more than 3M
166
+ rows/second (when fetching rows as arrays), and more than 2.2M rows/second (when
167
+ fetching rows as hashes.)
158
168
 
159
169
  ## Contributing
160
170
 
161
171
  Contributions in the form of issues, PRs or comments will be greatly
162
- appreciated!
172
+ appreciated!
data/Rakefile CHANGED
@@ -1,18 +1,27 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "bundler/gem_tasks"
4
- require "rake/clean"
3
+ require 'bundler/gem_tasks'
4
+ require 'rake/clean'
5
5
 
6
- require "rake/extensiontask"
7
- Rake::ExtensionTask.new("extralite_ext") do |ext|
8
- ext.ext_dir = "ext/extralite"
6
+ require 'rake/extensiontask'
7
+ Rake::ExtensionTask.new('extralite_ext') do |ext|
8
+ ext.ext_dir = 'ext/extralite'
9
9
  end
10
10
 
11
11
  task :recompile => [:clean, :compile]
12
12
 
13
- task :default => [:compile, :test]
13
+ task :default => [:compile, :doc, :test]
14
+ task :doc => :yard
14
15
  task :test do
15
16
  exec 'ruby test/run.rb'
16
17
  end
17
18
 
18
- CLEAN.include "**/*.o", "**/*.so", "**/*.so.*", "**/*.a", "**/*.bundle", "**/*.jar", "pkg", "tmp"
19
+ CLEAN.include '**/*.o', '**/*.so', '**/*.so.*', '**/*.a', '**/*.bundle', '**/*.jar', 'pkg', 'tmp'
20
+
21
+ require 'yard'
22
+ YARD_FILES = FileList['ext/extralite/extralite.c', 'lib/extralite.rb', 'lib/sequel/adapters/extralite.rb']
23
+
24
+ YARD::Rake::YardocTask.new do |t|
25
+ t.files = YARD_FILES
26
+ t.options = %w(-o doc --readme README.md)
27
+ end
@@ -51,6 +51,10 @@ static VALUE Database_allocate(VALUE klass) {
51
51
  } \
52
52
  }
53
53
 
54
+ /* call-seq: initialize(path)
55
+ *
56
+ * Initializes a new SQLite database with the given path.
57
+ */
54
58
 
55
59
  VALUE Database_initialize(VALUE self, VALUE path) {
56
60
  int rc;
@@ -72,6 +76,10 @@ VALUE Database_initialize(VALUE self, VALUE path) {
72
76
  return Qnil;
73
77
  }
74
78
 
79
+ /* call-seq: close
80
+ *
81
+ * Closes the database.
82
+ */
75
83
  VALUE Database_close(VALUE self) {
76
84
  int rc;
77
85
  Database_t *db;
@@ -86,6 +94,10 @@ VALUE Database_close(VALUE self) {
86
94
  return self;
87
95
  }
88
96
 
97
+ /* call-seq: closed?
98
+ *
99
+ * Returns true if the database is closed.
100
+ */
89
101
  VALUE Database_closed_p(VALUE self) {
90
102
  Database_t *db;
91
103
  GetDatabase(self, db);
@@ -104,7 +116,7 @@ inline VALUE get_column_value(sqlite3_stmt *stmt, int col, int type) {
104
116
  case SQLITE_TEXT:
105
117
  return rb_str_new_cstr((char *)sqlite3_column_text(stmt, col));
106
118
  case SQLITE_BLOB:
107
- rb_raise(cError, "BLOB reading not yet implemented");
119
+ return rb_str_new((const char *)sqlite3_column_blob(stmt, col), (long)sqlite3_column_bytes(stmt, col));
108
120
  default:
109
121
  rb_raise(cError, "Unknown column type: %d", type);
110
122
  }
@@ -124,16 +136,16 @@ static inline void bind_hash_parameter_values(sqlite3_stmt *stmt, VALUE hash) {
124
136
  switch (TYPE(k)) {
125
137
  case T_FIXNUM:
126
138
  bind_parameter_value(stmt, NUM2INT(k), v);
127
- return;
139
+ break;
128
140
  case T_SYMBOL:
129
141
  k = rb_funcall(k, ID_TO_S, 0);
130
142
  case T_STRING:
131
143
  if(RSTRING_PTR(k)[0] != ':') k = rb_str_plus(rb_str_new2(":"), k);
132
144
  int pos = sqlite3_bind_parameter_index(stmt, StringValuePtr(k));
133
145
  bind_parameter_value(stmt, pos, v);
134
- return;
146
+ break;
135
147
  default:
136
- rb_raise(cError, "Cannot bind hash key value idx %d", i);
148
+ rb_raise(cError, "Cannot bind hash key value idx %d", i);
137
149
  }
138
150
  }
139
151
  RB_GC_GUARD(keys);
@@ -342,6 +354,29 @@ VALUE safe_query_hash(VALUE arg) {
342
354
  return result;
343
355
  }
344
356
 
357
+ /* call-seq:
358
+ * query(sql, *parameters, &block)
359
+ * query_hash(sql, *parameters, &block)
360
+ *
361
+ * Runs a query returning rows as hashes (with symbol keys). If a block is
362
+ * given, it will be called for each row. Otherwise, an array containing all
363
+ * rows is returned.
364
+ *
365
+ * Query parameters to be bound to placeholders in the query can be specified as
366
+ * a list of values or as a hash mapping parameter names to values. When
367
+ * parameters are given as a least, the query should specify parameters using
368
+ * `?`:
369
+ *
370
+ * db.query('select * from foo where x = ?', 42)
371
+ *
372
+ * Named placeholders are specified using `:`. The placeholder values are
373
+ * specified using a hash, where keys are either strings are symbols. String
374
+ * keys can include or omit the `:` prefix. The following are equivalent:
375
+ *
376
+ * db.query('select * from foo where x = :bar', bar: 42)
377
+ * db.query('select * from foo where x = :bar', 'bar' => 42)
378
+ * db.query('select * from foo where x = :bar', ':bar' => 42)
379
+ */
345
380
  VALUE Database_query_hash(int argc, VALUE *argv, VALUE self) {
346
381
  query_ctx ctx = { self, argc, argv, 0 };
347
382
  return rb_ensure(safe_query_hash, (VALUE)&ctx, cleanup_stmt, (VALUE)&ctx);
@@ -376,6 +411,26 @@ VALUE safe_query_ary(VALUE arg) {
376
411
  return result;
377
412
  }
378
413
 
414
+ /* call-seq: query_ary(sql, *parameters, &block)
415
+ *
416
+ * Runs a query returning rows as arrays. If a block is given, it will be called
417
+ * for each row. Otherwise, an array containing all rows is returned.
418
+ *
419
+ * Query parameters to be bound to placeholders in the query can be specified as
420
+ * a list of values or as a hash mapping parameter names to values. When
421
+ * parameters are given as a least, the query should specify parameters using
422
+ * `?`:
423
+ *
424
+ * db.query_ary('select * from foo where x = ?', 42)
425
+ *
426
+ * Named placeholders are specified using `:`. The placeholder values are
427
+ * specified using a hash, where keys are either strings are symbols. String
428
+ * keys can include or omit the `:` prefix. The following are equivalent:
429
+ *
430
+ * db.query_ary('select * from foo where x = :bar', bar: 42)
431
+ * db.query_ary('select * from foo where x = :bar', 'bar' => 42)
432
+ * db.query_ary('select * from foo where x = :bar', ':bar' => 42)
433
+ */
379
434
  VALUE Database_query_ary(int argc, VALUE *argv, VALUE self) {
380
435
  query_ctx ctx = { self, argc, argv, 0 };
381
436
  return rb_ensure(safe_query_ary, (VALUE)&ctx, cleanup_stmt, (VALUE)&ctx);
@@ -405,6 +460,25 @@ VALUE safe_query_single_row(VALUE arg) {
405
460
  return row;
406
461
  }
407
462
 
463
+ /* call-seq: query_single_row(sql, *parameters)
464
+ *
465
+ * Runs a query returning a single row as a hash.
466
+ *
467
+ * Query parameters to be bound to placeholders in the query can be specified as
468
+ * a list of values or as a hash mapping parameter names to values. When
469
+ * parameters are given as a least, the query should specify parameters using
470
+ * `?`:
471
+ *
472
+ * db.query_single_row('select * from foo where x = ?', 42)
473
+ *
474
+ * Named placeholders are specified using `:`. The placeholder values are
475
+ * specified using a hash, where keys are either strings are symbols. String
476
+ * keys can include or omit the `:` prefix. The following are equivalent:
477
+ *
478
+ * db.query_single_row('select * from foo where x = :bar', bar: 42)
479
+ * db.query_single_row('select * from foo where x = :bar', 'bar' => 42)
480
+ * db.query_single_row('select * from foo where x = :bar', ':bar' => 42)
481
+ */
408
482
  VALUE Database_query_single_row(int argc, VALUE *argv, VALUE self) {
409
483
  query_ctx ctx = { self, argc, argv, 0 };
410
484
  return rb_ensure(safe_query_single_row, (VALUE)&ctx, cleanup_stmt, (VALUE)&ctx);
@@ -442,6 +516,26 @@ VALUE safe_query_single_column(VALUE arg) {
442
516
  return result;
443
517
  }
444
518
 
519
+ /* call-seq: query_single_column(sql, *parameters, &block)
520
+ *
521
+ * Runs a query returning single column values. If a block is given, it will be called
522
+ * for each value. Otherwise, an array containing all values is returned.
523
+ *
524
+ * Query parameters to be bound to placeholders in the query can be specified as
525
+ * a list of values or as a hash mapping parameter names to values. When
526
+ * parameters are given as a least, the query should specify parameters using
527
+ * `?`:
528
+ *
529
+ * db.query_single_column('select x from foo where x = ?', 42)
530
+ *
531
+ * Named placeholders are specified using `:`. The placeholder values are
532
+ * specified using a hash, where keys are either strings are symbols. String
533
+ * keys can include or omit the `:` prefix. The following are equivalent:
534
+ *
535
+ * db.query_single_column('select x from foo where x = :bar', bar: 42)
536
+ * db.query_single_column('select x from foo where x = :bar', 'bar' => 42)
537
+ * db.query_single_column('select x from foo where x = :bar', ':bar' => 42)
538
+ */
445
539
  VALUE Database_query_single_column(int argc, VALUE *argv, VALUE self) {
446
540
  query_ctx ctx = { self, argc, argv, 0 };
447
541
  return rb_ensure(safe_query_single_column, (VALUE)&ctx, cleanup_stmt, (VALUE)&ctx);
@@ -470,11 +564,34 @@ VALUE safe_query_single_value(VALUE arg) {
470
564
  return value;
471
565
  }
472
566
 
567
+ /* call-seq: query_single_value(sql, *parameters)
568
+ *
569
+ * Runs a query returning a single value from the first row.
570
+ *
571
+ * Query parameters to be bound to placeholders in the query can be specified as
572
+ * a list of values or as a hash mapping parameter names to values. When
573
+ * parameters are given as a least, the query should specify parameters using
574
+ * `?`:
575
+ *
576
+ * db.query_single_value('select x from foo where x = ?', 42)
577
+ *
578
+ * Named placeholders are specified using `:`. The placeholder values are
579
+ * specified using a hash, where keys are either strings are symbols. String
580
+ * keys can include or omit the `:` prefix. The following are equivalent:
581
+ *
582
+ * db.query_single_value('select x from foo where x = :bar', bar: 42)
583
+ * db.query_single_value('select x from foo where x = :bar', 'bar' => 42)
584
+ * db.query_single_value('select x from foo where x = :bar', ':bar' => 42)
585
+ */
473
586
  VALUE Database_query_single_value(int argc, VALUE *argv, VALUE self) {
474
587
  query_ctx ctx = { self, argc, argv, 0 };
475
588
  return rb_ensure(safe_query_single_value, (VALUE)&ctx, cleanup_stmt, (VALUE)&ctx);
476
589
  }
477
590
 
591
+ /* call-seq: last_insert_rowid
592
+ *
593
+ * Returns the rowid of the last inserted row.
594
+ */
478
595
  VALUE Database_last_insert_rowid(VALUE self) {
479
596
  Database_t *db;
480
597
  GetOpenDatabase(self, db);
@@ -482,6 +599,10 @@ VALUE Database_last_insert_rowid(VALUE self) {
482
599
  return INT2NUM(sqlite3_last_insert_rowid(db->sqlite3_db));
483
600
  }
484
601
 
602
+ /* call-seq: changes
603
+ *
604
+ * Returns the number of changes made to the database by the last operation.
605
+ */
485
606
  VALUE Database_changes(VALUE self) {
486
607
  Database_t *db;
487
608
  GetOpenDatabase(self, db);
@@ -489,6 +610,10 @@ VALUE Database_changes(VALUE self) {
489
610
  return INT2NUM(sqlite3_changes(db->sqlite3_db));
490
611
  }
491
612
 
613
+ /* call-seq: filename
614
+ *
615
+ * Returns the database filename.
616
+ */
492
617
  VALUE Database_filename(int argc, VALUE *argv, VALUE self) {
493
618
  const char *db_name;
494
619
  const char *filename;
@@ -501,6 +626,10 @@ VALUE Database_filename(int argc, VALUE *argv, VALUE self) {
501
626
  return filename ? rb_str_new_cstr(filename) : Qnil;
502
627
  }
503
628
 
629
+ /* call-seq: transaction_active?
630
+ *
631
+ * Returns true if a transaction is currently in progress.
632
+ */
504
633
  VALUE Database_transaction_active_p(VALUE self) {
505
634
  Database_t *db;
506
635
  GetOpenDatabase(self, db);
@@ -508,6 +637,10 @@ VALUE Database_transaction_active_p(VALUE self) {
508
637
  return sqlite3_get_autocommit(db->sqlite3_db) ? Qfalse : Qtrue;
509
638
  }
510
639
 
640
+ /* call-seq: load_extension(path)
641
+ *
642
+ * Loads an extension with the given path.
643
+ */
511
644
  VALUE Database_load_extension(VALUE self, VALUE path) {
512
645
  Database_t *db;
513
646
  GetOpenDatabase(self, db);
data/extralite.gemspec CHANGED
@@ -11,7 +11,7 @@ Gem::Specification.new do |s|
11
11
  s.homepage = 'https://github.com/digital-fabric/extralite'
12
12
  s.metadata = {
13
13
  "source_code_uri" => "https://github.com/digital-fabric/extralite",
14
- "documentation_uri" => "https://github.com/digital-fabric/extralite",
14
+ "documentation_uri" => "https://www.rubydoc.info/gems/extralite",
15
15
  "homepage_uri" => "https://github.com/digital-fabric/extralite",
16
16
  "changelog_uri" => "https://github.com/digital-fabric/extralite/blob/master/CHANGELOG.md"
17
17
  }
@@ -21,10 +21,10 @@ Gem::Specification.new do |s|
21
21
  s.require_paths = ["lib"]
22
22
  s.required_ruby_version = '>= 2.6'
23
23
 
24
- s.add_development_dependency 'rake-compiler', '1.1.1'
25
- s.add_development_dependency 'minitest', '5.14.4'
24
+ s.add_development_dependency 'rake-compiler', '1.1.6'
25
+ s.add_development_dependency 'minitest', '5.15.0'
26
26
  s.add_development_dependency 'simplecov', '0.17.1'
27
- s.add_development_dependency 'rubocop', '0.85.1'
28
- s.add_development_dependency 'pry', '0.13.1'
27
+ s.add_development_dependency 'yard', '0.9.27'
28
+
29
29
  s.add_development_dependency 'sequel', '5.51.0'
30
30
  end
@@ -1,3 +1,3 @@
1
1
  module Extralite
2
- VERSION = '1.7'
2
+ VERSION = '1.10'
3
3
  end
data/lib/extralite.rb CHANGED
@@ -1 +1,21 @@
1
1
  require_relative './extralite_ext'
2
+
3
+ # Extralite is a Ruby gem for working with SQLite databases
4
+ module Extralite
5
+ # A base class for Extralite exceptions
6
+ class Error < RuntimeError
7
+ end
8
+
9
+ # An exception representing an SQL error emitted by SQLite
10
+ class SQLError < Error
11
+ end
12
+
13
+ # An exception raised when an SQLite database is busy (locked by another
14
+ # thread or process)
15
+ class BusyError < Error
16
+ end
17
+
18
+ # An SQLite database
19
+ class Database
20
+ end
21
+ end
@@ -1,5 +1,9 @@
1
1
  # frozen-string-literal: true
2
2
 
3
+ # This file was adapted from the SQLite adapter included in Sequel:
4
+ # https://github.com/jeremyevans/sequel
5
+ # (distributed under the MIT license)
6
+
3
7
  require 'extralite'
4
8
  require 'sequel/adapters/shared/sqlite'
5
9
 
data/test/perf_ary.rb ADDED
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/inline'
4
+
5
+ gemfile do
6
+ source 'https://rubygems.org'
7
+ gem 'sqlite3'
8
+ gem 'extralite', path: '..'
9
+ gem 'benchmark-ips'
10
+ end
11
+
12
+ require 'benchmark/ips'
13
+ require 'fileutils'
14
+
15
+ DB_PATH = '/tmp/extralite_sqlite3_perf.db'
16
+
17
+ def prepare_database(count)
18
+ FileUtils.rm(DB_PATH) rescue nil
19
+ db = Extralite::Database.new(DB_PATH)
20
+ db.query('create table foo ( a integer primary key, b text )')
21
+ db.query('begin')
22
+ count.times { db.query('insert into foo (b) values (?)', "hello#{rand(1000)}" )}
23
+ db.query('commit')
24
+ end
25
+
26
+ def sqlite3_run(count)
27
+ db = SQLite3::Database.new(DB_PATH)
28
+ results = db.execute('select * from foo')
29
+ raise unless results.size == count
30
+ end
31
+
32
+ def extralite_run(count)
33
+ db = Extralite::Database.new(DB_PATH)
34
+ results = db.query_ary('select * from foo')
35
+ raise unless results.size == count
36
+ end
37
+
38
+ [10, 1000, 100000].each do |c|
39
+ puts; puts; puts "Record count: #{c}"
40
+
41
+ prepare_database(c)
42
+
43
+ Benchmark.ips do |x|
44
+ x.config(:time => 3, :warmup => 1)
45
+
46
+ x.report("sqlite3") { sqlite3_run(c) }
47
+ x.report("extralite") { extralite_run(c) }
48
+
49
+ x.compare!
50
+ end
51
+ end
File without changes
@@ -138,6 +138,31 @@ end
138
138
  r = @db.query('select x, y, z from t where z = :bazzz', ':bazzz' => 6)
139
139
  assert_equal [{ x: 4, y: 5, z: 6 }], r
140
140
  end
141
+
142
+ def test_parameter_binding_with_index_key
143
+ r = @db.query('select x, y, z from t where z = ?', 1 => 3)
144
+ assert_equal [{ x: 1, y: 2, z: 3 }], r
145
+
146
+ r = @db.query('select x, y, z from t where x = ?2', 1 => 42, 2 => 4)
147
+ assert_equal [{ x: 4, y: 5, z: 6 }], r
148
+ end
149
+
150
+ def test_value_casting
151
+ r = @db.query_single_value("select 'abc'")
152
+ assert_equal 'abc', r
153
+
154
+ r = @db.query_single_value('select 123')
155
+ assert_equal 123, r
156
+
157
+ r = @db.query_single_value('select 12.34')
158
+ assert_equal 12.34, r
159
+
160
+ r = @db.query_single_value('select zeroblob(4)')
161
+ assert_equal "\x00\x00\x00\x00", r
162
+
163
+ r = @db.query_single_value('select null')
164
+ assert_nil r
165
+ end
141
166
  end
142
167
 
143
168
  class ScenarioTest < MiniTest::Test
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: '1.7'
4
+ version: '1.10'
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-12-13 00:00:00.000000000 Z
11
+ date: 2021-12-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake-compiler
@@ -16,28 +16,28 @@ dependencies:
16
16
  requirements:
17
17
  - - '='
18
18
  - !ruby/object:Gem::Version
19
- version: 1.1.1
19
+ version: 1.1.6
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - '='
25
25
  - !ruby/object:Gem::Version
26
- version: 1.1.1
26
+ version: 1.1.6
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: minitest
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - '='
32
32
  - !ruby/object:Gem::Version
33
- version: 5.14.4
33
+ version: 5.15.0
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - '='
39
39
  - !ruby/object:Gem::Version
40
- version: 5.14.4
40
+ version: 5.15.0
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: simplecov
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -53,33 +53,19 @@ dependencies:
53
53
  - !ruby/object:Gem::Version
54
54
  version: 0.17.1
55
55
  - !ruby/object:Gem::Dependency
56
- name: rubocop
56
+ name: yard
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - '='
60
60
  - !ruby/object:Gem::Version
61
- version: 0.85.1
61
+ version: 0.9.27
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - '='
67
67
  - !ruby/object:Gem::Version
68
- version: 0.85.1
69
- - !ruby/object:Gem::Dependency
70
- name: pry
71
- requirement: !ruby/object:Gem::Requirement
72
- requirements:
73
- - - '='
74
- - !ruby/object:Gem::Version
75
- version: 0.13.1
76
- type: :development
77
- prerelease: false
78
- version_requirements: !ruby/object:Gem::Requirement
79
- requirements:
80
- - - '='
81
- - !ruby/object:Gem::Version
82
- version: 0.13.1
68
+ version: 0.9.27
83
69
  - !ruby/object:Gem::Dependency
84
70
  name: sequel
85
71
  requirement: !ruby/object:Gem::Requirement
@@ -102,6 +88,7 @@ extensions:
102
88
  extra_rdoc_files:
103
89
  - README.md
104
90
  files:
91
+ - ".github/FUNDING.yml"
105
92
  - ".github/workflows/test.yml"
106
93
  - ".gitignore"
107
94
  - CHANGELOG.md
@@ -119,7 +106,8 @@ files:
119
106
  - lib/extralite/version.rb
120
107
  - lib/sequel/adapters/extralite.rb
121
108
  - test/helper.rb
122
- - test/perf.rb
109
+ - test/perf_ary.rb
110
+ - test/perf_hash.rb
123
111
  - test/run.rb
124
112
  - test/test_database.rb
125
113
  - test/test_sequel.rb
@@ -128,7 +116,7 @@ licenses:
128
116
  - MIT
129
117
  metadata:
130
118
  source_code_uri: https://github.com/digital-fabric/extralite
131
- documentation_uri: https://github.com/digital-fabric/extralite
119
+ documentation_uri: https://www.rubydoc.info/gems/extralite
132
120
  homepage_uri: https://github.com/digital-fabric/extralite
133
121
  changelog_uri: https://github.com/digital-fabric/extralite/blob/master/CHANGELOG.md
134
122
  post_install_message: