:rocket: sqlx4k dev update β€” what's landing next ...
# feed
y
πŸš€ sqlx4k dev update β€” what's landing next Quick heads-up on two features coming to sqlx4k (the coroutine-first SQL toolkit for Kotlin Multiplatform β€” Postgres / MySQL / MariaDB / SQLite, JVM + Native + Android). Both lean hard into the project's core idea: catch it at compile time, not in prod. πŸ‘‡ πŸ” 1. Query validations & optimizations (compile-time) We already validate
@Query
SQL for syntax and schema. The next step parses each query once and runs a set of extra safeguards + codegen rewrites β€” all through KSP, all on by default, each toggleable per module. Validations that fail the build: β€’ Column validation β€” reference a column that doesn't exist on the entity (in
SELECT
/
WHERE
/
GROUP BY
/
HAVING
/
ORDER BY
/
SET
)? Build fails. β€’ Table validation β€” a single-table query pointing at the wrong table. β€’ Statement-kind check β€”
find*/count*/exists*
must be
SELECT
,
delete*
must be
DELETE
, etc. β€’ Projection check β€” a
find*
bound to the generated row mapper must select every column (no half-mapped rows at runtime). β€’ Stacked-statement guard β€” one
@Query
, one statement. Optimizations the processor applies for you: β€’
SELECT *
expansion β€” select * from users β†’ select id, name, email from users in the generated statement. β€’
findOne*
limiting β€” appends
LIMIT 2
so the driver still detects multi-row results but transfers far less on wide tables. Everything maps columns ↔️ properties with the same rules as the CRUD generator (snake_case / @Column), so it always stays consistent with the SQL that gets generated. Don't like one of them? arg("findone-limit", "false") in your KSP block and it's gone. πŸ§ͺ 2. In-memory repositories (for unit testing) (experimental) A companion module,
sqlx4k-codegen-test
, generates a thread-safe in-memory implementation of every @Repository β€” so you can unit-test the code around your repos with no database at all. For
Sqlx4kRepository
you get
InMemorySqlx4kRepository
.
Copy code
val repo = InMemorySqlx4kRepository()
// A QueryExecutor is accepted to match the interface, but never touched.
repo.insert(db, Sqlx4k(id = 1, test = "test")).getOrThrow()
val all = repo.findAll(db).getOrThrow()
What you get out of the box: β€’ Full CRUD +
save
/
batchInsert
/
batchUpdate
, with auto-increment numeric ids. β€’ Whole-table
findAll
/
countAll
/
deleteAll
. β€’ Derived
@Query
methods β€” the in-memory behavior is derived from the query's actual SQL: the
WHERE
clause is parsed into a predicate over stored entities.
@Query("select * from users where name = :name")
just behaves like
filter { it.name == name }
. Supports
= <> < <= > >=, IS [NOT] NULL, AND/OR
, named params & literals. β€’ Test helpers β€”
clear()
,
findAllStored()
, and a
withStore { }
block for dirmap. Anything the generator can't translate (LIKE, IN, subqueries, function callsws NotImplementedError β€” and since the class is open, you just override thosefew methods yourself. It's opt-in per KSP config (kspTest), so it never touches your production wiring. Heads-up: this one's early/experimental β€” the generated API may still shift, so feedback is very welcome. πŸ™ Repo & full docs: github.com/smyrgeorge/sqlx4k β€” would love to hear what you think, especially on the in-memory repos. πŸ’¬