diff --git a/Cargo.lock b/Cargo.lock index 24f199fd9c..edfa9c09fb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -40,6 +40,12 @@ dependencies = [ "threadpool", ] +[[package]] +name = "ahash" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6789e291be47ace86a60303502173d84af8327e3627ecf334356ee0f87a164c" + [[package]] name = "ahash" version = "0.5.8" @@ -298,13 +304,34 @@ version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" +[[package]] +name = "block-buffer" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" +dependencies = [ + "block-padding", + "byte-tools", + "byteorder", + "generic-array 0.12.3", +] + [[package]] name = "block-buffer" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" dependencies = [ - "generic-array", + "generic-array 0.14.4", +] + +[[package]] +name = "block-padding" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5" +dependencies = [ + "byte-tools", ] [[package]] @@ -345,6 +372,12 @@ version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2e8c087f005730276d1096a652e92a8bacee2e2472bcc9715a74d2bec38b5820" +[[package]] +name = "byte-tools" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" + [[package]] name = "byteorder" version = "1.3.4" @@ -369,12 +402,24 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8de60b887edf6d74370fc8eb177040da4847d971d6234c7b13a6da324ef0caf" dependencies = [ - "semver", + "semver 0.9.0", "serde", "serde_derive", "serde_json", ] +[[package]] +name = "cargo_metadata" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83f95cf4bf0dda0ac2e65371ae7215d0dce3c187613a9dbf23aaa9374186f97a" +dependencies = [ + "semver 0.11.0", + "semver-parser 0.10.0", + "serde", + "serde_json", +] + [[package]] name = "cast" version = "0.2.3" @@ -677,7 +722,7 @@ version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "58bcd97a54c7ca5ce2f6eb16f6bede5b0ab5f0055fedc17d2f0b4466e21671ca" dependencies = [ - "generic-array", + "generic-array 0.14.4", "subtle", ] @@ -726,13 +771,22 @@ dependencies = [ "zeroize 0.9.3", ] +[[package]] +name = "digest" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" +dependencies = [ + "generic-array 0.12.3", +] + [[package]] name = "digest" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" dependencies = [ - "generic-array", + "generic-array 0.14.4", ] [[package]] @@ -790,6 +844,12 @@ version = "2.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f7531096570974c3a9dcf9e4b8e1cede1ec26cf5046219fb3b9d897503b9be59" +[[package]] +name = "fake-simd" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" + [[package]] name = "fastrand" version = "1.4.0" @@ -956,6 +1016,15 @@ dependencies = [ "slab", ] +[[package]] +name = "generic-array" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec" +dependencies = [ + "typenum", +] + [[package]] name = "generic-array" version = "0.14.4" @@ -1018,6 +1087,18 @@ name = "hashbrown" version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04" +dependencies = [ + "ahash 0.4.6", +] + +[[package]] +name = "hashlink" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d99cf782f0dc4372d26846bec3de7804ceb5df083c2d4462c0b8d2330e894fa8" +dependencies = [ + "hashbrown", +] [[package]] name = "heck" @@ -1050,7 +1131,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "deae6d9dbb35ec2c502d62b8f7b1c000a0822c3b0794ba36b3149c0a1c840dff" dependencies = [ "crypto-mac", - "digest", + "digest 0.9.0", ] [[package]] @@ -1197,12 +1278,6 @@ dependencies = [ "vcpkg", ] -[[package]] -name = "linked-hash-map" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8dd5a6d5999d9907cda8ed67bbd137d3af8085216c2ac62de5be860bd41f304a" - [[package]] name = "lock_api" version = "0.4.1" @@ -1221,15 +1296,6 @@ dependencies = [ "cfg-if 0.1.10", ] -[[package]] -name = "lru-cache" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31e24f1ad8321ca0e8a1e0ac13f23cb668e6f5466c2c57319f6a5cf1cc8e3b1c" -dependencies = [ - "linked-hash-map", -] - [[package]] name = "maplit" version = "1.0.2" @@ -1254,9 +1320,9 @@ version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b5a279bb9607f9f53c22d496eade00d138d1bdcccd07d74650387cf94942a15" dependencies = [ - "block-buffer", - "digest", - "opaque-debug", + "block-buffer 0.9.0", + "digest 0.9.0", + "opaque-debug 0.3.0", ] [[package]] @@ -1470,6 +1536,12 @@ version = "11.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a170cebd8021a008ea92e4db85a72f80b35df514ec664b296fdcbb654eac0b2c" +[[package]] +name = "opaque-debug" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" + [[package]] name = "opaque-debug" version = "0.3.0" @@ -1607,6 +1679,49 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" +[[package]] +name = "pest" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10f4872ae94d7b90ae48754df22fd42ad52ce740b8f370b03da4835417403e53" +dependencies = [ + "ucd-trie", +] + +[[package]] +name = "pest_derive" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "833d1ae558dc601e9a60366421196a8d94bc0ac980476d0b67e1d0988d72b2d0" +dependencies = [ + "pest", + "pest_generator", +] + +[[package]] +name = "pest_generator" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99b8db626e31e5b81787b9783425769681b347011cc59471e33ea46d2ea0cf55" +dependencies = [ + "pest", + "pest_meta", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "pest_meta" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54be6e404f5317079812fc8f9f5279de376d8856929e21c184ecf6bbd692a11d" +dependencies = [ + "maplit", + "pest", + "sha-1 0.8.2", +] + [[package]] name = "pin-project" version = "1.0.1" @@ -1878,7 +1993,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3648b669b10afeab18972c105e284a7b953a669b0be3514c27f9b17acab2f9cd" dependencies = [ "byteorder", - "digest", + "digest 0.9.0", "lazy_static", "num-bigint-dig", "num-integer", @@ -1909,7 +2024,7 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" dependencies = [ - "semver", + "semver 0.9.0", ] [[package]] @@ -1995,7 +2110,17 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" dependencies = [ - "semver-parser", + "semver-parser 0.7.0", + "serde", +] + +[[package]] +name = "semver" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6" +dependencies = [ + "semver-parser 0.10.0", "serde", ] @@ -2005,6 +2130,16 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" +[[package]] +name = "semver-parser" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e012c6c5380fb91897ba7b9261a0f565e624e869d42fe1a1d03fa0d68a083d5" +dependencies = [ + "pest", + "pest_derive", +] + [[package]] name = "serde" version = "1.0.117" @@ -2047,17 +2182,29 @@ dependencies = [ "serde", ] +[[package]] +name = "sha-1" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7d94d0bede923b3cea61f3f1ff57ff8cdfd77b400fb8f9998949e0cf04163df" +dependencies = [ + "block-buffer 0.7.3", + "digest 0.8.1", + "fake-simd", + "opaque-debug 0.2.3", +] + [[package]] name = "sha-1" version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ce3cdf1b5e620a498ee6f2a171885ac7e22f0e12089ec4b3d22b84921792507c" dependencies = [ - "block-buffer", + "block-buffer 0.9.0", "cfg-if 1.0.0", "cpuid-bool", - "digest", - "opaque-debug", + "digest 0.9.0", + "opaque-debug 0.3.0", ] [[package]] @@ -2072,11 +2219,11 @@ version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e7aab86fe2149bad8c507606bdb3f4ef5e7b2380eb92350f56122cca72a42a8" dependencies = [ - "block-buffer", + "block-buffer 0.9.0", "cfg-if 1.0.0", "cpuid-bool", - "digest", - "opaque-debug", + "digest 0.9.0", + "opaque-debug 0.3.0", ] [[package]] @@ -2179,7 +2326,7 @@ version = "0.2.0" dependencies = [ "anyhow", "async-trait", - "cargo_metadata", + "cargo_metadata 0.10.0", "chrono", "clap 3.0.0-beta.2", "console 0.11.3", @@ -2200,7 +2347,7 @@ dependencies = [ name = "sqlx-core" version = "0.4.0" dependencies = [ - "ahash", + "ahash 0.5.8", "atoi", "base64 0.13.0", "bigdecimal", @@ -2213,13 +2360,14 @@ dependencies = [ "crossbeam-channel 0.4.4", "crossbeam-queue", "crossbeam-utils 0.7.2", - "digest", + "digest 0.9.0", "either", "encoding_rs", "futures-channel", "futures-core", "futures-util", - "generic-array", + "generic-array 0.14.4", + "hashlink", "hex", "hmac", "ipnetwork", @@ -2227,7 +2375,6 @@ dependencies = [ "libc", "libsqlite3-sys", "log", - "lru-cache", "md-5", "memchr", "num-bigint 0.3.1", @@ -2241,7 +2388,7 @@ dependencies = [ "rustls", "serde", "serde_json", - "sha-1", + "sha-1 0.9.2", "sha2", "smallvec", "sqlformat", @@ -2306,11 +2453,13 @@ dependencies = [ name = "sqlx-macros" version = "0.4.0" dependencies = [ + "cargo_metadata 0.12.1", "dotenv", "either", "futures", "heck", "hex", + "lazy_static", "proc-macro2", "quote", "serde", @@ -2742,6 +2891,12 @@ version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33" +[[package]] +name = "ucd-trie" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c" + [[package]] name = "unicode-bidi" version = "0.3.4" diff --git a/sqlx-cli/src/lib.rs b/sqlx-cli/src/lib.rs index 9d18bf51c2..ab83fdf68a 100644 --- a/sqlx-cli/src/lib.rs +++ b/sqlx-cli/src/lib.rs @@ -53,9 +53,17 @@ hint: This command only works in the manifest directory of a Cargo package."# DatabaseCommand::Setup { source } => database::setup(&source, &database_url).await?, }, - Command::Prepare { check: false, args } => prepare::run(&database_url, args)?, + Command::Prepare { + check: false, + merged, + args, + } => prepare::run(&database_url, merged, args)?, - Command::Prepare { check: true, args } => prepare::check(&database_url, args)?, + Command::Prepare { + check: true, + merged, + args, + } => prepare::check(&database_url, merged, args)?, }; Ok(()) diff --git a/sqlx-cli/src/opt.rs b/sqlx-cli/src/opt.rs index 9bddee06fc..839b33b87e 100644 --- a/sqlx-cli/src/opt.rs +++ b/sqlx-cli/src/opt.rs @@ -29,6 +29,10 @@ pub enum Command { #[clap(long)] check: bool, + /// Generate a single top-level `sqlx-data.json` file when using a cargo workspace. + #[clap(long)] + merged: bool, + /// Arguments to be passed to `cargo rustc ...`. #[clap(last = true)] args: Vec, diff --git a/sqlx-cli/src/prepare.rs b/sqlx-cli/src/prepare.rs index 8a588ba1d3..95df2c546e 100644 --- a/sqlx-cli/src/prepare.rs +++ b/sqlx-cli/src/prepare.rs @@ -13,7 +13,7 @@ use std::{env, fs}; type QueryData = BTreeMap; type JsonObject = serde_json::Map; -pub fn run(url: &str, cargo_args: Vec) -> anyhow::Result<()> { +pub fn run(url: &str, merge: bool, cargo_args: Vec) -> anyhow::Result<()> { #[derive(serde::Serialize)] struct DataFile { db: &'static str, @@ -22,7 +22,7 @@ pub fn run(url: &str, cargo_args: Vec) -> anyhow::Result<()> { } let db_kind = get_db_kind(url)?; - let data = run_prepare_step(cargo_args)?; + let data = run_prepare_step(merge, cargo_args)?; if data.is_empty() { println!( @@ -45,9 +45,9 @@ pub fn run(url: &str, cargo_args: Vec) -> anyhow::Result<()> { Ok(()) } -pub fn check(url: &str, cargo_args: Vec) -> anyhow::Result<()> { +pub fn check(url: &str, merge: bool, cargo_args: Vec) -> anyhow::Result<()> { let db_kind = get_db_kind(url)?; - let data = run_prepare_step(cargo_args)?; + let data = run_prepare_step(merge, cargo_args)?; let data_file = fs::read("sqlx-data.json").context( "failed to open `sqlx-data.json`; you may need to run `cargo sqlx prepare` first", @@ -78,7 +78,7 @@ pub fn check(url: &str, cargo_args: Vec) -> anyhow::Result<()> { Ok(()) } -fn run_prepare_step(cargo_args: Vec) -> anyhow::Result { +fn run_prepare_step(merge: bool, cargo_args: Vec) -> anyhow::Result { // path to the Cargo executable let cargo = env::var("CARGO") .context("`prepare` subcommand may only be invoked as `cargo sqlx prepare`")?; @@ -92,20 +92,41 @@ fn run_prepare_step(cargo_args: Vec) -> anyhow::Result { // have repeatedly caused issues in the past. let _ = remove_dir_all(metadata.target_directory.join("sqlx")); - let check_status = Command::new(&cargo) - .arg("rustc") - .args(cargo_args) - .arg("--") - .arg("--emit") - .arg("dep-info,metadata") - // set an always-changing cfg so we can consistently trigger recompile - .arg("--cfg") - .arg(format!( - "__sqlx_recompile_trigger=\"{}\"", - SystemTime::UNIX_EPOCH.elapsed()?.as_millis() - )) - .env("SQLX_OFFLINE", "false") - .status()?; + let check_status = if merge { + let check_status = Command::new(&cargo).arg("clean").status()?; + + if !check_status.success() { + bail!("`cargo clean` failed with status: {}", check_status); + } + + Command::new(&cargo) + .arg("check") + .args(cargo_args) + .env( + "RUSTFLAGS", + format!( + "--cfg __sqlx_recompile_trigger=\"{}\"", + SystemTime::UNIX_EPOCH.elapsed()?.as_millis() + ), + ) + .env("SQLX_OFFLINE", "false") + .status()? + } else { + Command::new(&cargo) + .arg("rustc") + .args(cargo_args) + .arg("--") + .arg("--emit") + .arg("dep-info,metadata") + // set an always-changing cfg so we can consistently trigger recompile + .arg("--cfg") + .arg(format!( + "__sqlx_recompile_trigger=\"{}\"", + SystemTime::UNIX_EPOCH.elapsed()?.as_millis() + )) + .env("SQLX_OFFLINE", "false") + .status()? + }; if !check_status.success() { bail!("`cargo check` failed with status: {}", check_status); diff --git a/sqlx-macros/Cargo.toml b/sqlx-macros/Cargo.toml index 6ddb51a59a..ab1e255de0 100644 --- a/sqlx-macros/Cargo.toml +++ b/sqlx-macros/Cargo.toml @@ -53,11 +53,13 @@ bit-vec = [ "sqlx-core/bit-vec" ] json = [ "sqlx-core/json", "serde_json" ] [dependencies] +cargo_metadata = "0.12.1" dotenv = { version = "0.15.0", default-features = false } futures = { version = "0.3.4", default-features = false, features = [ "executor" ] } hex = { version = "0.4.2", optional = true } heck = "0.3.1" either = "1.5.3" +lazy_static = "1.4.0" proc-macro2 = { version = "1.0.9", default-features = false } sqlx-core = { version = "0.4.0", default-features = false, path = "../sqlx-core" } sqlx-rt = { version = "0.2.0", default-features = false, path = "../sqlx-rt" } diff --git a/sqlx-macros/src/query/mod.rs b/sqlx-macros/src/query/mod.rs index 3ccab3139a..817e947cd7 100644 --- a/sqlx-macros/src/query/mod.rs +++ b/sqlx-macros/src/query/mod.rs @@ -1,5 +1,5 @@ -use std::borrow::Cow; use std::env; +use std::{borrow::Cow, path::PathBuf}; use proc_macro2::{Span, TokenStream}; use syn::Type; @@ -16,12 +16,29 @@ use crate::database::DatabaseExt; use crate::query::data::QueryData; use crate::query::input::RecordType; use either::Either; +use lazy_static::lazy_static; mod args; mod data; mod input; mod output; +// If we are in a workspace, lookup `workspace_root` since `CARGO_MANIFEST_DIR` won't +// reflect the workspace dir: https://github.com/rust-lang/cargo/issues/3946 +lazy_static! { + static ref CRATE_ROOT: PathBuf = { + let manifest_dir = + env::var("CARGO_MANIFEST_DIR").expect("`CARGO_MANIFEST_DIR` must be set"); + + let metadata = cargo_metadata::MetadataCommand::new() + .current_dir(manifest_dir) + .exec() + .expect("Could not fetch metadata"); + + metadata.workspace_root + }; +} + pub fn expand_input(input: QueryMacroInput) -> crate::Result { let manifest_dir = env::var("CARGO_MANIFEST_DIR").map_err(|_| "`CARGO_MANIFEST_DIR` must be set")?; @@ -47,8 +64,12 @@ pub fn expand_input(input: QueryMacroInput) -> crate::Result { _ => { let data_file_path = std::path::Path::new(&manifest_dir).join("sqlx-data.json"); + let workspace_data_file_path = CRATE_ROOT.join("sqlx-data.json"); + if data_file_path.exists() { expand_from_file(input, data_file_path) + } else if workspace_data_file_path.exists() { + expand_from_file(input, workspace_data_file_path) } else { Err( "`DATABASE_URL` must be set, or `cargo sqlx prepare` must have been run \