Files
attune/docs/development/compilation-notes.md
2026-02-04 17:46:30 -06:00

4.8 KiB

Compilation Notes

Build Cache Issues

If you see compilation errors that appear to be already fixed in the source code, the build cache may be stale.

Clear Build Cache

cargo clean -p <package-name>
# or clean everything
cargo clean

Then rebuild:

cargo build --package <package-name>

SQLx Offline Compilation

SQLx macros (query!, query_as!, query_scalar!) perform compile-time verification of SQL queries against the database schema. This requires either:

  1. Online mode: Database connection available at compile time
  2. Offline mode: Pre-generated query metadata cache

Error: Type Annotations Needed

If you see errors like:

error[E0282]: type annotations needed
   --> crates/sensor/src/rule_matcher.rs:406:13
    |
406 |         let result = sqlx::query!(
    |             ^^^^^^

This means SQLx cannot infer types because:

  • No DATABASE_URL is set
  • Query metadata cache is missing or outdated
export DATABASE_URL="postgresql://user:pass@localhost:5432/attune"
cargo build

Solution 2: Update Query Cache

Generate/update the query metadata cache:

export DATABASE_URL="postgresql://user:pass@localhost:5432/attune"
cargo sqlx prepare --workspace

This creates .sqlx/ directory with query metadata that allows offline compilation.

Commit the .sqlx/ directory to version control so others can compile without a database.

Disable compile-time verification (queries will only be checked at runtime):

cargo build --features sqlx/offline

Common Compilation Errors

1. Mismatched Types in Option Handling

Error:

error[E0308]: mismatched types
   --> src/file.rs:100:30
    |
100 |     let x = result.and_then(|row| row.field)
    |                              ^^^^^^^^^^^^^^ expected `Option<_>`, found `Value`

Cause: and_then expects a function that returns Option<T>, but row.field is already Option<T>.

Solution: Use map().flatten() for nested Options:

// Wrong
let x = result.and_then(|row| row.field);

// Right
let x = result.map(|row| row.field).flatten();

2. SQLx Query Type Inference

Error:

error[E0282]: type annotations needed
   --> src/file.rs:50:13
    |
50  |         let result = sqlx::query!(...);
    |             ^^^^^^ type must be known at this point

Cause: SQLx needs database connection to infer types.

Solutions:

  • Set DATABASE_URL environment variable
  • Run cargo sqlx prepare to generate cache
  • See "SQLx Offline Compilation" section above

3. Missing Traits

Error:

error[E0599]: the method `from_row` exists for struct `X`, but its trait bounds were not satisfied

Cause: Missing #[derive(FromRow)] on model struct.

Solution: Add SQLx derive macro:

use sqlx::FromRow;

#[derive(FromRow)]
pub struct MyModel {
    pub id: i64,
    pub name: String,
}

Development Workflow

  1. Keep database running during development:

    docker run -d -p 5432:5432 -e POSTGRES_PASSWORD=postgres postgres:14
    export DATABASE_URL="postgresql://postgres:postgres@localhost:5432/attune"
    
  2. Apply migrations:

    sqlx database create
    sqlx migrate run
    
  3. Generate query cache (for CI/CD):

    cargo sqlx prepare --workspace
    git add .sqlx/
    git commit -m "Update SQLx query cache"
    
  4. Build normally:

    cargo build
    

CI/CD Pipeline

For continuous integration without database access:

  1. Commit .sqlx/ directory with prepared query metadata
  2. Enable offline mode in CI:
    SQLX_OFFLINE=true cargo build --release
    

Troubleshooting

Build succeeds but tests fail

# Ensure database is running and migrations are applied
export DATABASE_URL="postgresql://postgres:postgres@localhost:5432/attune_test"
sqlx database create
sqlx migrate run

# Run tests
cargo test

Query cache out of sync

# Delete old cache
rm -rf .sqlx/

# Regenerate
export DATABASE_URL="postgresql://postgres:postgres@localhost:5432/attune"
cargo sqlx prepare --workspace

"prepared statement already exists"

This typically indicates multiple connections trying to prepare the same statement. Solutions:

  • Use connection pooling (already implemented in attune_common::db)
  • Ensure tests use separate database instances
  • Clean up connections properly

See Also