extralite 2.15 → 3.0.0
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-bundle.yml +1 -1
- data/.github/workflows/test.yml +1 -1
- data/CHANGELOG.md +10 -0
- data/README.md +106 -42
- data/TODO.md +2 -16
- data/examples/transform.rb +61 -0
- data/ext/extralite/changeset.c +11 -11
- data/ext/extralite/common.c +234 -22
- data/ext/extralite/database.c +157 -100
- data/ext/extralite/extralite.h +52 -6
- data/ext/extralite/extralite_ext.c +2 -0
- data/ext/extralite/query.c +67 -41
- data/ext/extralite/transform.c +420 -0
- data/gemspec.rb +1 -1
- data/lib/extralite/version.rb +1 -1
- data/lib/extralite.rb +102 -1
- data/test/perf_array.rb +1 -1
- data/test/perf_hash.rb +1 -1
- data/test/perf_hash_prepared.rb +2 -2
- data/test/perf_splat.rb +1 -1
- data/test/perf_transform.rb +58 -0
- data/test/test_database.rb +37 -10
- data/test/test_query.rb +11 -15
- data/test/test_transform.rb +817 -0
- metadata +6 -2
data/test/test_database.rb
CHANGED
|
@@ -302,6 +302,15 @@ class DatabaseTest < Minitest::Test
|
|
|
302
302
|
|
|
303
303
|
r = @db.query_single_splat("select reverse('abcd')")
|
|
304
304
|
assert_equal 'dcba', r
|
|
305
|
+
|
|
306
|
+
e = nil
|
|
307
|
+
begin
|
|
308
|
+
@db.execute("select load_extension('/extensions/foo')")
|
|
309
|
+
rescue => e
|
|
310
|
+
end
|
|
311
|
+
|
|
312
|
+
assert_kind_of Extralite::SQLError, e
|
|
313
|
+
assert_equal 'not authorized', e.message
|
|
305
314
|
end
|
|
306
315
|
|
|
307
316
|
def test_tables
|
|
@@ -341,7 +350,7 @@ class DatabaseTest < Minitest::Test
|
|
|
341
350
|
|
|
342
351
|
def test_pragma
|
|
343
352
|
assert_equal 'memory', @db.pragma('journal_mode')
|
|
344
|
-
assert_equal
|
|
353
|
+
assert_equal 1, @db.pragma('synchronous')
|
|
345
354
|
|
|
346
355
|
assert_equal 1, @db.pragma(:schema_version)
|
|
347
356
|
assert_equal 0, @db.pragma(:recursive_triggers)
|
|
@@ -866,14 +875,17 @@ class DatabaseTest < Minitest::Test
|
|
|
866
875
|
db = Extralite::Database.new(':memory:', gvl_release_threshold: 23)
|
|
867
876
|
assert_equal 23, db.gvl_release_threshold
|
|
868
877
|
|
|
869
|
-
fn = Tempfile.new('
|
|
870
|
-
db = Extralite::Database.new(fn
|
|
878
|
+
fn = Tempfile.new('extralite_test_database_initialize_modern').path
|
|
879
|
+
db = Extralite::Database.new(fn)
|
|
871
880
|
assert_equal 'wal', db.pragma(:journal_mode)
|
|
872
881
|
assert_equal 1, db.pragma(:synchronous)
|
|
882
|
+
assert_equal 1, db.pragma(:foreign_keys)
|
|
873
883
|
|
|
874
|
-
fn = Tempfile.new('
|
|
875
|
-
db = Extralite::Database.new(fn,
|
|
876
|
-
assert_equal
|
|
884
|
+
fn = Tempfile.new('extralite_test_database_initialize_legacy').path
|
|
885
|
+
db = Extralite::Database.new(fn, legacy: true)
|
|
886
|
+
assert_equal 'delete', db.pragma(:journal_mode)
|
|
887
|
+
assert_equal 2, db.pragma(:synchronous)
|
|
888
|
+
assert_equal 0, db.pragma(:foreign_keys)
|
|
877
889
|
end
|
|
878
890
|
|
|
879
891
|
def test_database_inspect
|
|
@@ -1052,7 +1064,7 @@ class DatabaseTest < Minitest::Test
|
|
|
1052
1064
|
def test_wal_checkpoint
|
|
1053
1065
|
fn = Tempfile.new('extralite_test_wal_checkpoint').path
|
|
1054
1066
|
|
|
1055
|
-
db = Extralite::Database.new(fn
|
|
1067
|
+
db = Extralite::Database.new(fn)
|
|
1056
1068
|
|
|
1057
1069
|
db.execute 'create table t (x, y, z)'
|
|
1058
1070
|
rows = (1..1000).map { [rand, rand, rand] }
|
|
@@ -1121,12 +1133,27 @@ class DatabaseTest < Minitest::Test
|
|
|
1121
1133
|
assert_nil result
|
|
1122
1134
|
assert_equal [7, 8], @db.query_splat('SELECT x FROM t ORDER BY x')
|
|
1123
1135
|
end
|
|
1136
|
+
|
|
1137
|
+
def test_quote
|
|
1138
|
+
assert_equal '"abc', @db.quote('"abc')
|
|
1139
|
+
assert_equal "''abc''def", @db.quote("'abc'def")
|
|
1140
|
+
|
|
1141
|
+
assert_equal "'abc'def", @db.query_single_splat("select '#{@db.quote("'abc'def")}'")
|
|
1142
|
+
end
|
|
1143
|
+
|
|
1144
|
+
def test_cache_flush
|
|
1145
|
+
assert_equal @db, @db.cache_flush
|
|
1146
|
+
end
|
|
1147
|
+
|
|
1148
|
+
def test_release_memory
|
|
1149
|
+
assert_equal @db, @db.release_memory
|
|
1150
|
+
end
|
|
1124
1151
|
end
|
|
1125
1152
|
|
|
1126
1153
|
class ScenarioTest < Minitest::Test
|
|
1127
1154
|
def setup
|
|
1128
1155
|
@fn = Tempfile.new('extralite_scenario_test').path
|
|
1129
|
-
@db = Extralite::Database.new(@fn)
|
|
1156
|
+
@db = Extralite::Database.new(@fn, legacy: true)
|
|
1130
1157
|
@db.query('create table if not exists t (x,y,z)')
|
|
1131
1158
|
@db.query('delete from t')
|
|
1132
1159
|
@db.query('insert into t values (1, 2, 3)')
|
|
@@ -1136,7 +1163,7 @@ class ScenarioTest < Minitest::Test
|
|
|
1136
1163
|
def test_concurrent_transactions
|
|
1137
1164
|
done = false
|
|
1138
1165
|
t = Thread.new do
|
|
1139
|
-
db = Extralite::Database.new(@fn)
|
|
1166
|
+
db = Extralite::Database.new(@fn, legacy: true)
|
|
1140
1167
|
db.query 'begin immediate'
|
|
1141
1168
|
sleep 0.01 until done
|
|
1142
1169
|
|
|
@@ -1806,7 +1833,7 @@ class RactorTest < Minitest::Test
|
|
|
1806
1833
|
assert_equal [10] * 10, buf
|
|
1807
1834
|
|
|
1808
1835
|
final_check = Ractor.new(fn) do |rfn|
|
|
1809
|
-
rdb = Extralite::Database.new(rfn
|
|
1836
|
+
rdb = Extralite::Database.new(rfn)
|
|
1810
1837
|
count = rdb.query_single_splat('select count(*) from stress_test')
|
|
1811
1838
|
Ractor.yield count
|
|
1812
1839
|
end
|
data/test/test_query.rb
CHANGED
|
@@ -27,7 +27,7 @@ class QueryTest < Minitest::Test
|
|
|
27
27
|
def test_mode
|
|
28
28
|
query = @db.prepare('select 1')
|
|
29
29
|
assert_equal :hash, query.mode
|
|
30
|
-
|
|
30
|
+
|
|
31
31
|
query.mode = :splat
|
|
32
32
|
assert_equal :splat, query.mode
|
|
33
33
|
|
|
@@ -554,7 +554,7 @@ class QueryTest < Minitest::Test
|
|
|
554
554
|
def test_query_execute_with_mixed_params
|
|
555
555
|
@db.execute 'delete from t'
|
|
556
556
|
q = @db.prepare('insert into t values (?, ?, ?)')
|
|
557
|
-
|
|
557
|
+
|
|
558
558
|
q.execute(1, [2], 3)
|
|
559
559
|
q.execute([4, 5], 6)
|
|
560
560
|
q.execute([7], 8, [9])
|
|
@@ -1014,7 +1014,7 @@ class QueryTransformTest < Minitest::Test
|
|
|
1014
1014
|
|
|
1015
1015
|
@q1 = @db.prepare_splat('select c from t where a = ?')
|
|
1016
1016
|
@q2 = @db.prepare_splat('select c from t order by a')
|
|
1017
|
-
|
|
1017
|
+
|
|
1018
1018
|
@q3 = @db.prepare('select * from t where a = ?')
|
|
1019
1019
|
@q4 = @db.prepare('select * from t order by a')
|
|
1020
1020
|
|
|
@@ -1038,8 +1038,7 @@ class QueryTransformTest < Minitest::Test
|
|
|
1038
1038
|
end
|
|
1039
1039
|
|
|
1040
1040
|
def test_transform_hash
|
|
1041
|
-
|
|
1042
|
-
assert_equal @q5, q
|
|
1041
|
+
@q5.transform = ->(h) { MyModel.new(h) }
|
|
1043
1042
|
|
|
1044
1043
|
o = @q5.bind(1).next
|
|
1045
1044
|
assert_kind_of MyModel, o
|
|
@@ -1054,7 +1053,7 @@ class QueryTransformTest < Minitest::Test
|
|
|
1054
1053
|
[{ a: 4, b: 5 }]
|
|
1055
1054
|
], @q5.batch_query([[1], [4]]).map { |a| a.map(&:values) }
|
|
1056
1055
|
|
|
1057
|
-
@q6.transform
|
|
1056
|
+
@q6.transform = ->(h) { MyModel.new(h) }
|
|
1058
1057
|
assert_equal [
|
|
1059
1058
|
{ a: 1, b: 2 },
|
|
1060
1059
|
{ a: 4, b: 5 }
|
|
@@ -1070,8 +1069,7 @@ class QueryTransformTest < Minitest::Test
|
|
|
1070
1069
|
|
|
1071
1070
|
def test_transform_array
|
|
1072
1071
|
@q5.mode = :array
|
|
1073
|
-
|
|
1074
|
-
assert_equal @q5, q
|
|
1072
|
+
@q5.transform = ->(h) { MyModel.new(h) }
|
|
1075
1073
|
|
|
1076
1074
|
o = @q5.bind(1).next
|
|
1077
1075
|
assert_kind_of MyModel, o
|
|
@@ -1087,7 +1085,7 @@ class QueryTransformTest < Minitest::Test
|
|
|
1087
1085
|
], @q5.batch_query([[1], [4]]).map { |a| a.map(&:values) }
|
|
1088
1086
|
|
|
1089
1087
|
@q6.mode = :array
|
|
1090
|
-
@q6.transform
|
|
1088
|
+
@q6.transform = ->(h) { MyModel.new(h) }
|
|
1091
1089
|
assert_equal [
|
|
1092
1090
|
[1, 2],
|
|
1093
1091
|
[4, 5]
|
|
@@ -1102,8 +1100,7 @@ class QueryTransformTest < Minitest::Test
|
|
|
1102
1100
|
end
|
|
1103
1101
|
|
|
1104
1102
|
def test_transform_splat_single_column
|
|
1105
|
-
|
|
1106
|
-
assert_equal @q1, q
|
|
1103
|
+
@q1.transform = ->(c) { JSON.parse(c, symbolize_names: true) }
|
|
1107
1104
|
|
|
1108
1105
|
assert_equal({ foo: 42, bar: 43 }, @q1.bind(1).next)
|
|
1109
1106
|
assert_equal({ foo: 45, bar: 46 }, @q1.bind(4).next)
|
|
@@ -1113,7 +1110,7 @@ class QueryTransformTest < Minitest::Test
|
|
|
1113
1110
|
[{ foo: 45, bar: 46 }]
|
|
1114
1111
|
], @q1.batch_query([[1], [4]])
|
|
1115
1112
|
|
|
1116
|
-
@q2.transform
|
|
1113
|
+
@q2.transform = ->(c) { JSON.parse(c, symbolize_names: true) }
|
|
1117
1114
|
assert_equal [
|
|
1118
1115
|
{ foo: 42, bar: 43 },
|
|
1119
1116
|
{ foo: 45, bar: 46 }
|
|
@@ -1129,8 +1126,7 @@ class QueryTransformTest < Minitest::Test
|
|
|
1129
1126
|
|
|
1130
1127
|
def test_transform_splat_multi_column
|
|
1131
1128
|
@q3.mode = :splat
|
|
1132
|
-
|
|
1133
|
-
assert_equal @q3, q
|
|
1129
|
+
@q3.transform = ->(a, b, c) { { a: a, b: b, c: JSON.parse(c, symbolize_names: true) } }
|
|
1134
1130
|
|
|
1135
1131
|
assert_equal({ a: 1, b: 2, c: { foo: 42, bar: 43 }}, @q3.bind(1).next)
|
|
1136
1132
|
assert_equal({ a: 4, b: 5, c: { foo: 45, bar: 46 }}, @q3.bind(4).next)
|
|
@@ -1141,7 +1137,7 @@ class QueryTransformTest < Minitest::Test
|
|
|
1141
1137
|
], @q3.batch_query([[1], [4]])
|
|
1142
1138
|
|
|
1143
1139
|
@q4.mode = :splat
|
|
1144
|
-
@q4.transform
|
|
1140
|
+
@q4.transform = ->(a, b, c) { { a: a, b: b, c: JSON.parse(c, symbolize_names: true) } }
|
|
1145
1141
|
assert_equal [
|
|
1146
1142
|
{ a: 1, b: 2, c: { foo: 42, bar: 43 }},
|
|
1147
1143
|
{ a: 4, b: 5, c: { foo: 45, bar: 46 }}
|