cd /news/developer-tools/case-study-sqlx-0-9-querybuilder-mig… · home topics developer-tools article
[ARTICLE · art-29159] src=githits.com ↗ pub= topic=developer-tools verified=true sentiment=↑ positive

Case Study: SQLx 0.9 QueryBuilder Migration

Codex GPT-5.5 migrated a Rust fixture from dynamic SQL to SQLx 0.9's QueryBuilder with push_bind, preserving SQL injection safety. The GitHits-assisted run completed 29% faster (425s vs 597s) using 64% fewer tokens (1.22M vs 3.36M) and 41% fewer tool calls than the unaided run. Both runs produced a passing patch that replaced unsafe string interpolation with bound parameters.

read3 min views14 publishedJun 3, 2026

Back to blog

June 3, 2026 · 3 min read

A measured Codex run migrating dynamic SQL to SQLx 0.9 while preserving bound user input.

The fixture is a Rust migration to sqlx 0.9.0

.

Both runs used Codex GPT-5.5 against the same fixture. The prompt was:

Fix this Rust fixture so `cargo test` succeeds against `sqlx 0.9.0`, preserving SQL injection safety.

The fixture started with stale dynamic SQL construction. SQLx 0.9 introduced SqlSafeStr

, so passing an owned dynamic String

to query_as

no longer compiled by default. AssertSqlSafe

can make dynamic SQL compile again. In this fixture, using it would keep the injection bug.

Case study replay

SQLx 0.9 SQL safety migration #

model Codex GPT-5.5Fix this Rust fixture so cargo test succeeds against sqlx 0.9.0, preserving SQL injection safety.

Without GitHits

  • tokens

  • 0

  • time

  • 0s / 597s

  • Ready. Click "Watch Replay" to start.

  • Reached the same safe QueryBuilder fix, but spent 3.36M tokens across 19 web searches and 52 shell calls.

With GitHits

  • tokens

  • 0

  • time

  • 0s / 425s

  • Ready. Click "Watch Replay" to start.

  • Used SQLx 0.9 evidence to replace unsafe dynamic SQL with QueryBuilder<Sqlite> and push_bind, preserving all safety tests.

Result #

Run Time Tokens Tools
With GitHits 425s 1.22M 44
Without GitHits 597s 3.36M 75

Both runs produced a passing patch. The GitHits run was about 29% faster, with about 64% fewer processed tokens and 41% fewer tool calls.

The fixture #

The stale implementation built SQL by interpolating user input directly into a LIKE

clause:

let sql = format!(
    "SELECT id, title FROM articles WHERE lower(title) LIKE lower('%{term}%') ORDER BY id"
);

sqlx::query_as::<_, (i64, String)>(&sql)

The tests checked three behaviors:

  • A normal case-insensitive substring search works.
  • Apostrophes, such as O'Reilly

, are treated as search data. - Injection-like input, such as ' OR 1=1 --

, does not match every article.

The correct migration used QueryBuilder<Sqlite>

and bound the user-derived search pattern:

let mut query = sqlx::QueryBuilder::<sqlx::Sqlite>::new(
    "SELECT id, title FROM articles WHERE lower(title) LIKE lower("
);
query.push_bind(format!("%{term}%"));
query.push(") ORDER BY id");

The important choice is binding user input with push_bind

. QueryBuilder

alone is not enough, because SQLx documentation explicitly warns against pushing untrusted text into SQL with .push()

.

Evidence Path #

The GitHits run checked package metadata for sqlx 0.9.0

, looked at vulnerability status, inspected dependency evidence, read changelog evidence for the SqlSafeStr

change, read SQLx docs for both AssertSqlSafe

and QueryBuilder

, inspected sqlx-core/src/sql_str.rs

, inspected query_builder.rs

, and pulled a safe QueryBuilder

SQLite LIKE

example.

That evidence established two facts.

First, SQLx 0.9’s query*()

functions now accept impl SqlSafeStr

, which is implemented for static SQL and for audited dynamic SQL through AssertSqlSafe

.

Second, AssertSqlSafe

is appropriate only when the caller has audited the dynamic SQL. In this fixture, the dynamic string contained user input. The patch needed bound parameters.

The no-GitHits run found the same final answer through a longer route: 19 web searches and 52 shell calls. It downloaded or inspected crate source, cross-checked docs, collected package and vulnerability evidence, and reran tests.

The relevant evidence was:

  • Package metadata to confirm the target version.
  • Vulnerability checks to avoid outdated risk assumptions.
  • Dependency evidence to understand the crate family involved.
  • Changelog evidence to explain the breaking change.
  • Docs and source reads to distinguish safe APIs from escape hatches.
  • Real examples to show the intended usage shape.

In this fixture, the required property was SQL injection safety. The patch had to satisfy SQLx 0.9’s type signature and keep user input bound as data.

── more in #developer-tools 4 stories · sorted by recency
── more on @codex 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
Live at https://your-agent.zahid.host
Get free account → Pricing
from €0/mo · no card required
LIVE [news/case-study-sqlx-0-9-…] indexed:0 read:3min 2026-06-03 ·