mirror of
https://github.com/launchbadge/sqlx
synced 2024-12-05 01:59:10 +00:00
Add a "sqlite-unbundled" feature that dynamically links to system libsqlite3.so library (#3507)
* Add a "sqlite-unbundled" feature that dynamically links to system libsqlite3.so library * update README abouot the newly-added `sqlite-unbundled` feature * Update README.md to make it clear with bulleted list Co-authored-by: Austin Bonander <austin.bonander@gmail.com> * more cfg feature updates Co-authored-by: Austin Bonander <austin.bonander@gmail.com> * update documentation in sqlx-sqlx/src/lib.rs too and also mention possible build time increasement. * cargo fmt * Add "sqlite-unbundled" feature to sqlx-cli * Add sqlite-unbundled to gituhb actions tests * cfg(feature = "sqlite") => cfg(any(feature = "sqlite", feature = "sqlite-unbundled")) * fix * CI: make sqlite-unbundled tests workaround required-features by duplicating the relevant test section * use an internal "_sqlite" feature to do the conditional compilation --------- Co-authored-by: Austin Bonander <austin.bonander@gmail.com>
This commit is contained in:
parent
68da5aefea
commit
5b8bb3b28b
20 changed files with 68 additions and 26 deletions
17
.github/workflows/sqlx.yml
vendored
17
.github/workflows/sqlx.yml
vendored
|
@ -117,6 +117,7 @@ jobs:
|
|||
strategy:
|
||||
matrix:
|
||||
runtime: [async-std, tokio]
|
||||
linking: [sqlite, sqlite-unbundled]
|
||||
needs: check
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
@ -125,7 +126,11 @@ jobs:
|
|||
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
with:
|
||||
key: "${{ runner.os }}-sqlite-${{ matrix.runtime }}-${{ matrix.tls }}"
|
||||
key: "${{ runner.os }}-${{ matrix.linking }}-${{ matrix.runtime }}-${{ matrix.tls }}"
|
||||
|
||||
- name: Install system sqlite library
|
||||
if: ${{ matrix.linking == 'sqlite-unbundled' }}
|
||||
run: sudo apt-get install -y libsqlite3-dev
|
||||
|
||||
- run: echo "using ${DATABASE_URL}"
|
||||
|
||||
|
@ -135,7 +140,7 @@ jobs:
|
|||
- run: >
|
||||
cargo test
|
||||
--no-default-features
|
||||
--features any,macros,sqlite,_unstable-all-types,runtime-${{ matrix.runtime }}
|
||||
--features any,macros,${{ matrix.linking }},_unstable-all-types,runtime-${{ matrix.runtime }}
|
||||
--
|
||||
--test-threads=1
|
||||
env:
|
||||
|
@ -151,8 +156,8 @@ jobs:
|
|||
- run: >
|
||||
cargo build
|
||||
--no-default-features
|
||||
--test sqlite-macros
|
||||
--features any,macros,sqlite,_unstable-all-types,runtime-${{ matrix.runtime }}
|
||||
--test ${{ matrix.linking }}-macros
|
||||
--features any,macros,${{ matrix.linking }},_unstable-all-types,runtime-${{ matrix.runtime }}
|
||||
env:
|
||||
SQLX_OFFLINE: true
|
||||
SQLX_OFFLINE_DIR: .sqlx
|
||||
|
@ -163,8 +168,8 @@ jobs:
|
|||
- run: >
|
||||
cargo test
|
||||
--no-default-features
|
||||
--test sqlite-macros
|
||||
--features any,macros,sqlite,_unstable-all-types,runtime-${{ matrix.runtime }}
|
||||
--test ${{ matrix.linking }}-macros
|
||||
--features any,macros,${{ matrix.linking }},_unstable-all-types,runtime-${{ matrix.runtime }}
|
||||
env:
|
||||
DATABASE_URL: sqlite://tests/sqlite/sqlite.db
|
||||
SQLX_OFFLINE: true
|
||||
|
|
|
@ -98,12 +98,14 @@ runtime-tokio-rustls = ["runtime-tokio", "tls-rustls-ring"]
|
|||
# for conditional compilation
|
||||
_rt-async-std = []
|
||||
_rt-tokio = []
|
||||
_sqlite = []
|
||||
|
||||
# database
|
||||
any = ["sqlx-core/any", "sqlx-mysql?/any", "sqlx-postgres?/any", "sqlx-sqlite?/any"]
|
||||
postgres = ["sqlx-postgres", "sqlx-macros?/postgres"]
|
||||
mysql = ["sqlx-mysql", "sqlx-macros?/mysql"]
|
||||
sqlite = ["sqlx-sqlite", "sqlx-macros?/sqlite"]
|
||||
sqlite = ["_sqlite", "sqlx-sqlite/bundled", "sqlx-macros?/sqlite"]
|
||||
sqlite-unbundled = ["_sqlite", "sqlx-sqlite/unbundled", "sqlx-macros?/sqlite-unbundled"]
|
||||
|
||||
# types
|
||||
json = ["sqlx-macros?/json", "sqlx-mysql?/json", "sqlx-postgres?/json", "sqlx-sqlite?/json"]
|
||||
|
@ -250,6 +252,11 @@ name = "sqlite-macros"
|
|||
path = "tests/sqlite/macros.rs"
|
||||
required-features = ["sqlite", "macros"]
|
||||
|
||||
[[test]]
|
||||
name = "sqlite-unbundled-macros"
|
||||
path = "tests/sqlite/macros.rs"
|
||||
required-features = ["sqlite-unbundled", "macros"]
|
||||
|
||||
[[test]]
|
||||
name = "sqlite-derives"
|
||||
path = "tests/sqlite/derives.rs"
|
||||
|
|
|
@ -183,7 +183,14 @@ be removed in the future.
|
|||
|
||||
- `mssql`: Add support for the MSSQL database server.
|
||||
|
||||
- `sqlite`: Add support for the self-contained [SQLite](https://sqlite.org/) database engine.
|
||||
- `sqlite`: Add support for the self-contained [SQLite](https://sqlite.org/) database engine with SQLite bundled and statically-linked.
|
||||
|
||||
- `sqlite-unbundled`: The same as above (`sqlite`), but link SQLite from the system instead of the bundled version.
|
||||
* Allows updating SQLite independently of SQLx or using forked versions.
|
||||
* You must have SQLite installed on the system or provide a path to the library at build time.
|
||||
See [the `rusqlite` README](https://github.com/rusqlite/rusqlite?tab=readme-ov-file#notes-on-building-rusqlite-and-libsqlite3-sys) for details.
|
||||
* May result in link errors if the SQLite version is too old. Version `3.20.0` or newer is recommended.
|
||||
* Can increase build time due to the use of bindgen.
|
||||
|
||||
- `any`: Add support for the `Any` database driver, which can proxy to a database driver at runtime.
|
||||
|
||||
|
|
|
@ -57,6 +57,7 @@ native-tls = ["sqlx/runtime-tokio-native-tls"]
|
|||
mysql = ["sqlx/mysql"]
|
||||
postgres = ["sqlx/postgres"]
|
||||
sqlite = ["sqlx/sqlite"]
|
||||
sqlite-unbundled = ["sqlx/sqlite-unbundled"]
|
||||
|
||||
# workaround for musl + openssl issues
|
||||
openssl-vendored = ["openssl/vendored"]
|
||||
|
|
|
@ -19,6 +19,9 @@ $ cargo install sqlx-cli --features openssl-vendored
|
|||
|
||||
# use Rustls rather than OpenSSL (be sure to add the features for the databases you intend to use!)
|
||||
$ cargo install sqlx-cli --no-default-features --features rustls
|
||||
|
||||
# only for sqlite and use the system sqlite library
|
||||
$ cargo install sqlx-cli --no-default-features --features sqlite-unbundled
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
|
|
@ -11,7 +11,7 @@ pub async fn create(connect_opts: &ConnectOpts) -> anyhow::Result<()> {
|
|||
let exists = crate::retry_connect_errors(connect_opts, Any::database_exists).await?;
|
||||
|
||||
if !exists {
|
||||
#[cfg(feature = "sqlite")]
|
||||
#[cfg(feature = "_sqlite")]
|
||||
sqlx::sqlite::CREATE_DB_WAL.store(
|
||||
connect_opts.sqlite_create_db_wal,
|
||||
std::sync::atomic::Ordering::Release,
|
||||
|
|
|
@ -258,7 +258,7 @@ pub struct ConnectOpts {
|
|||
/// However, if your application sets a `journal_mode` on `SqliteConnectOptions` to something
|
||||
/// other than `Wal`, then it will have to take the database file out of WAL mode on connecting,
|
||||
/// which requires an exclusive lock and may return a `database is locked` (`SQLITE_BUSY`) error.
|
||||
#[cfg(feature = "sqlite")]
|
||||
#[cfg(feature = "_sqlite")]
|
||||
#[clap(long, action = clap::ArgAction::Set, default_value = "true")]
|
||||
pub sqlite_create_db_wal: bool,
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ pub enum AnyKind {
|
|||
#[cfg(feature = "mysql")]
|
||||
MySql,
|
||||
|
||||
#[cfg(feature = "sqlite")]
|
||||
#[cfg(feature = "_sqlite")]
|
||||
Sqlite,
|
||||
|
||||
#[cfg(feature = "mssql")]
|
||||
|
@ -48,12 +48,12 @@ impl FromStr for AnyKind {
|
|||
Err(Error::Configuration("database URL has the scheme of a MySQL database but the `mysql` feature is not enabled".into()))
|
||||
}
|
||||
|
||||
#[cfg(feature = "sqlite")]
|
||||
#[cfg(feature = "_sqlite")]
|
||||
_ if url.starts_with("sqlite:") => {
|
||||
Ok(AnyKind::Sqlite)
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "sqlite"))]
|
||||
#[cfg(not(feature = "_sqlite"))]
|
||||
_ if url.starts_with("sqlite:") => {
|
||||
Err(Error::Configuration("database URL has the scheme of a SQLite database but the `sqlite` feature is not enabled".into()))
|
||||
}
|
||||
|
|
|
@ -18,6 +18,8 @@ _tls-native-tls = ["sqlx-core/_tls-native-tls"]
|
|||
_tls-rustls-aws-lc-rs = ["sqlx-core/_tls-rustls-aws-lc-rs"]
|
||||
_tls-rustls-ring = ["sqlx-core/_tls-rustls-ring"]
|
||||
|
||||
_sqlite = []
|
||||
|
||||
# SQLx features
|
||||
derive = []
|
||||
macros = []
|
||||
|
@ -26,7 +28,8 @@ migrate = ["sqlx-core/migrate"]
|
|||
# database
|
||||
mysql = ["sqlx-mysql"]
|
||||
postgres = ["sqlx-postgres"]
|
||||
sqlite = ["sqlx-sqlite"]
|
||||
sqlite = ["_sqlite", "sqlx-sqlite/bundled"]
|
||||
sqlite-unbundled = ["_sqlite", "sqlx-sqlite/unbundled"]
|
||||
|
||||
# type integrations
|
||||
json = ["sqlx-core/json", "sqlx-mysql?/json", "sqlx-postgres?/json", "sqlx-sqlite?/json"]
|
||||
|
|
|
@ -44,7 +44,7 @@ mod sqlx {
|
|||
#[cfg(feature = "postgres")]
|
||||
pub use sqlx_postgres as postgres;
|
||||
|
||||
#[cfg(feature = "sqlite")]
|
||||
#[cfg(feature = "_sqlite")]
|
||||
pub use sqlx_sqlite as sqlite;
|
||||
}
|
||||
|
||||
|
@ -61,7 +61,7 @@ impl_database_ext! {
|
|||
row: sqlx::postgres::PgRow,
|
||||
}
|
||||
|
||||
#[cfg(feature = "sqlite")]
|
||||
#[cfg(feature = "_sqlite")]
|
||||
impl_database_ext! {
|
||||
sqlx::sqlite::Sqlite,
|
||||
row: sqlx::sqlite::SqliteRow,
|
||||
|
|
|
@ -10,7 +10,7 @@ use sqlx_core::describe::Describe;
|
|||
use sqlx_core::executor::Executor;
|
||||
use sqlx_core::type_checking::TypeChecking;
|
||||
|
||||
#[cfg(any(feature = "postgres", feature = "mysql", feature = "sqlite"))]
|
||||
#[cfg(any(feature = "postgres", feature = "mysql", feature = "_sqlite"))]
|
||||
mod impls;
|
||||
|
||||
pub trait DatabaseExt: Database + TypeChecking {
|
||||
|
|
|
@ -225,7 +225,7 @@ fn expand_derive_decode_strong_enum(
|
|||
));
|
||||
}
|
||||
|
||||
if cfg!(feature = "sqlite") {
|
||||
if cfg!(feature = "_sqlite") {
|
||||
tts.extend(quote!(
|
||||
#[automatically_derived]
|
||||
impl<'r> ::sqlx::decode::Decode<'r, ::sqlx::sqlite::Sqlite> for #ident {
|
||||
|
|
|
@ -211,7 +211,7 @@ fn expand_derive_has_sql_type_strong_enum(
|
|||
}
|
||||
}
|
||||
|
||||
if cfg!(feature = "sqlite") {
|
||||
if cfg!(feature = "_sqlite") {
|
||||
tts.extend(quote!(
|
||||
#[automatically_derived]
|
||||
impl sqlx::Type<::sqlx::Sqlite> for #ident {
|
||||
|
|
|
@ -47,7 +47,7 @@ pub const FOSS_DRIVERS: &[QueryDriver] = &[
|
|||
QueryDriver::new::<sqlx_mysql::MySql>(),
|
||||
#[cfg(feature = "postgres")]
|
||||
QueryDriver::new::<sqlx_postgres::Postgres>(),
|
||||
#[cfg(feature = "sqlite")]
|
||||
#[cfg(feature = "_sqlite")]
|
||||
QueryDriver::new::<sqlx_sqlite::Sqlite>(),
|
||||
];
|
||||
|
||||
|
|
|
@ -30,6 +30,7 @@ migrate = ["sqlx-macros-core/migrate"]
|
|||
mysql = ["sqlx-macros-core/mysql"]
|
||||
postgres = ["sqlx-macros-core/postgres"]
|
||||
sqlite = ["sqlx-macros-core/sqlite"]
|
||||
sqlite-unbundled = ["sqlx-macros-core/sqlite-unbundled"]
|
||||
|
||||
# type
|
||||
bigdecimal = ["sqlx-macros-core/bigdecimal"]
|
||||
|
|
|
@ -23,6 +23,9 @@ uuid = ["dep:uuid", "sqlx-core/uuid"]
|
|||
|
||||
regexp = ["dep:regex"]
|
||||
|
||||
bundled = ["libsqlite3-sys/bundled"]
|
||||
unbundled = ["libsqlite3-sys/buildtime_bindgen"]
|
||||
|
||||
[dependencies]
|
||||
futures-core = { version = "0.3.19", default-features = false }
|
||||
futures-channel = { version = "0.3.19", default-features = false, features = ["sink", "alloc", "std"] }
|
||||
|
@ -55,7 +58,6 @@ default-features = false
|
|||
features = [
|
||||
"pkg-config",
|
||||
"vcpkg",
|
||||
"bundled",
|
||||
"unlock_notify"
|
||||
]
|
||||
|
||||
|
|
|
@ -2,7 +2,8 @@
|
|||
//!
|
||||
//! ### Note: linkage is semver-exempt.
|
||||
//! This driver uses the `libsqlite3-sys` crate which links the native library for SQLite 3.
|
||||
//! For portability, we enable the `bundled` feature which builds and links SQLite from source.
|
||||
//! With the "sqlite" feature, we enable the `bundled` feature which builds and links SQLite from
|
||||
//! source.
|
||||
//!
|
||||
//! We reserve the right to upgrade the version of `libsqlite3-sys` as necessary to pick up new
|
||||
//! `3.x.y` versions of SQLite.
|
||||
|
@ -20,6 +21,18 @@
|
|||
//! ```
|
||||
//!
|
||||
//! and then upgrade these crates in lockstep when necessary.
|
||||
//!
|
||||
//! ### Dynamic linking
|
||||
//! To dynamically link to a system SQLite library, the "sqlite-unbundled" feature can be used
|
||||
//! instead.
|
||||
//!
|
||||
//! This allows updating SQLite independently of SQLx or using forked versions, but you must have
|
||||
//! SQLite installed on the system or provide a path to the library at build time (See
|
||||
//! [the `rusqlite` README](https://github.com/rusqlite/rusqlite?tab=readme-ov-file#notes-on-building-rusqlite-and-libsqlite3-sys)
|
||||
//! for details).
|
||||
//!
|
||||
//! It may result in link errors if the SQLite version is too old. Version `3.20.0` or newer is
|
||||
//! recommended. It can increase build time due to the use of bindgen.
|
||||
|
||||
// SQLite is a C library. All interactions require FFI which is unsafe.
|
||||
// All unsafe blocks should have comments pointing to SQLite docs and ensuring that we maintain
|
||||
|
|
|
@ -41,7 +41,7 @@ pub fn install_default_drivers() {
|
|||
sqlx_mysql::any::DRIVER,
|
||||
#[cfg(feature = "postgres")]
|
||||
sqlx_postgres::any::DRIVER,
|
||||
#[cfg(feature = "sqlite")]
|
||||
#[cfg(feature = "_sqlite")]
|
||||
sqlx_sqlite::any::DRIVER,
|
||||
])
|
||||
.expect("non-default drivers already installed")
|
||||
|
|
|
@ -44,8 +44,8 @@ pub use sqlx_mysql::{self as mysql, MySql, MySqlConnection, MySqlExecutor, MySql
|
|||
#[doc(inline)]
|
||||
pub use sqlx_postgres::{self as postgres, PgConnection, PgExecutor, PgPool, Postgres};
|
||||
|
||||
#[cfg(feature = "sqlite")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "sqlite")))]
|
||||
#[cfg(feature = "_sqlite")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "_sqlite")))]
|
||||
#[doc(inline)]
|
||||
pub use sqlx_sqlite::{self as sqlite, Sqlite, SqliteConnection, SqliteExecutor, SqlitePool};
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ fn ui_tests() {
|
|||
}
|
||||
}
|
||||
|
||||
if cfg!(feature = "sqlite") {
|
||||
if cfg!(feature = "_sqlite") {
|
||||
if dotenvy::var("DATABASE_URL").map_or(true, |v| {
|
||||
Path::is_relative(v.trim_start_matches("sqlite://").as_ref())
|
||||
}) {
|
||||
|
|
Loading…
Reference in a new issue