extralite 1.25 → 1.27

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: 8a6e8245385b707be08a300ff6bb089291cfa27500fd99f35698f3dc566147e0
4
- data.tar.gz: 1bc49ffc376a8e8f17da33cda6afdd59299e9d6dac381ef2ff9c7ea8d3a92418
3
+ metadata.gz: a027328ec4af0d01bc81706f4f8e1ea08770a1341d8a36953882244b2d20ed88
4
+ data.tar.gz: 916fabb4a5328e93bcdcb8121b54aa3e958b87915e9b1c9027cccb44941837b9
5
5
  SHA512:
6
- metadata.gz: 1e119afa5f07f499935cd83692cb86c22c548ed7f4e35b46735860349186e66c5b1cd1ca2b32cbc8aa41c1e9106c942d38958b145480b397d838a5d75d32985f
7
- data.tar.gz: 28f0b76e7ed23e51b9f99f7a8756534163330f909668d7f2d1fa34bd1517ee37ccfdcffe18028fa51cbf427353f313256832daead4ed09a00742a4bd24236744
6
+ metadata.gz: fc4cd60e38d6e229d5d28ab6e28db3a16f7ddf1ffde53e3f5a97cacebe607158604421016bab34fa5bf96659ab4d0074fffb0f51712e4429d5529f59bbcdec0d
7
+ data.tar.gz: db9905c1c839a4135fe4c1156b3991f8cad5ac438b5c70091be34e8afee7563371e19afe45cd835cec2f83dd26fc92e5855bf7c53c6ee473728b80caabb3e5e1
data/.github/FUNDING.yml CHANGED
@@ -1 +1 @@
1
- github: ciconia
1
+ github: noteflakes
data/.yardopts ADDED
@@ -0,0 +1,8 @@
1
+ -o ./_yardoc
2
+ -m markdown -M redcarpet
3
+ --verbose
4
+ --protected
5
+ --no-private
6
+ --exclude sqlite3_constants.rb
7
+ ./lib
8
+ ./ext/extralite
data/CHANGELOG.md CHANGED
@@ -1,3 +1,12 @@
1
+ # 1.27 2023-06-12
2
+
3
+ - Fix execution of prepared statements in Sequel adapter (#23 @gschlager)
4
+ - Update bundled sqlite code to version 3.42.0 (#22 @gschlager)
5
+
6
+ # 1.26 2023-05-17
7
+
8
+ - Improve documentation
9
+
1
10
  # 1.25 2023-03-10
2
11
 
3
12
  - Remove bundled sqlite3 source files from extralite.gemspec
data/Gemfile.lock CHANGED
@@ -1,13 +1,13 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- extralite (1.25)
4
+ extralite (1.27)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
8
8
  specs:
9
9
  docile (1.4.0)
10
- json (2.6.1)
10
+ json (2.6.3)
11
11
  minitest (5.15.0)
12
12
  rake (13.0.6)
13
13
  rake-compiler (1.1.6)
data/README.md CHANGED
@@ -14,7 +14,7 @@ with an SQLite3 database, as well as prepared statements.
14
14
  Extralite comes in two flavors: the `extralite` gem which uses the
15
15
  system-installed sqlite3 library, and the `extralite-bundle` gem which bundles
16
16
  the latest version of SQLite
17
- ([3.40.1](https://sqlite.org/releaselog/3_40_1.html)), offering access to the
17
+ ([3.42.0](https://sqlite.org/releaselog/3_42_0.html)), offering access to the
18
18
  latest features and enhancements.
19
19
 
20
20
  ## Features
@@ -56,6 +56,7 @@ else
56
56
  $CFLAGS << ' -DTAINTING_SUPPORT'
57
57
  end
58
58
 
59
+ # @!visibility private
59
60
  def asplode missing
60
61
  if RUBY_PLATFORM =~ /mingw|mswin/
61
62
  abort "#{missing} is missing. Install SQLite3 from " +
@@ -1,6 +1,12 @@
1
1
  #include <stdio.h>
2
2
  #include "extralite.h"
3
3
 
4
+ /*
5
+ * Document-class: Extralite::PreparedStatement
6
+ *
7
+ * This class represents a prepared statement.
8
+ */
9
+
4
10
  VALUE cPreparedStatement;
5
11
 
6
12
  static size_t PreparedStatement_size(const void *ptr) {
@@ -1,5 +1,4 @@
1
1
  module Extralite
2
-
3
2
  SQLITE_STATUS_MEMORY_USED = 0
4
3
  SQLITE_STATUS_PAGECACHE_USED = 1
5
4
  SQLITE_STATUS_PAGECACHE_OVERFLOW = 2
@@ -1,3 +1,4 @@
1
1
  module Extralite
2
- VERSION = '1.25'
2
+ # Extralite version
3
+ VERSION = '1.27'
3
4
  end
data/lib/extralite.rb CHANGED
@@ -29,6 +29,7 @@ module Extralite
29
29
  class Database
30
30
  alias_method :execute, :query
31
31
 
32
+ # @!visibility private
32
33
  TABLES_SQL = <<~SQL
33
34
  SELECT name FROM sqlite_master
34
35
  WHERE type ='table'
@@ -7,22 +7,28 @@
7
7
  require 'extralite'
8
8
  require 'sequel/adapters/shared/sqlite'
9
9
 
10
+ # @!visibility private
10
11
  module Sequel
12
+ # Extralite Sequel adapter
11
13
  module Extralite
14
+ # @!visibility private
12
15
  FALSE_VALUES = (%w'0 false f no n'.each(&:freeze) + [0]).freeze
13
16
 
14
17
  blob = Object.new
18
+ # @!visibility private
15
19
  def blob.call(s)
16
20
  Sequel::SQL::Blob.new(s.to_s)
17
21
  end
18
22
 
19
23
  boolean = Object.new
24
+ # @!visibility private
20
25
  def boolean.call(s)
21
26
  s = s.downcase if s.is_a?(String)
22
27
  !FALSE_VALUES.include?(s)
23
28
  end
24
29
 
25
30
  date = Object.new
31
+ # @!visibility private
26
32
  def date.call(s)
27
33
  case s
28
34
  when String
@@ -37,22 +43,26 @@ module Sequel
37
43
  end
38
44
 
39
45
  integer = Object.new
46
+ # @!visibility private
40
47
  def integer.call(s)
41
48
  s.to_i
42
49
  end
43
50
 
44
51
  float = Object.new
52
+ # @!visibility private
45
53
  def float.call(s)
46
54
  s.to_f
47
55
  end
48
56
 
49
57
  numeric = Object.new
58
+ # @!visibility private
50
59
  def numeric.call(s)
51
60
  s = s.to_s unless s.is_a?(String)
52
61
  BigDecimal(s) rescue s
53
62
  end
54
63
 
55
64
  time = Object.new
65
+ # @!visibility private
56
66
  def time.call(s)
57
67
  case s
58
68
  when String
@@ -82,19 +92,21 @@ module Sequel
82
92
  end
83
93
  SQLITE_TYPES.freeze
84
94
 
95
+ # @!visibility private
85
96
  USE_EXTENDED_RESULT_CODES = false
86
-
97
+
98
+ # Database adapter for Sequel
87
99
  class Database < Sequel::Database
88
100
  include ::Sequel::SQLite::DatabaseMethods
89
-
101
+
90
102
  set_adapter_scheme :extralite
91
-
103
+
92
104
  # Mimic the file:// uri, by having 2 preceding slashes specify a relative
93
105
  # path, and 3 preceding slashes specify an absolute path.
94
106
  def self.uri_to_options(uri) # :nodoc:
95
107
  { :database => (uri.host.nil? && uri.path == '/') ? nil : "#{uri.host}#{uri.path}" }
96
108
  end
97
-
109
+
98
110
  private_class_method :uri_to_options
99
111
 
100
112
  # The conversion procs to use for this database
@@ -119,14 +131,14 @@ module Sequel
119
131
  # if USE_EXTENDED_RESULT_CODES
120
132
  # db.extended_result_codes = true
121
133
  # end
122
-
134
+
123
135
  connection_pragmas.each{|s| log_connection_yield(s, db){db.query(s)}}
124
-
136
+
125
137
  class << db
126
138
  attr_reader :prepared_statements
127
139
  end
128
140
  db.instance_variable_set(:@prepared_statements, {})
129
-
141
+
130
142
  db
131
143
  end
132
144
 
@@ -135,7 +147,7 @@ module Sequel
135
147
  c.prepared_statements.each_value{|v| v.first.close }
136
148
  c.close
137
149
  end
138
-
150
+
139
151
  # Run the given SQL with the given arguments and yield each row.
140
152
  def execute(sql, opts=OPTS, &block)
141
153
  _execute(:select, sql, opts, &block)
@@ -145,7 +157,7 @@ module Sequel
145
157
  def execute_dui(sql, opts=OPTS)
146
158
  _execute(:update, sql, opts)
147
159
  end
148
-
160
+
149
161
  # Drop any prepared statements on the connection when executing DDL. This is because
150
162
  # prepared statements lock the table in such a way that you can't drop or alter the
151
163
  # table while a prepared statement that references it still exists.
@@ -156,11 +168,13 @@ module Sequel
156
168
  super
157
169
  end
158
170
  end
159
-
171
+
172
+ # @!visibility private
160
173
  def execute_insert(sql, opts=OPTS)
161
174
  _execute(:insert, sql, opts)
162
175
  end
163
-
176
+
177
+ # @!visibility private
164
178
  def freeze
165
179
  @conversion_procs.freeze
166
180
  super
@@ -181,13 +195,13 @@ module Sequel
181
195
  end
182
196
 
183
197
  private
184
-
198
+
185
199
  def adapter_initialize
186
200
  @conversion_procs = SQLITE_TYPES.dup
187
201
  @conversion_procs['datetime'] = @conversion_procs['timestamp'] = method(:to_application_timestamp)
188
202
  set_integer_booleans
189
203
  end
190
-
204
+
191
205
  # Yield an available connection. Rescue any Extralite::Error and turn
192
206
  # them into DatabaseErrors.
193
207
  def _execute(type, sql, opts, &block)
@@ -212,7 +226,7 @@ module Sequel
212
226
  raise_error(e)
213
227
  end
214
228
  end
215
-
229
+
216
230
  # The SQLite adapter does not need the pool to convert exceptions.
217
231
  # Also, force the max connections to 1 if a memory database is being
218
232
  # used, as otherwise each connection gets a separate database.
@@ -223,7 +237,7 @@ module Sequel
223
237
  o[:max_connections] = 1 if @opts[:database] == ':memory:' || blank_object?(@opts[:database])
224
238
  o
225
239
  end
226
-
240
+
227
241
  def prepared_statement_argument(arg)
228
242
  case arg
229
243
  when Date, DateTime, Time
@@ -267,9 +281,9 @@ module Sequel
267
281
  log_sql << ")"
268
282
  end
269
283
  if block
270
- log_connection_yield(log_sql, conn, args){cps.execute(ps_args, &block)}
284
+ log_connection_yield(log_sql, conn, args){cps.query(ps_args, &block)}
271
285
  else
272
- log_connection_yield(log_sql, conn, args){cps.execute!(ps_args){|r|}}
286
+ log_connection_yield(log_sql, conn, args){cps.query(ps_args){|r|}}
273
287
  case type
274
288
  when :insert
275
289
  conn.last_insert_rowid
@@ -278,7 +292,7 @@ module Sequel
278
292
  end
279
293
  end
280
294
  end
281
-
295
+
282
296
  # # SQLite3 raises ArgumentError in addition to SQLite3::Exception in
283
297
  # # some cases, such as operations on a closed database.
284
298
  def database_error_classes
@@ -297,15 +311,17 @@ module Sequel
297
311
  end
298
312
  end
299
313
  end
300
-
314
+
315
+ # Dataset adapter for Sequel
301
316
  class Dataset < Sequel::Dataset
302
317
  include ::Sequel::SQLite::DatasetMethods
303
318
 
319
+ # @!visibility private
304
320
  module ArgumentMapper
305
321
  include Sequel::Dataset::ArgumentMapper
306
-
322
+
307
323
  protected
308
-
324
+
309
325
  # Return a hash with the same values as the given hash,
310
326
  # but with the keys converted to strings.
311
327
  def map_to_prepared_args(hash)
@@ -313,19 +329,22 @@ module Sequel
313
329
  hash.each{|k,v| args[k.to_s.gsub('.', '__')] = v}
314
330
  args
315
331
  end
316
-
332
+
317
333
  private
318
-
334
+
319
335
  # SQLite uses a : before the name of the argument for named
320
336
  # arguments.
321
337
  def prepared_arg(k)
322
338
  LiteralString.new("#{prepared_arg_placeholder}#{k.to_s.gsub('.', '__')}")
323
339
  end
324
340
  end
325
-
341
+
342
+ # @!visibility private
326
343
  BindArgumentMethods = prepared_statements_module(:bind, ArgumentMapper)
344
+ # @!visibility private
327
345
  PreparedStatementMethods = prepared_statements_module(:prepare, BindArgumentMethods)
328
346
 
347
+ # @!visibility private
329
348
  def fetch_rows(sql, &block)
330
349
  execute(sql, &block)
331
350
  # execute(sql) do |result|
@@ -350,9 +369,9 @@ module Sequel
350
369
  # end
351
370
  # end
352
371
  end
353
-
372
+
354
373
  private
355
-
374
+
356
375
  # The base type name for a given type, without any parenthetical part.
357
376
  def base_type_name(t)
358
377
  (t =~ /^(.*?)\(/ ? $1 : t).downcase if t
data/test/test_sequel.rb CHANGED
@@ -4,21 +4,43 @@ require_relative 'helper'
4
4
  require 'sequel'
5
5
 
6
6
  class SequelExtraliteTest < MiniTest::Test
7
- def test_sequel
8
- db = Sequel.connect('extralite::memory:')
9
- db.create_table :items do
7
+ def setup
8
+ @db = Sequel.connect('extralite::memory:')
9
+ @db.create_table :items do
10
10
  primary_key :id
11
11
  String :name, unique: true, null: false
12
12
  Float :price, null: false
13
13
  end
14
14
 
15
- items = db[:items]
16
-
15
+ items = @db[:items]
17
16
  items.insert(name: 'abc', price: 123)
18
17
  items.insert(name: 'def', price: 456)
19
18
  items.insert(name: 'ghi', price: 789)
19
+ end
20
+
21
+ def teardown
22
+ @db.disconnect
23
+ end
24
+
25
+ def test_sequel
26
+ items = @db[:items]
20
27
 
21
28
  assert_equal 3, items.count
22
29
  assert_equal (123+456+789) / 3, items.avg(:price)
23
30
  end
31
+
32
+ def test_prepared_statement
33
+ items = @db[:items]
34
+ prepared_query = items.where(name: :$name).prepare(:select, :select_by_name)
35
+ prepared_insert = items.prepare(:insert, :insert_with_name_and_price, name: :$name, price: :$price)
36
+
37
+ assert_equal prepared_query.call(name: 'def'), [{ id: 2, name: 'def', price: 456 }]
38
+ assert_equal @db.call(:select_by_name, name: 'def'), [{ id: 2, name: 'def', price: 456 }]
39
+
40
+ id = prepared_insert.call(name: 'jkl', price: 444)
41
+ assert_equal items[id: id], { id: id, name: 'jkl', price: 444 }
42
+
43
+ id = @db.call(:insert_with_name_and_price, name: 'mno', price: 555)
44
+ assert_equal items[id: id], { id: id, name: 'mno', price: 555 }
45
+ end
24
46
  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: '1.25'
4
+ version: '1.27'
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sharon Rosner
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-03-10 00:00:00.000000000 Z
11
+ date: 2023-06-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake-compiler
@@ -91,6 +91,7 @@ files:
91
91
  - ".github/FUNDING.yml"
92
92
  - ".github/workflows/test.yml"
93
93
  - ".gitignore"
94
+ - ".yardopts"
94
95
  - CHANGELOG.md
95
96
  - Gemfile
96
97
  - Gemfile.lock