sqlite_web_vfs 1.0.1
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 +7 -0
- data/LICENSE-3RD-PARTY.md +32 -0
- data/README.md +118 -0
- data/examples/sqlite3_example.rb +21 -0
- data/examples/sqlite3_ffi_example.rb +25 -0
- data/ext/sqlite_web_vfs/Makefile +267 -0
- data/ext/sqlite_web_vfs/_wrap_web_vfs.o +0 -0
- data/ext/sqlite_web_vfs/extconf.rb +177 -0
- data/ext/sqlite_web_vfs/readerwriterqueue.h +5 -0
- data/ext/sqlite_web_vfs/shim.c +16 -0
- data/ext/sqlite_web_vfs/shim.o +0 -0
- data/ext/sqlite_web_vfs/upstream/HTTP.h +435 -0
- data/ext/sqlite_web_vfs/upstream/SQLiteVFS.h +530 -0
- data/ext/sqlite_web_vfs/upstream/ThreadPool.h +209 -0
- data/ext/sqlite_web_vfs/upstream/atomicops.h +772 -0
- data/ext/sqlite_web_vfs/upstream/dbi.h +203 -0
- data/ext/sqlite_web_vfs/upstream/readerwriterqueue.h +979 -0
- data/ext/sqlite_web_vfs/upstream/web_vfs.cc +21 -0
- data/ext/sqlite_web_vfs/upstream/web_vfs.h +823 -0
- data/lib/sqlite_web_vfs/loader.rb +69 -0
- data/lib/sqlite_web_vfs.rb +12 -0
- data/spec/integration/sq_lite_web_vfs_integration_spec.rb +45 -0
- data/spec/integration/sqlite_web_vfs_integration_spec.rb +45 -0
- data/spec/spec_helper.rb +7 -0
- metadata +67 -0
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'rbconfig'
|
|
4
|
+
|
|
5
|
+
module SQLiteWebVFS
|
|
6
|
+
module Loader
|
|
7
|
+
module_function
|
|
8
|
+
|
|
9
|
+
# Absolute path to the built native extension (.bundle/.so)
|
|
10
|
+
def built_extension_path
|
|
11
|
+
# The compiled extension is installed under this logical name by extconf.rb
|
|
12
|
+
require_path = File.join('sqlite_web_vfs', 'sqlite_web_vfs')
|
|
13
|
+
# Find the actual full path Ruby would use for this require
|
|
14
|
+
$LOAD_PATH.each do |lp|
|
|
15
|
+
Dir[File.join(lp, "#{require_path}.{so,bundle,dll}")].each do |p|
|
|
16
|
+
return p if File.file?(p)
|
|
17
|
+
end
|
|
18
|
+
# Ruby might place it in a versioned directory under lp/sqlite_web_vfs
|
|
19
|
+
Dir[File.join(lp, 'sqlite_web_vfs', 'sqlite_web_vfs.{so,bundle,dll}')].each do |p|
|
|
20
|
+
return p if File.file?(p)
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
nil
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# Load the HTTP VFS into the process (auto-applied to connections).
|
|
27
|
+
# This only requires the compiled extension; it registers itself via sqlite3_auto_extension.
|
|
28
|
+
# Security note: Loading extensions can execute native code. Only load trusted code.
|
|
29
|
+
def load(db = nil)
|
|
30
|
+
begin
|
|
31
|
+
require 'sqlite_web_vfs/sqlite_web_vfs'
|
|
32
|
+
rescue LoadError
|
|
33
|
+
raise_load_error(<<~MSG)
|
|
34
|
+
Could not locate the sqlite_web_vfs native extension. Ensure the gem built correctly.
|
|
35
|
+
- macOS: brew install sqlite curl
|
|
36
|
+
- Amazon Linux 2023: sudo dnf install sqlite-devel libcurl-devel
|
|
37
|
+
If SQLite is installed but detection failed, rebuild with:
|
|
38
|
+
gem uninstall sqlite_web_vfs && gem install sqlite_web_vfs -- --with-sqlite3-dir=/path/to/prefix
|
|
39
|
+
To force building with a bundled SQLite amalgamation (advanced):
|
|
40
|
+
WEBVFS_FORCE_BUNDLED=1 gem install sqlite_web_vfs
|
|
41
|
+
MSG
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# Determine loaded extension path, if any
|
|
45
|
+
dlex = %w[so bundle dll]
|
|
46
|
+
so = $LOADED_FEATURES.find do |f|
|
|
47
|
+
dlex.any? { |ext| f.end_with?("/sqlite_web_vfs/sqlite_web_vfs.#{ext}") }
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# Ensure the current connection loads the extension too (auto-extension affects future opens)
|
|
51
|
+
if db
|
|
52
|
+
db.enable_load_extension(true) if db.respond_to?(:enable_load_extension)
|
|
53
|
+
if db.respond_to?(:load_extension)
|
|
54
|
+
db.load_extension(so) if so
|
|
55
|
+
elsif db.respond_to?(:api) && db.api.respond_to?(:load_extension)
|
|
56
|
+
if so
|
|
57
|
+
rc = db.api.load_extension(db.handle, so, nil, nil)
|
|
58
|
+
raise_load_error("sqlite3-ffi load_extension failed with code #{rc}") unless rc.zero?
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
so
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def raise_load_error(msg)
|
|
66
|
+
raise LoadError, "SQLiteWebVFS::Loader: #{msg}"
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'sqlite_web_vfs/loader'
|
|
4
|
+
|
|
5
|
+
module SQLiteWebVFS
|
|
6
|
+
# Requiring the compiled extension ensures the VFS registers via sqlite3_auto_extension.
|
|
7
|
+
begin
|
|
8
|
+
require 'sqlite_web_vfs/sqlite_web_vfs'
|
|
9
|
+
rescue LoadError
|
|
10
|
+
# The loader will surface clearer installation instructions when used.
|
|
11
|
+
end
|
|
12
|
+
end
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'uri'
|
|
4
|
+
require_relative '../spec_helper'
|
|
5
|
+
require 'sqlite_web_vfs'
|
|
6
|
+
|
|
7
|
+
RSpec.describe SQLiteWebVFS do
|
|
8
|
+
let(:chinook_url) { 'https://github.com/lerocha/chinook-database/raw/master/ChinookDatabase/DataSources/Chinook_Sqlite.sqlite' }
|
|
9
|
+
let(:encoded_url) { URI.encode_www_form_component(chinook_url) }
|
|
10
|
+
let(:web_uri) { "file:/__web__?vfs=web&mode=ro&immutable=1&web_url=#{encoded_url}" }
|
|
11
|
+
|
|
12
|
+
it 'loads and queries remote DB via sqlite3 gem' do
|
|
13
|
+
begin
|
|
14
|
+
require 'sqlite3'
|
|
15
|
+
rescue LoadError
|
|
16
|
+
skip 'sqlite3 gem not available'
|
|
17
|
+
end
|
|
18
|
+
db = SQLite3::Database.new(':memory:')
|
|
19
|
+
SQLiteWebVFS::Loader.load(db)
|
|
20
|
+
db.execute('ATTACH DATABASE ? AS remote', [web_uri])
|
|
21
|
+
count = db.get_first_value('SELECT COUNT(*) FROM remote.Album')
|
|
22
|
+
expect(count).to be_a(Integer)
|
|
23
|
+
ensure
|
|
24
|
+
db&.close
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
it 'loads and queries remote DB via sqlite3-ffi gem' do
|
|
28
|
+
begin
|
|
29
|
+
begin
|
|
30
|
+
require 'sqlite3-ffi'
|
|
31
|
+
rescue LoadError
|
|
32
|
+
require 'sqlite3/ffi'
|
|
33
|
+
end
|
|
34
|
+
rescue LoadError
|
|
35
|
+
skip 'sqlite3-ffi gem not available'
|
|
36
|
+
end
|
|
37
|
+
db = SQLite3::Database.new(':memory:')
|
|
38
|
+
SQLiteWebVFS::Loader.load(db)
|
|
39
|
+
db.execute('ATTACH DATABASE ? AS remote', [web_uri])
|
|
40
|
+
count = db.execute('SELECT COUNT(*) FROM remote.Album').first.first
|
|
41
|
+
expect(count).to be_a(Integer)
|
|
42
|
+
ensure
|
|
43
|
+
db&.close
|
|
44
|
+
end
|
|
45
|
+
end
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'uri'
|
|
4
|
+
require_relative '../spec_helper'
|
|
5
|
+
require 'sqlite_web_vfs'
|
|
6
|
+
|
|
7
|
+
RSpec.describe SQLiteWebVFS do
|
|
8
|
+
let(:chinook_url) { ENV['CHINOOK_URL'] || 'https://github.com/lerocha/chinook-database/raw/master/ChinookDatabase/DataSources/Chinook_Sqlite.sqlite' }
|
|
9
|
+
let(:encoded_url) { URI.encode_www_form_component(chinook_url) }
|
|
10
|
+
let(:web_uri) { "file:/__web__?vfs=web&mode=ro&immutable=1&web_url=#{encoded_url}" }
|
|
11
|
+
|
|
12
|
+
it 'loads and queries remote DB via sqlite3 gem' do
|
|
13
|
+
begin
|
|
14
|
+
require 'sqlite3'
|
|
15
|
+
rescue LoadError
|
|
16
|
+
skip 'sqlite3 gem not available'
|
|
17
|
+
end
|
|
18
|
+
db = SQLite3::Database.new(':memory:')
|
|
19
|
+
SQLiteWebVFS::Loader.load(db)
|
|
20
|
+
db.execute('ATTACH DATABASE ? AS remote', [web_uri])
|
|
21
|
+
count = db.get_first_value('SELECT COUNT(*) FROM remote.Album')
|
|
22
|
+
expect(count).to be_a(Integer)
|
|
23
|
+
ensure
|
|
24
|
+
db&.close
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
it 'loads and queries remote DB via sqlite3-ffi gem' do
|
|
28
|
+
begin
|
|
29
|
+
begin
|
|
30
|
+
require 'sqlite3-ffi'
|
|
31
|
+
rescue LoadError
|
|
32
|
+
require 'sqlite3/ffi'
|
|
33
|
+
end
|
|
34
|
+
rescue LoadError
|
|
35
|
+
skip 'sqlite3-ffi gem not available'
|
|
36
|
+
end
|
|
37
|
+
db = SQLite3::Database.new(':memory:')
|
|
38
|
+
SQLiteWebVFS::Loader.load(db)
|
|
39
|
+
db.execute('ATTACH DATABASE ? AS remote', [web_uri])
|
|
40
|
+
count = db.execute('SELECT COUNT(*) FROM remote.Album').first.first
|
|
41
|
+
expect(count).to be_a(Integer)
|
|
42
|
+
ensure
|
|
43
|
+
db&.close
|
|
44
|
+
end
|
|
45
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: sqlite_web_vfs
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 1.0.1
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Denis Sablic
|
|
8
|
+
bindir: bin
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies: []
|
|
12
|
+
description: Builds and loads the HTTP VFS from mlin/sqlite_web_vfs for SQLite, enabling
|
|
13
|
+
remote DB access over HTTP(S) via Range requests.
|
|
14
|
+
email: denis.sablic@gmail.com
|
|
15
|
+
executables: []
|
|
16
|
+
extensions:
|
|
17
|
+
- ext/sqlite_web_vfs/extconf.rb
|
|
18
|
+
extra_rdoc_files: []
|
|
19
|
+
files:
|
|
20
|
+
- LICENSE-3RD-PARTY.md
|
|
21
|
+
- README.md
|
|
22
|
+
- examples/sqlite3_example.rb
|
|
23
|
+
- examples/sqlite3_ffi_example.rb
|
|
24
|
+
- ext/sqlite_web_vfs/Makefile
|
|
25
|
+
- ext/sqlite_web_vfs/_wrap_web_vfs.o
|
|
26
|
+
- ext/sqlite_web_vfs/extconf.rb
|
|
27
|
+
- ext/sqlite_web_vfs/readerwriterqueue.h
|
|
28
|
+
- ext/sqlite_web_vfs/shim.c
|
|
29
|
+
- ext/sqlite_web_vfs/shim.o
|
|
30
|
+
- ext/sqlite_web_vfs/upstream/HTTP.h
|
|
31
|
+
- ext/sqlite_web_vfs/upstream/SQLiteVFS.h
|
|
32
|
+
- ext/sqlite_web_vfs/upstream/ThreadPool.h
|
|
33
|
+
- ext/sqlite_web_vfs/upstream/atomicops.h
|
|
34
|
+
- ext/sqlite_web_vfs/upstream/dbi.h
|
|
35
|
+
- ext/sqlite_web_vfs/upstream/readerwriterqueue.h
|
|
36
|
+
- ext/sqlite_web_vfs/upstream/web_vfs.cc
|
|
37
|
+
- ext/sqlite_web_vfs/upstream/web_vfs.h
|
|
38
|
+
- lib/sqlite_web_vfs.rb
|
|
39
|
+
- lib/sqlite_web_vfs/loader.rb
|
|
40
|
+
- spec/integration/sq_lite_web_vfs_integration_spec.rb
|
|
41
|
+
- spec/integration/sqlite_web_vfs_integration_spec.rb
|
|
42
|
+
- spec/spec_helper.rb
|
|
43
|
+
homepage: https://github.com/dsablic/sqlite_web_vfs
|
|
44
|
+
licenses:
|
|
45
|
+
- BSD-3-Clause
|
|
46
|
+
metadata:
|
|
47
|
+
rubygems_mfa_required: 'true'
|
|
48
|
+
source_code_uri: https://github.com/dsablic/sqlite_web_vfs
|
|
49
|
+
bug_tracker_uri: https://github.com/dsablic/sqlite_web_vfs/issues
|
|
50
|
+
rdoc_options: []
|
|
51
|
+
require_paths:
|
|
52
|
+
- lib
|
|
53
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
54
|
+
requirements:
|
|
55
|
+
- - ">="
|
|
56
|
+
- !ruby/object:Gem::Version
|
|
57
|
+
version: 3.2.0
|
|
58
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
59
|
+
requirements:
|
|
60
|
+
- - ">="
|
|
61
|
+
- !ruby/object:Gem::Version
|
|
62
|
+
version: '0'
|
|
63
|
+
requirements: []
|
|
64
|
+
rubygems_version: 4.0.6
|
|
65
|
+
specification_version: 4
|
|
66
|
+
summary: Loadable SQLite HTTP VFS (Ruby loader)
|
|
67
|
+
test_files: []
|