extralite 2.7 → 2.8
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/.yardopts +1 -1
- data/CHANGELOG.md +15 -4
- data/README.md +83 -46
- data/examples/kv_store.rb +1 -1
- data/examples/pubsub_store_polyphony.rb +2 -2
- 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 +182 -102
- data/ext/extralite/extralite.h +10 -17
- data/ext/extralite/iterator.c +0 -1
- data/ext/extralite/query.c +45 -44
- data/gemspec.rb +1 -1
- data/lib/extralite/version.rb +1 -1
- data/lib/extralite.rb +158 -4
- 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 +148 -117
- 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
data/ext/extralite/query.c
CHANGED
@@ -15,8 +15,8 @@ ID ID_inspect;
|
|
15
15
|
ID ID_slice;
|
16
16
|
|
17
17
|
VALUE SYM_hash;
|
18
|
-
VALUE
|
19
|
-
VALUE
|
18
|
+
VALUE SYM_splat;
|
19
|
+
VALUE SYM_array;
|
20
20
|
|
21
21
|
#define DB_GVL_MODE(query) Database_prepare_gvl_mode(query->db_struct)
|
22
22
|
|
@@ -68,8 +68,8 @@ static inline Query_t *self_to_query(VALUE obj) {
|
|
68
68
|
|
69
69
|
static inline enum query_mode symbol_to_query_mode(VALUE sym) {
|
70
70
|
if (sym == SYM_hash) return QUERY_HASH;
|
71
|
-
if (sym ==
|
72
|
-
if (sym ==
|
71
|
+
if (sym == SYM_splat) return QUERY_SPLAT;
|
72
|
+
if (sym == SYM_array) return QUERY_ARRAY;
|
73
73
|
|
74
74
|
rb_raise(cError, "Invalid query mode");
|
75
75
|
}
|
@@ -78,10 +78,10 @@ static inline VALUE query_mode_to_symbol(enum query_mode query_mode) {
|
|
78
78
|
switch (query_mode) {
|
79
79
|
case QUERY_HASH:
|
80
80
|
return SYM_hash;
|
81
|
-
case
|
82
|
-
return
|
83
|
-
case
|
84
|
-
return
|
81
|
+
case QUERY_SPLAT:
|
82
|
+
return SYM_splat;
|
83
|
+
case QUERY_ARRAY:
|
84
|
+
return SYM_array;
|
85
85
|
default:
|
86
86
|
rb_raise(cError, "Invalid mode");
|
87
87
|
}
|
@@ -232,10 +232,10 @@ inline safe_query_impl query_impl(enum query_mode query_mode) {
|
|
232
232
|
switch (query_mode) {
|
233
233
|
case QUERY_HASH:
|
234
234
|
return safe_query_hash;
|
235
|
-
case
|
236
|
-
return
|
237
|
-
case
|
238
|
-
return
|
235
|
+
case QUERY_SPLAT:
|
236
|
+
return safe_query_splat;
|
237
|
+
case QUERY_ARRAY:
|
238
|
+
return safe_query_array;
|
239
239
|
default:
|
240
240
|
rb_raise(cError, "Invalid query mode (query_impl)");
|
241
241
|
}
|
@@ -593,9 +593,12 @@ VALUE Query_mode_get(VALUE self) {
|
|
593
593
|
return query_mode_to_symbol(query->query_mode);
|
594
594
|
}
|
595
595
|
|
596
|
-
/*
|
596
|
+
/* call-seq:
|
597
|
+
* query.mode = mode
|
598
|
+
*
|
599
|
+
* Sets the query mode. This can be one of `:hash`, `:splat`, `:array`.
|
597
600
|
*
|
598
|
-
* @param [Symbol] query mode
|
601
|
+
* @param mode [Symbol] query mode
|
599
602
|
* @return [Symbol] query mode
|
600
603
|
*/
|
601
604
|
VALUE Query_mode_set(VALUE self, VALUE mode) {
|
@@ -610,41 +613,39 @@ void Init_ExtraliteQuery(void) {
|
|
610
613
|
cQuery = rb_define_class_under(mExtralite, "Query", rb_cObject);
|
611
614
|
rb_define_alloc_func(cQuery, Query_allocate);
|
612
615
|
|
613
|
-
|
614
|
-
|
615
|
-
|
616
|
-
|
617
|
-
|
618
|
-
|
619
|
-
|
620
|
-
|
621
|
-
|
622
|
-
|
623
|
-
|
624
|
-
|
625
|
-
|
626
|
-
|
627
|
-
|
628
|
-
|
629
|
-
|
630
|
-
|
631
|
-
|
632
|
-
|
633
|
-
|
634
|
-
|
635
|
-
|
636
|
-
|
637
|
-
DEF("to_a", Query_to_a, 0);
|
638
|
-
DEF("transform", Query_transform, 0);
|
616
|
+
rb_define_method(cQuery, "bind", Query_bind, -1);
|
617
|
+
rb_define_method(cQuery, "close", Query_close, 0);
|
618
|
+
rb_define_method(cQuery, "closed?", Query_closed_p, 0);
|
619
|
+
rb_define_method(cQuery, "columns", Query_columns, 0);
|
620
|
+
rb_define_method(cQuery, "clone", Query_clone, 0);
|
621
|
+
rb_define_method(cQuery, "database", Query_database, 0);
|
622
|
+
rb_define_method(cQuery, "db", Query_database, 0);
|
623
|
+
rb_define_method(cQuery, "dup", Query_clone, 0);
|
624
|
+
rb_define_method(cQuery, "each", Query_each, 0);
|
625
|
+
rb_define_method(cQuery, "eof?", Query_eof_p, 0);
|
626
|
+
rb_define_method(cQuery, "execute", Query_execute, -1);
|
627
|
+
rb_define_method(cQuery, "<<", Query_execute_chevrons, 1);
|
628
|
+
rb_define_method(cQuery, "batch_execute", Query_batch_execute, 1);
|
629
|
+
rb_define_method(cQuery, "batch_query", Query_batch_query, 1);
|
630
|
+
rb_define_method(cQuery, "initialize", Query_initialize, 3);
|
631
|
+
rb_define_method(cQuery, "inspect", Query_inspect, 0);
|
632
|
+
rb_define_method(cQuery, "mode", Query_mode_get, 0);
|
633
|
+
rb_define_method(cQuery, "mode=", Query_mode_set, 1);
|
634
|
+
rb_define_method(cQuery, "next", Query_next, -1);
|
635
|
+
rb_define_method(cQuery, "reset", Query_reset, 0);
|
636
|
+
rb_define_method(cQuery, "sql", Query_sql, 0);
|
637
|
+
rb_define_method(cQuery, "status", Query_status, -1);
|
638
|
+
rb_define_method(cQuery, "to_a", Query_to_a, 0);
|
639
|
+
rb_define_method(cQuery, "transform", Query_transform, 0);
|
639
640
|
|
640
641
|
ID_inspect = rb_intern("inspect");
|
641
642
|
ID_slice = rb_intern("slice");
|
642
643
|
|
643
644
|
SYM_hash = ID2SYM(rb_intern("hash"));
|
644
|
-
|
645
|
-
|
645
|
+
SYM_splat = ID2SYM(rb_intern("splat"));
|
646
|
+
SYM_array = ID2SYM(rb_intern("array"));
|
646
647
|
|
647
648
|
rb_gc_register_mark_object(SYM_hash);
|
648
|
-
rb_gc_register_mark_object(
|
649
|
-
rb_gc_register_mark_object(
|
649
|
+
rb_gc_register_mark_object(SYM_splat);
|
650
|
+
rb_gc_register_mark_object(SYM_array);
|
650
651
|
}
|
data/gemspec.rb
CHANGED
@@ -18,7 +18,7 @@ def common_spec(s)
|
|
18
18
|
s.required_ruby_version = '>= 3.0'
|
19
19
|
|
20
20
|
s.add_development_dependency 'rake-compiler', '1.2.7'
|
21
|
-
s.add_development_dependency 'minitest', '5.
|
21
|
+
s.add_development_dependency 'minitest', '5.22.2'
|
22
22
|
s.add_development_dependency 'simplecov', '0.17.1'
|
23
23
|
s.add_development_dependency 'yard', '0.9.34'
|
24
24
|
s.add_development_dependency 'sequel', '5.77.0'
|
data/lib/extralite/version.rb
CHANGED
data/lib/extralite.rb
CHANGED
@@ -1,8 +1,163 @@
|
|
1
1
|
require_relative './extralite_ext'
|
2
|
-
require_relative './extralite/sqlite3_constants'
|
3
2
|
|
4
3
|
# Extralite is a Ruby gem for working with SQLite databases
|
5
4
|
module Extralite
|
5
|
+
SQLITE_STATUS_MEMORY_USED = 0
|
6
|
+
SQLITE_STATUS_PAGECACHE_USED = 1
|
7
|
+
SQLITE_STATUS_PAGECACHE_OVERFLOW = 2
|
8
|
+
SQLITE_STATUS_SCRATCH_USED = 3
|
9
|
+
SQLITE_STATUS_SCRATCH_OVERFLOW = 4
|
10
|
+
SQLITE_STATUS_MALLOC_SIZE = 5
|
11
|
+
SQLITE_STATUS_PARSER_STACK = 6
|
12
|
+
SQLITE_STATUS_PAGECACHE_SIZE = 7
|
13
|
+
SQLITE_STATUS_SCRATCH_SIZE = 8
|
14
|
+
SQLITE_STATUS_MALLOC_COUNT = 9
|
15
|
+
|
16
|
+
SQLITE_DBSTATUS_LOOKASIDE_USED = 0
|
17
|
+
SQLITE_DBSTATUS_CACHE_USED = 1
|
18
|
+
SQLITE_DBSTATUS_SCHEMA_USED = 2
|
19
|
+
SQLITE_DBSTATUS_STMT_USED = 3
|
20
|
+
SQLITE_DBSTATUS_LOOKASIDE_HIT = 4
|
21
|
+
SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE = 5
|
22
|
+
SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL = 6
|
23
|
+
SQLITE_DBSTATUS_CACHE_HIT = 7
|
24
|
+
SQLITE_DBSTATUS_CACHE_MISS = 8
|
25
|
+
SQLITE_DBSTATUS_CACHE_WRITE = 9
|
26
|
+
SQLITE_DBSTATUS_DEFERRED_FKS = 10
|
27
|
+
SQLITE_DBSTATUS_CACHE_USED_SHARED = 11
|
28
|
+
SQLITE_DBSTATUS_CACHE_SPILL = 12
|
29
|
+
|
30
|
+
SQLITE_STMTSTATUS_FULLSCAN_STEP = 1
|
31
|
+
SQLITE_STMTSTATUS_SORT = 2
|
32
|
+
SQLITE_STMTSTATUS_AUTOINDEX = 3
|
33
|
+
SQLITE_STMTSTATUS_VM_STEP = 4
|
34
|
+
SQLITE_STMTSTATUS_REPREPARE = 5
|
35
|
+
SQLITE_STMTSTATUS_RUN = 6
|
36
|
+
SQLITE_STMTSTATUS_FILTER_MISS = 7
|
37
|
+
SQLITE_STMTSTATUS_FILTER_HIT = 8
|
38
|
+
SQLITE_STMTSTATUS_MEMUSED = 99
|
39
|
+
|
40
|
+
SQLITE_LIMIT_LENGTH = 0
|
41
|
+
SQLITE_LIMIT_SQL_LENGTH = 1
|
42
|
+
SQLITE_LIMIT_COLUMN = 2
|
43
|
+
SQLITE_LIMIT_EXPR_DEPTH = 3
|
44
|
+
SQLITE_LIMIT_COMPOUND_SELECT = 4
|
45
|
+
SQLITE_LIMIT_VDBE_OP = 5
|
46
|
+
SQLITE_LIMIT_FUNCTION_ARG = 6
|
47
|
+
SQLITE_LIMIT_ATTACHED = 7
|
48
|
+
SQLITE_LIMIT_LIKE_PATTERN_LENGTH = 8
|
49
|
+
SQLITE_LIMIT_VARIABLE_NUMBER = 9
|
50
|
+
SQLITE_LIMIT_TRIGGER_DEPTH = 10
|
51
|
+
SQLITE_LIMIT_WORKER_THREADS = 11
|
52
|
+
|
53
|
+
SQLITE_OK = 0
|
54
|
+
SQLITE_ERROR = 1
|
55
|
+
SQLITE_INTERNAL = 2
|
56
|
+
SQLITE_PERM = 3
|
57
|
+
SQLITE_ABORT = 4
|
58
|
+
SQLITE_BUSY = 5
|
59
|
+
SQLITE_LOCKED = 6
|
60
|
+
SQLITE_NOMEM = 7
|
61
|
+
SQLITE_READONLY = 8
|
62
|
+
SQLITE_INTERRUPT = 9
|
63
|
+
SQLITE_IOERR = 10
|
64
|
+
SQLITE_CORRUPT = 11
|
65
|
+
SQLITE_NOTFOUND = 12
|
66
|
+
SQLITE_FULL = 13
|
67
|
+
SQLITE_CANTOPEN = 14
|
68
|
+
SQLITE_PROTOCOL = 15
|
69
|
+
SQLITE_EMPTY = 16
|
70
|
+
SQLITE_SCHEMA = 17
|
71
|
+
SQLITE_TOOBIG = 18
|
72
|
+
SQLITE_CONSTRAINT = 19
|
73
|
+
SQLITE_MISMATCH = 20
|
74
|
+
SQLITE_MISUSE = 21
|
75
|
+
SQLITE_NOLFS = 22
|
76
|
+
SQLITE_AUTH = 23
|
77
|
+
SQLITE_FORMAT = 24
|
78
|
+
SQLITE_RANGE = 25
|
79
|
+
SQLITE_NOTADB = 26
|
80
|
+
SQLITE_NOTICE = 27
|
81
|
+
SQLITE_WARNING = 28
|
82
|
+
SQLITE_ROW = 100
|
83
|
+
SQLITE_DONE = 101
|
84
|
+
|
85
|
+
SQLITE_ERROR_MISSING_COLLSEQ = (SQLITE_ERROR | (1<<8))
|
86
|
+
SQLITE_ERROR_RETRY = (SQLITE_ERROR | (2<<8))
|
87
|
+
SQLITE_ERROR_SNAPSHOT = (SQLITE_ERROR | (3<<8))
|
88
|
+
SQLITE_IOERR_READ = (SQLITE_IOERR | (1<<8))
|
89
|
+
SQLITE_IOERR_SHORT_READ = (SQLITE_IOERR | (2<<8))
|
90
|
+
SQLITE_IOERR_WRITE = (SQLITE_IOERR | (3<<8))
|
91
|
+
SQLITE_IOERR_FSYNC = (SQLITE_IOERR | (4<<8))
|
92
|
+
SQLITE_IOERR_DIR_FSYNC = (SQLITE_IOERR | (5<<8))
|
93
|
+
SQLITE_IOERR_TRUNCATE = (SQLITE_IOERR | (6<<8))
|
94
|
+
SQLITE_IOERR_FSTAT = (SQLITE_IOERR | (7<<8))
|
95
|
+
SQLITE_IOERR_UNLOCK = (SQLITE_IOERR | (8<<8))
|
96
|
+
SQLITE_IOERR_RDLOCK = (SQLITE_IOERR | (9<<8))
|
97
|
+
SQLITE_IOERR_DELETE = (SQLITE_IOERR | (10<<8))
|
98
|
+
SQLITE_IOERR_BLOCKED = (SQLITE_IOERR | (11<<8))
|
99
|
+
SQLITE_IOERR_NOMEM = (SQLITE_IOERR | (12<<8))
|
100
|
+
SQLITE_IOERR_ACCESS = (SQLITE_IOERR | (13<<8))
|
101
|
+
SQLITE_IOERR_CHECKRESERVEDLOCK = (SQLITE_IOERR | (14<<8))
|
102
|
+
SQLITE_IOERR_LOCK = (SQLITE_IOERR | (15<<8))
|
103
|
+
SQLITE_IOERR_CLOSE = (SQLITE_IOERR | (16<<8))
|
104
|
+
SQLITE_IOERR_DIR_CLOSE = (SQLITE_IOERR | (17<<8))
|
105
|
+
SQLITE_IOERR_SHMOPEN = (SQLITE_IOERR | (18<<8))
|
106
|
+
SQLITE_IOERR_SHMSIZE = (SQLITE_IOERR | (19<<8))
|
107
|
+
SQLITE_IOERR_SHMLOCK = (SQLITE_IOERR | (20<<8))
|
108
|
+
SQLITE_IOERR_SHMMAP = (SQLITE_IOERR | (21<<8))
|
109
|
+
SQLITE_IOERR_SEEK = (SQLITE_IOERR | (22<<8))
|
110
|
+
SQLITE_IOERR_DELETE_NOENT = (SQLITE_IOERR | (23<<8))
|
111
|
+
SQLITE_IOERR_MMAP = (SQLITE_IOERR | (24<<8))
|
112
|
+
SQLITE_IOERR_GETTEMPPATH = (SQLITE_IOERR | (25<<8))
|
113
|
+
SQLITE_IOERR_CONVPATH = (SQLITE_IOERR | (26<<8))
|
114
|
+
SQLITE_IOERR_VNODE = (SQLITE_IOERR | (27<<8))
|
115
|
+
SQLITE_IOERR_AUTH = (SQLITE_IOERR | (28<<8))
|
116
|
+
SQLITE_IOERR_BEGIN_ATOMIC = (SQLITE_IOERR | (29<<8))
|
117
|
+
SQLITE_IOERR_COMMIT_ATOMIC = (SQLITE_IOERR | (30<<8))
|
118
|
+
SQLITE_IOERR_ROLLBACK_ATOMIC = (SQLITE_IOERR | (31<<8))
|
119
|
+
SQLITE_IOERR_DATA = (SQLITE_IOERR | (32<<8))
|
120
|
+
SQLITE_IOERR_CORRUPTFS = (SQLITE_IOERR | (33<<8))
|
121
|
+
SQLITE_LOCKED_SHAREDCACHE = (SQLITE_LOCKED | (1<<8))
|
122
|
+
SQLITE_LOCKED_VTAB = (SQLITE_LOCKED | (2<<8))
|
123
|
+
SQLITE_BUSY_RECOVERY = (SQLITE_BUSY | (1<<8))
|
124
|
+
SQLITE_BUSY_SNAPSHOT = (SQLITE_BUSY | (2<<8))
|
125
|
+
SQLITE_BUSY_TIMEOUT = (SQLITE_BUSY | (3<<8))
|
126
|
+
SQLITE_CANTOPEN_NOTEMPDIR = (SQLITE_CANTOPEN | (1<<8))
|
127
|
+
SQLITE_CANTOPEN_ISDIR = (SQLITE_CANTOPEN | (2<<8))
|
128
|
+
SQLITE_CANTOPEN_FULLPATH = (SQLITE_CANTOPEN | (3<<8))
|
129
|
+
SQLITE_CANTOPEN_CONVPATH = (SQLITE_CANTOPEN | (4<<8))
|
130
|
+
SQLITE_CANTOPEN_DIRTYWAL = (SQLITE_CANTOPEN | (5<<8))
|
131
|
+
SQLITE_CANTOPEN_SYMLINK = (SQLITE_CANTOPEN | (6<<8))
|
132
|
+
SQLITE_CORRUPT_VTAB = (SQLITE_CORRUPT | (1<<8))
|
133
|
+
SQLITE_CORRUPT_SEQUENCE = (SQLITE_CORRUPT | (2<<8))
|
134
|
+
SQLITE_CORRUPT_INDEX = (SQLITE_CORRUPT | (3<<8))
|
135
|
+
SQLITE_READONLY_RECOVERY = (SQLITE_READONLY | (1<<8))
|
136
|
+
SQLITE_READONLY_CANTLOCK = (SQLITE_READONLY | (2<<8))
|
137
|
+
SQLITE_READONLY_ROLLBACK = (SQLITE_READONLY | (3<<8))
|
138
|
+
SQLITE_READONLY_DBMOVED = (SQLITE_READONLY | (4<<8))
|
139
|
+
SQLITE_READONLY_CANTINIT = (SQLITE_READONLY | (5<<8))
|
140
|
+
SQLITE_READONLY_DIRECTORY = (SQLITE_READONLY | (6<<8))
|
141
|
+
SQLITE_ABORT_ROLLBACK = (SQLITE_ABORT | (2<<8))
|
142
|
+
SQLITE_CONSTRAINT_CHECK = (SQLITE_CONSTRAINT | (1<<8))
|
143
|
+
SQLITE_CONSTRAINT_COMMITHOOK = (SQLITE_CONSTRAINT | (2<<8))
|
144
|
+
SQLITE_CONSTRAINT_FOREIGNKEY = (SQLITE_CONSTRAINT | (3<<8))
|
145
|
+
SQLITE_CONSTRAINT_FUNCTION = (SQLITE_CONSTRAINT | (4<<8))
|
146
|
+
SQLITE_CONSTRAINT_NOTNULL = (SQLITE_CONSTRAINT | (5<<8))
|
147
|
+
SQLITE_CONSTRAINT_PRIMARYKEY = (SQLITE_CONSTRAINT | (6<<8))
|
148
|
+
SQLITE_CONSTRAINT_TRIGGER = (SQLITE_CONSTRAINT | (7<<8))
|
149
|
+
SQLITE_CONSTRAINT_UNIQUE = (SQLITE_CONSTRAINT | (8<<8))
|
150
|
+
SQLITE_CONSTRAINT_VTAB = (SQLITE_CONSTRAINT | (9<<8))
|
151
|
+
SQLITE_CONSTRAINT_ROWID = (SQLITE_CONSTRAINT |(10<<8))
|
152
|
+
SQLITE_CONSTRAINT_PINNED = (SQLITE_CONSTRAINT |(11<<8))
|
153
|
+
SQLITE_CONSTRAINT_DATATYPE = (SQLITE_CONSTRAINT |(12<<8))
|
154
|
+
SQLITE_NOTICE_RECOVER_WAL = (SQLITE_NOTICE | (1<<8))
|
155
|
+
SQLITE_NOTICE_RECOVER_ROLLBACK = (SQLITE_NOTICE | (2<<8))
|
156
|
+
SQLITE_WARNING_AUTOINDEX = (SQLITE_WARNING | (1<<8))
|
157
|
+
SQLITE_AUTH_USER = (SQLITE_AUTH | (1<<8))
|
158
|
+
SQLITE_OK_LOAD_PERMANENTLY = (SQLITE_OK | (1<<8))
|
159
|
+
SQLITE_OK_SYMLINK = (SQLITE_OK | (2<<8))
|
160
|
+
|
6
161
|
|
7
162
|
# The following error classes are already defined in the C extension. We put
|
8
163
|
# them here for the sake of generating docs.
|
@@ -29,7 +184,6 @@ module Extralite
|
|
29
184
|
class ParameterError < Error
|
30
185
|
end
|
31
186
|
|
32
|
-
# This class encapsulates an SQLite database connection.
|
33
187
|
class Database
|
34
188
|
# @!visibility private
|
35
189
|
TABLES_SQL = (<<~SQL).freeze
|
@@ -46,7 +200,7 @@ module Extralite
|
|
46
200
|
# @param db [String] name of attached database
|
47
201
|
# @return [Array] list of tables
|
48
202
|
def tables(db = 'main')
|
49
|
-
|
203
|
+
query_splat(format(TABLES_SQL, db: db))
|
50
204
|
end
|
51
205
|
|
52
206
|
# Gets or sets one or more database pragmas. For a list of available pragmas
|
@@ -150,7 +304,7 @@ module Extralite
|
|
150
304
|
end
|
151
305
|
|
152
306
|
def pragma_get(key)
|
153
|
-
|
307
|
+
query_single_splat("pragma #{key}")
|
154
308
|
end
|
155
309
|
end
|
156
310
|
|
data/test/perf_splat.rb
ADDED
@@ -0,0 +1,63 @@
|
|
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-#{Time.now.to_i}-#{rand(10000)}.db"
|
16
|
+
puts "DB_PATH = #{DB_PATH.inspect}"
|
17
|
+
|
18
|
+
$sqlite3_db = SQLite3::Database.new(DB_PATH)
|
19
|
+
$extralite_db = Extralite::Database.new(DB_PATH, gvl_release_threshold: -1)
|
20
|
+
|
21
|
+
def prepare_database(count)
|
22
|
+
db = Extralite::Database.new(DB_PATH)
|
23
|
+
$extralite_db.query('create table if not exists foo ( a integer primary key, b text )')
|
24
|
+
$extralite_db.query('delete from foo')
|
25
|
+
$extralite_db.query('begin')
|
26
|
+
count.times { $extralite_db.query('insert into foo (b) values (?)', "hello#{rand(1000)}" )}
|
27
|
+
$extralite_db.query('commit')
|
28
|
+
end
|
29
|
+
|
30
|
+
def sqlite3_run(expected_count)
|
31
|
+
count = 0
|
32
|
+
$sqlite3_db.execute('select b from foo').each do |row|
|
33
|
+
b = row.first
|
34
|
+
count += 1
|
35
|
+
end
|
36
|
+
raise unless count == expected_count
|
37
|
+
end
|
38
|
+
|
39
|
+
def extralite_run(expected_count)
|
40
|
+
count = 0
|
41
|
+
$extralite_db.query_splat('select * from foo') do |b|
|
42
|
+
count += 1
|
43
|
+
end
|
44
|
+
raise unless count == expected_count
|
45
|
+
end
|
46
|
+
|
47
|
+
[10, 1000, 100000].each do |c|
|
48
|
+
puts; puts; puts "Record count: #{c}"
|
49
|
+
|
50
|
+
prepare_database(c)
|
51
|
+
|
52
|
+
bm = Benchmark.ips do |x|
|
53
|
+
x.config(:time => 5, :warmup => 2)
|
54
|
+
|
55
|
+
x.report("sqlite3") { sqlite3_run(c) }
|
56
|
+
x.report("extralite") { extralite_run(c) }
|
57
|
+
|
58
|
+
x.compare!
|
59
|
+
end
|
60
|
+
puts;
|
61
|
+
bm.entries.each { |e| puts "#{e.label}: #{(e.ips * c).round.to_i} rows/s" }
|
62
|
+
puts;
|
63
|
+
end
|
@@ -38,20 +38,20 @@ end
|
|
38
38
|
|
39
39
|
TRANSFORM = ->(b) { { b: b } }
|
40
40
|
|
41
|
-
def
|
41
|
+
def extralite_run_array_map(count)
|
42
42
|
results = []
|
43
|
-
$extralite_db.
|
43
|
+
$extralite_db.query_array('select * from foo') { |(b)| results << { b: b } }
|
44
44
|
raise unless results.size == count
|
45
45
|
end
|
46
46
|
|
47
|
-
def
|
47
|
+
def extralite_run_splat_map(count)
|
48
48
|
results = []
|
49
|
-
$extralite_db.
|
49
|
+
$extralite_db.query_splat('select * from foo') { |b| results << { b: b } }
|
50
50
|
raise unless results.size == count
|
51
51
|
end
|
52
52
|
|
53
53
|
def extralite_run_transform(count)
|
54
|
-
results = $extralite_db.
|
54
|
+
results = $extralite_db.query_splat(TRANSFORM, 'select * from foo')
|
55
55
|
raise unless results.size == count
|
56
56
|
end
|
57
57
|
|
@@ -62,8 +62,8 @@ end
|
|
62
62
|
bm = Benchmark.ips do |x|
|
63
63
|
x.config(:time => 5, :warmup => 2)
|
64
64
|
|
65
|
-
x.report("
|
66
|
-
x.report("
|
65
|
+
x.report("array_map") { extralite_run_array_map(c) }
|
66
|
+
x.report("splat_map") { extralite_run_splat_map(c) }
|
67
67
|
x.report("transform") { extralite_run_transform(c) }
|
68
68
|
|
69
69
|
x.compare!
|