Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(sqlx-cli): do not clean sqlx during prepare #2786

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

cycraig
Copy link
Contributor

@cycraig cycraig commented Sep 27, 2023

Description

Fix cargo sqlx prepare --workspace running cargo clean -p sqlx unnecessarily.

See #2785

This should be a non-breaking change. It shouldn't affect in-workspace dependencies that happen to be named sqlx either.

How to test or review this PR

  • Checkout this branch and install sqlx-cli.
cargo install -f --path ./sqlx-cli
  • Run cargo sqlx prepare --workspace in a project with crates that use query! macros.

The timing difference is quite significant in a larger workspace, saves ~40 seconds on an incremental build.

BEFORE:

$ time cargo sqlx prepare --database-url "postgresql://postgres:password@localhost/example" --workspace -- --all-targets --all-features
    Cleaning [=============================] 1/1: sqlx, 0 files/folders cleaned 
...
    Finished dev [unoptimized + debuginfo] target(s) in 19.83s
query data written to .sqlx in the workspace root; please check this into version control
make sqlx-prepare  80.33s user 28.84s system 138% cpu 1:18.64 total

AFTER (this PR, note there is no cleaning step):

$ time cargo sqlx prepare --database-url "postgresql://postgres:password@localhost/example" --workspace -- --all-targets --all-features
...
    Finished dev [unoptimized + debuginfo] target(s) in 15.88s
query data written to .sqlx in the workspace root; please check this into version control
make sqlx-prepare  36.71s user 13.13s system 260% cpu 19.155 total

@cycraig
Copy link
Contributor Author

cycraig commented Sep 27, 2023

The unit test is failing because it checks that the sqlx dependency is marked to be cleaned. This seems unintentional, as the original PR for that test mentioned sqlx was intended to be ignored: #1802 (comment)

Edit: not sure how to update the test right now without losing coverage or adding +10,000 useless lines of Cargo.lock, may come back to this later.

@abonander
Copy link
Collaborator

The only reason we clean anything in the first place is it seems like the only surefire way to force a recompile so that the proc macros actually execute. If you have any thoughts there, we could get rid of the cleaning entirely.

@cycraig
Copy link
Contributor Author

cycraig commented Nov 21, 2023

Unfortunately it looks like cargo clean remains the only recommended way to force recompilation, so we're kind of stuck with it: rust-lang/cargo#1101 (comment)

Regarding avoiding cleaning dependencies unnecessarily, I'm still encountering problems with this patch due to feature unification.

E.g. pgvector-rust disables all default features of sqlx, so it shouldn't depend on sqlx-macros. However, when used in a workspace with macros enabled, e.g. sqlx = { version = "0.7", default-features = false, features = ["macros"] }, it will appear as a dependency for pgvector-rust.

cargo tree -i sqlx-macros - essentially what metadata.all_dependents_of does:

sqlx-macros v0.7.2 (proc-macro)
└── sqlx v0.7.2
    ├── example v0.1.0 (/tmp/example)
    └── pgvector v0.3.2
        └── example v0.1.0 (/tmp/example)

This is just expected behaviour; I think we would need a way to isolate the features/dependencies of a particular dependency to avoid it (assuming the clean behaviour is kept)?

Maybe a CLI argument could be added as a manual workaround, e.g. cargo sqlx prepare --no-clean pgvector,other? Not great though.

@abonander
Copy link
Collaborator

Would the fix maybe be just cleaning workspace crates? Or just the current crate?

@cycraig
Copy link
Contributor Author

cycraig commented Nov 21, 2023

Would the fix maybe be just cleaning workspace crates? Or just the current crate?

There may be out-of-workspace dependencies that contain query macros, so I don't think that would work in general.

sqlx-prepare only cleans dependencies for --workspace (to ensure all queries are generated and combined), only the current crate is touched otherwise. I guess technically that misses the case where prepare is run on a non-workspace crate that relies on a dependency with query macros, but it's probably uncommon.

@abonander
Copy link
Collaborator

Ignoring non-workspace crates seems fine to me. Those should be prepared separately.

@cycraig
Copy link
Contributor Author

cycraig commented Nov 28, 2023

Ignoring non-workspace crates seems fine to me. Those should be prepared separately.

Is that possible, to vendor prepared query macros from dependencies? How can query macros from a

  • local dependency (crate/workspace in the same repo or a git submodule, just not in the same workspace),
  • git dependency, or
  • registry dependency (from crates.io or other registry, least common),

be prepared to ensure they're valid against a different database?

I'm all for ignoring (not cleaning) non-workspace crates, but there do seem to be valid, if uncommon, cases where it may be needed. Maybe just hide the behaviour behind a coarse CLI flag? (As opposed to a fine-grained flag suggested in my previous comment).

E.g.

  1. (breaking) --clean-deps: change prepare to ignore cleaning non-workspace dependencies by default, unless this flag is specified.
  2. (non-breaking) --no-clean-deps: keep current clean behaviour in prepare, allow users to disable it with this flag.

In both cases, prepare would still touch files in the workspace to force recompilation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants