75 lines
2.7 KiB
Plaintext
75 lines
2.7 KiB
Plaintext
---
|
|
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
|