From 3e1f84be25038b623e07b59a00e6ceeb6e788455 Mon Sep 17 00:00:00 2001 From: Mark Delk Date: Tue, 1 Jul 2025 14:06:10 -0500 Subject: [PATCH 1/8] update readme for macos sqlite3 .load issue --- README.md | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/README.md b/README.md index 969fe5a..14960e9 100644 --- a/README.md +++ b/README.md @@ -74,6 +74,55 @@ It then exposes a method, `SqliteExtensions::UUID.to_path`, which returns the lo This can be passed to [sqlite3](https://github.com/sparklemotion/sqlite3-ruby) in `Database.new(extensions: [])` or `Database#load_extension`. +## Issues + +### Missing `.load` command + +The default `sqlite3` on MacOS doesn't allow loading runtime extensions, so you'll need to use the version from `brew` instead (`brew install sqlite3`). + +```console +% /usr/bin/sqlite3 +SQLite version 3.43.2 2023-10-10 13:08:14 +Enter ".help" for usage hints. +Connected to a transient in-memory database. +Use ".open FILENAME" to reopen on a persistent database. +sqlite> .load +Error: unknown command or invalid arguments: "load". Enter ".help" for help +``` + +You can do so by following the suggestions from `brew info sqlite3`: + +```console +% brew info sqlite3 +... +==> Caveats +sqlite is keg-only, which means it was not symlinked into /opt/homebrew, +because macOS already provides this software and installing another version in +parallel can cause all kinds of trouble. + +If you need to have sqlite first in your PATH, run: + echo 'export PATH="/opt/homebrew/opt/sqlite/bin:$PATH"' >> ~/.zshrc + +For compilers to find sqlite you may need to set: + export LDFLAGS="-L/opt/homebrew/opt/sqlite/lib" + export CPPFLAGS="-I/opt/homebrew/opt/sqlite/include" + +For pkg-config to find sqlite you may need to set: + export PKG_CONFIG_PATH="/opt/homebrew/opt/sqlite/lib/pkgconfig" +``` + +Afterwards, to check that `.load` support works: + +```console +% sqlite3 +SQLite version 3.50.1 2025-06-06 14:52:32 +Enter ".help" for usage hints. +Connected to a transient in-memory database. +Use ".open FILENAME" to reopen on a persistent database. +(ins)sqlite> .load +Usage: .load FILE ?ENTRYPOINT? +``` + ## Development ```shell From dd1cdd811b9c47307a8fd65f53d2bfcd6bb503c4 Mon Sep 17 00:00:00 2001 From: Mark Delk Date: Tue, 1 Jul 2025 14:38:34 -0500 Subject: [PATCH 2/8] use full file path (with DLEXT) to fix macos issues --- lib/sqlite_extensions/uuid.rb | 5 ++++- spec/sqlite_extensions/uuid_spec.rb | 26 +++++++++++++++++++++++--- 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/lib/sqlite_extensions/uuid.rb b/lib/sqlite_extensions/uuid.rb index d8605d9..0490383 100644 --- a/lib/sqlite_extensions/uuid.rb +++ b/lib/sqlite_extensions/uuid.rb @@ -1,10 +1,13 @@ # frozen_string_literal: true +require "rbconfig" + module SqliteExtensions module UUID def self.to_path spec = Gem.loaded_specs["sqlite_extensions-uuid"] - File.join(spec.require_path, "sqlite_extensions/uuid/uuid") + path = File.join(spec.require_path, "sqlite_extensions/uuid/uuid") + path + "." + RbConfig::CONFIG.fetch("DLEXT") end end end diff --git a/spec/sqlite_extensions/uuid_spec.rb b/spec/sqlite_extensions/uuid_spec.rb index 75ef9a5..4a839ba 100644 --- a/spec/sqlite_extensions/uuid_spec.rb +++ b/spec/sqlite_extensions/uuid_spec.rb @@ -6,15 +6,35 @@ end describe "#to_path" do + subject { described_class.to_path } + before do gemspec = instance_double(Gem::Specification, require_path: "foo") allow(Gem).to receive(:loaded_specs).and_return("sqlite_extensions-uuid" => gemspec) end - it "returns the path to the compiled extension" do - path = described_class.to_path + context "when linux" do + before do + allow(RbConfig::CONFIG).to receive(:fetch).with("DLEXT").and_return("so") + end + + it { is_expected.to eq "foo/sqlite_extensions/uuid/uuid.so" } + end + + context "when mac with .dylib extension" do + before do + allow(RbConfig::CONFIG).to receive(:fetch).with("DLEXT").and_return("dylib") + end + + it { is_expected.to eq "foo/sqlite_extensions/uuid/uuid.dylib" } + end + + context "when mac with .bundle extension" do + before do + allow(RbConfig::CONFIG).to receive(:fetch).with("DLEXT").and_return("bundle") + end - expect(path).to eq "foo/sqlite_extensions/uuid/uuid" + it { is_expected.to eq "foo/sqlite_extensions/uuid/uuid.bundle" } end end From 27b947b80b5559102038fb45965aeb671094dfa8 Mon Sep 17 00:00:00 2001 From: Mark Delk Date: Thu, 3 Jul 2025 14:03:18 -0500 Subject: [PATCH 3/8] add a changelog --- CHANGELOG.md | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..15ccd0f --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,47 @@ +# sqlite_extensions-uuid + +Source code: https://github.com/jethrodaniel/sqlite_extensions-uuid + +## v1.0.2 - 2025-07-03 + +* Update `SqliteExtensions::UUID.to_path` to include the library's file extension. + + When loading an extension without a filename (at least on MacOS and Linux), + SQLite looks for a file ending in `.dylib` and `.so`, respectively. + + As a result, if your extension is a `.bundle` file (on MacOS), then you + need to pass the full path. + + Passing the full path shouldn't be an issue on any platform anyway. + + NOTE: we determine the extension using `RbConfig::CONFIG["DLEXT"]`, and we + don't check if the file actually exists, we just construct the path. + + Gem: [`v1.0.2`](https://rubygems.org/gems/sqlite_extensions-uuid/versions/1.0.2) + +## v1.0.1 - 2025-03-20 + +* Add `SqliteExtensions::UUID::VERSION`, use RSpec for internal tests. + + Gem: [`v1.0.1`](https://rubygems.org/gems/sqlite_extensions-uuid/versions/1.0.1) + +## v1.0.0 - 2024-12-07 + +* Require `sqlite3-ruby` 2.4+ so we can use `sqlite3-ruby`'s extension + loading support. + + Now that sqlite3-ruby natively supports loading extensions, we can load + extensions in Rails apps without having to monkey-patch anything, like so: + + ```ruby + gem "sqlite_extensions-uuid" + ``` + + ```yaml + development: + adapter: sqlite3 + extensions: + - <%= SqliteExtensions::UUID.to_path %> + ``` + + Gem: [`v1.0.0`](https://rubygems.org/gems/sqlite_extensions-uuid/versions/1.0.0) From 774558c9c273f221bd8b7c246db8585efa414a09 Mon Sep 17 00:00:00 2001 From: Mark Delk Date: Thu, 3 Jul 2025 14:03:26 -0500 Subject: [PATCH 4/8] update readme --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 14960e9..fccc1d5 100644 --- a/README.md +++ b/README.md @@ -78,7 +78,7 @@ This can be passed to [sqlite3](https://github.com/sparklemotion/sqlite3-ruby) i ### Missing `.load` command -The default `sqlite3` on MacOS doesn't allow loading runtime extensions, so you'll need to use the version from `brew` instead (`brew install sqlite3`). +The default `sqlite3` on MacOS doesn't allow loading runtime extensions, so you'll need to use a version that does, e.g, from `brew` (`brew install sqlite3`). ```console % /usr/bin/sqlite3 @@ -90,7 +90,7 @@ sqlite> .load Error: unknown command or invalid arguments: "load". Enter ".help" for help ``` -You can do so by following the suggestions from `brew info sqlite3`: +If using `brew`, you'll want to follow the suggestions from `brew info sqlite3`: ```console % brew info sqlite3 @@ -111,7 +111,7 @@ For pkg-config to find sqlite you may need to set: export PKG_CONFIG_PATH="/opt/homebrew/opt/sqlite/lib/pkgconfig" ``` -Afterwards, to check that `.load` support works: +Afterwards, check that `.load` support works: ```console % sqlite3 From 20c4e664c85eb7af20a6a6d24ce35ae044df37af Mon Sep 17 00:00:00 2001 From: Mark Delk Date: Thu, 3 Jul 2025 14:07:15 -0500 Subject: [PATCH 5/8] add macos and ruby 3.4 to ci --- .github/workflows/ruby.yml | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ruby.yml b/.github/workflows/ruby.yml index 8c12d52..02749e7 100644 --- a/.github/workflows/ruby.yml +++ b/.github/workflows/ruby.yml @@ -1,20 +1,16 @@ name: CI on: - push: - branches: [ "main" ] pull_request: branches: [ "main" ] -permissions: - contents: read - jobs: test: - runs-on: ubuntu-latest + runs-on: ${{ matrix.os }} strategy: matrix: - ruby-version: ['3.3'] + ruby-version: ['3.3', '3.4'] + os: [ubuntu-latest, macos-latest] steps: - uses: actions/checkout@v4 From e315ccebab039e7e969ed1e8af7b44e5b9b12f45 Mon Sep 17 00:00:00 2001 From: Mark Delk Date: Thu, 3 Jul 2025 14:24:36 -0500 Subject: [PATCH 6/8] update gemspec --- sqlite_extensions-uuid.gemspec | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/sqlite_extensions-uuid.gemspec b/sqlite_extensions-uuid.gemspec index 73703d6..3a83e1f 100644 --- a/sqlite_extensions-uuid.gemspec +++ b/sqlite_extensions-uuid.gemspec @@ -8,10 +8,14 @@ Gem::Specification.new do |spec| spec.authors = ["Mark Delk"] spec.email = ["jethrodaniel@gmail.com"] - spec.summary = "SQLite's UUID v4 extension, packaged as a gem" + spec.summary = "SQLite's UUID v4 extension, packaged as a gem." spec.homepage = "https://github.com/jethrodaniel/sqlite_extensions-uuid" spec.license = "MIT" spec.required_ruby_version = ">= 3.0.0" + spec.metadata["allowed_push_host"] = "https://rubygems.org" + spec.metadata["homepage_uri"] = spec.homepage + spec.metadata["source_code_uri"] = spec.homepage + spec.metadata["changelog_uri"] = "#{spec.homepage}/blob/main/CHANGELOG.md" spec.files = Dir.glob("lib/**/*.rb") + Dir.glob("ext/**/*.{c,h}") spec.require_paths = ["lib"] From a2db7851a15d5dc01804d313d0fa6cde5859bf04 Mon Sep 17 00:00:00 2001 From: Mark Delk Date: Thu, 3 Jul 2025 14:24:42 -0500 Subject: [PATCH 7/8] update changelog --- CHANGELOG.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 15ccd0f..08c8e76 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,9 @@ # sqlite_extensions-uuid -Source code: https://github.com/jethrodaniel/sqlite_extensions-uuid +* Source code: https://github.com/jethrodaniel/sqlite_extensions-uuid +* Ruby gem: https://rubygems.org/gems/sqlite_extensions-uuid + +## [Unreleased] ## v1.0.2 - 2025-07-03 @@ -17,14 +20,13 @@ Source code: https://github.com/jethrodaniel/sqlite_extensions-uuid NOTE: we determine the extension using `RbConfig::CONFIG["DLEXT"]`, and we don't check if the file actually exists, we just construct the path. - Gem: [`v1.0.2`](https://rubygems.org/gems/sqlite_extensions-uuid/versions/1.0.2) +* Internal cleanup: add a changelog, add MacOS to CI, update gemspec + ## v1.0.1 - 2025-03-20 * Add `SqliteExtensions::UUID::VERSION`, use RSpec for internal tests. - Gem: [`v1.0.1`](https://rubygems.org/gems/sqlite_extensions-uuid/versions/1.0.1) - ## v1.0.0 - 2024-12-07 * Require `sqlite3-ruby` 2.4+ so we can use `sqlite3-ruby`'s extension @@ -43,5 +45,3 @@ Source code: https://github.com/jethrodaniel/sqlite_extensions-uuid extensions: - <%= SqliteExtensions::UUID.to_path %> ``` - - Gem: [`v1.0.0`](https://rubygems.org/gems/sqlite_extensions-uuid/versions/1.0.0) From ae837b5a77f7f07a5ed7d47788c0489afa99f0fc Mon Sep 17 00:00:00 2001 From: Mark Delk Date: Thu, 3 Jul 2025 14:29:02 -0500 Subject: [PATCH 8/8] actually update version, fix specs --- lib/sqlite_extensions/uuid/version.rb | 2 +- spec/sqlite_extensions/uuid_spec.rb | 17 +++++++++++------ 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/lib/sqlite_extensions/uuid/version.rb b/lib/sqlite_extensions/uuid/version.rb index 9d88a25..2f2c956 100644 --- a/lib/sqlite_extensions/uuid/version.rb +++ b/lib/sqlite_extensions/uuid/version.rb @@ -2,6 +2,6 @@ module SqliteExtensions module UUID - VERSION = "1.0.1" + VERSION = "1.0.2" end end diff --git a/spec/sqlite_extensions/uuid_spec.rb b/spec/sqlite_extensions/uuid_spec.rb index 4a839ba..d5b53e5 100644 --- a/spec/sqlite_extensions/uuid_spec.rb +++ b/spec/sqlite_extensions/uuid_spec.rb @@ -2,7 +2,7 @@ RSpec.describe SqliteExtensions::UUID do it "has a version" do - expect(described_class::VERSION).to eq "1.0.1" + expect(described_class::VERSION).to eq "1.0.2" end describe "#to_path" do @@ -38,13 +38,13 @@ end end - it "has the correct gemspec info" do + it "has the correct gemspec info" do # rubocop:disable RSpec/ExampleLength path = File.expand_path("../../sqlite_extensions-uuid.gemspec", __dir__) gemspec = Gem::Specification.load path expect(gemspec).to have_attributes( name: "sqlite_extensions-uuid", - version: Gem::Version.new("1.0.1"), + version: Gem::Version.new("1.0.2"), files: %w[ ext/sqlite_extensions/uuid/extconf.rb ext/sqlite_extensions/uuid/sqlite3.h @@ -55,13 +55,18 @@ lib/sqlite_extensions/uuid/version.rb ], licenses: ["MIT"], - metadata: {}, + metadata: { + "allowed_push_host" => "https://rubygems.org", + "changelog_uri" => "https://github.com/jethrodaniel/sqlite_extensions-uuid/blob/main/CHANGELOG.md", + "homepage_uri" => "https://github.com/jethrodaniel/sqlite_extensions-uuid", + "source_code_uri" => "https://github.com/jethrodaniel/sqlite_extensions-uuid" + }, required_ruby_version: Gem::Requirement.new([">= 3.0.0"]), - summary: "SQLite's UUID v4 extension, packaged as a gem" + summary: "SQLite's UUID v4 extension, packaged as a gem." ) require_paths = gemspec.require_paths expect(require_paths.size).to eq 2 - expect(require_paths.first).to end_with "sqlite_extensions-uuid-1.0.1" + expect(require_paths.first).to end_with "sqlite_extensions-uuid-1.0.2" expect(require_paths.last).to eq "lib" end end