--- title: "Rust: sqlx without macros" author: "James Pace" date: "2024/01/01" --- [`sqlx`](https://github.com/launchbadge/sqlx) is a Rust crate that allows for interacting with a SQL database. One of the more popular features of `sqlx` is that it does compile time checking of database queries (giving you some ORM-ish properties) while still allowing you to write straight SQL queries without the abstraction of an ORM though use of their [`query!`](https://docs.rs/sqlx/0.5.5/sqlx/macro.query.html). To make this work, `sqlx` requires: 1. access to a database at compile time, OR 2. config files to be generated from a running database everytime the database queries are modified. I don't particularly like either of those options, though I admittedly have not tried either of them long term. Requring a running database at compile time would seem to make compilation a lot slower. It also adds a unexpected step (run a container hosting a development database) before you can compile, which just feels wrong. The configuation files are better in the sense they don't require a running database at compile time, but it's an extra thing that has to be kept in sync with the code. Luckily, `sqlx` provides functions that can be used to do queries that aren't checked at compile time for people with the same concerns as I have. Because this isn't the recommended path though, the number of examples of using the functions online is a little lacking, which I'll make an effort to improve in this post. The other thing I'll show in this post is working with JSON in Postgres. Postgres has native support for working with JSON documents, providing a lot of the benefits of NoSQL databases, but in a SQL database. `sqlx`'s API for json documents integrates well with serde, and is resonably easy to work with. # Pre-reqs Running the example requires a running Postgres database, which I'm going to run locally via [`podman`](https://podman.io/) using the bash script below. ```bash #!/usr/bin/env bash DATA_DIR="$PWD/data" if [ ! -d "$DATA_DIR" ]; then echo "Making data directory." mkdir $DATA_DIR fi podman run --rm --name test-db --network=host \ -e POSTGRES_USER=postgres \ -e POSTGRES_PASSWORD=devpassword \ -e PGDATA=/var/lib/postgresql/data/pgdata \ -v $DATA_DIR:/var/lib/postgresql/data \ docker.io/library/postgres:latest ``` The script: 1. Defines `DATA_DIR` which will be a local host directory we will mount in the database container and tell the database to save its files to so they persist beyond container restarts. 2. Makes that directory if it is missing. 3. Starts a container running the official postgres image. Environment variables are used to set some settings to values suitable for local testing. # Example