Skip to content

Commit

Permalink
Added example demonstrating migration and compile-time checking with …
Browse files Browse the repository at this point in the history
…SQLite extensions
  • Loading branch information
djarb committed Feb 3, 2025
1 parent f3d2d38 commit 22d0d2c
Show file tree
Hide file tree
Showing 8 changed files with 98 additions and 0 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ members = [
"examples/postgres/mockable-todos",
"examples/postgres/transaction",
"examples/sqlite/todos",
"examples/sqlite/extension",
]

[workspace.package]
Expand Down
17 changes: 17 additions & 0 deletions examples/sqlite/extension/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
[package]
name = "sqlx-example-sqlite-extension"
version = "0.1.0"
license.workspace = true
edition.workspace = true
repository.workspace = true
keywords.workspace = true
categories.workspace = true
authors.workspace = true

[dependencies]
sqlx = { path = "../../../", features = [ "sqlite", "runtime-tokio", "tls-native-tls" ] }
tokio = { version = "1.20.0", features = ["rt", "macros"]}
anyhow = "1.0"

[lints]
workspace = true
9 changes: 9 additions & 0 deletions examples/sqlite/extension/download-extension.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#!/bin/bash

# This grabs a pre-compiled version of the extension used in this
# example, and stores it in a temporary directory. That's a bit
# unusual. Normally, any extensions you need will be installed into a
# directory on the library search path, either by using the system
# package manager or by compiling and installing it yourself.

mkdir /tmp/sqlite3-lib && wget -O /tmp/sqlite3-lib/ipaddr.so https://github.com/nalgeon/sqlean/releases/download/0.15.2/ipaddr.so
Binary file added examples/sqlite/extension/extension.test.db
Binary file not shown.
25 changes: 25 additions & 0 deletions examples/sqlite/extension/migrations/20250203094951_addresses.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
create table addresses (address text, family integer);

-- The `ipfamily` function is provided by the
-- [ipaddr](https://github.com/nalgeon/sqlean/blob/main/docs/ipaddr.md)
-- sqlite extension, and so this migration can not run if that
-- extension is not loaded.
insert into addresses (address, family) values
('fd04:3d29:9f41::1', ipfamily('fd04:3d29:9f41::1')),
('10.0.0.1', ipfamily('10.0.0.1')),
('10.0.0.2', ipfamily('10.0.0.2')),
('fd04:3d29:9f41::2', ipfamily('fd04:3d29:9f41::2')),
('fd04:3d29:9f41::3', ipfamily('fd04:3d29:9f41::3')),
('10.0.0.3', ipfamily('10.0.0.3')),
('fd04:3d29:9f41::4', ipfamily('fd04:3d29:9f41::4')),
('fd04:3d29:9f41::5', ipfamily('fd04:3d29:9f41::5')),
('fd04:3d29:9f41::6', ipfamily('fd04:3d29:9f41::6')),
('10.0.0.4', ipfamily('10.0.0.4')),
('10.0.0.5', ipfamily('10.0.0.5')),
('10.0.0.6', ipfamily('10.0.0.6')),
('10.0.0.7', ipfamily('10.0.0.7')),
('fd04:3d29:9f41::7', ipfamily('fd04:3d29:9f41::7')),
('fd04:3d29:9f41::8', ipfamily('fd04:3d29:9f41::8')),
('10.0.0.8', ipfamily('10.0.0.8')),
('fd04:3d29:9f41::9', ipfamily('fd04:3d29:9f41::9')),
('10.0.0.9', ipfamily('10.0.0.9'));
12 changes: 12 additions & 0 deletions examples/sqlite/extension/sqlx.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[common.drivers.sqlite]
# Including the full path to the extension is somewhat unusual,
# because normally an extension will be installed in a standard
# directory which is part of the library search path. If that were the
# case here, the load-extensions value could just be `["ipaddr"]`
#
# When the extension file is installed in a non-standard location, as
# in this example, there are two options:
# * Provide the full path the the extension, as seen below.
# * Add the non-standard location to the library search path, which on
# Linux means adding it to the LD_LIBRARY_PATH environment variable.
load-extensions = ["/tmp/sqlite3-lib/ipaddr"]
33 changes: 33 additions & 0 deletions examples/sqlite/extension/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
use std::str::FromStr;

use sqlx::{query, sqlite::{SqlitePool, SqliteConnectOptions}};

#[tokio::main(flavor = "current_thread")]
async fn main() -> anyhow::Result<()> {
let opts = SqliteConnectOptions::from_str(&std::env::var("DATABASE_URL")?)?
// The sqlx.toml file controls loading extensions for the CLI
// and for the query checking macros, *not* for the
// application while it's running. Thus, if we want the
// extension to be available during program execution, we need
// to load it.
//
// Note that while in this case the extension path is the same
// when checking the program (sqlx.toml) and when running it
// (here), this is not required. The runtime environment can
// be entirely different from the development one.
//
// The extension can be described with a full path, as seen
// here, but in many cases that will not be necessary. As long
// as the extension is installed in a directory on the library
// search path, it is sufficient to just provide the extension
// name, like "ipaddr"
.extension("/tmp/sqlite3-lib/ipaddr");

let db = SqlitePool::connect_with(opts).await?;

query!("insert into addresses (address, family) values (?1, ipfamily(?1))", "10.0.0.10").execute(&db).await?;

println!("Query which requires the extension was successfully executed.");

Ok(())
}
1 change: 1 addition & 0 deletions examples/x.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,3 +85,4 @@ def project(name, database=None, driver=None):
project("mysql/todos", driver="mysql_8", database="todos")
project("postgres/todos", driver="postgres_12", database="todos")
project("sqlite/todos", driver="sqlite", database="todos.db")
project("sqlite/extension", driver="sqlite", database="extension.db")

0 comments on commit 22d0d2c

Please sign in to comment.