Query is a Rust server that provides an API, CLI, and authentication for remote interaction with SQLite databases. It has introduced "functions" to enhance your product with hosted JavaScript code accessing remote SQLite databases.
Let's explore a practical example of a Query function:
export async function handleRequest(req) {
const db = new Database("example.sql");
const result = await db.query("SELECT * FROM example WHERE id = ?", [1]);
return new Response(JSON.stringify({ data: result }), {
status: 200,
headers: {
"content-type": "application/json",
},
});
}
In this example, the function fetches data from a database table and responds with a JSON object containing the result.
A Query function follows a specific format. It exports an asynchronous function named handleRequest
that takes a Request and returns a Response.
A connection to a database is required to interact with databases using the Query function. It can be achieved by utilizing the Database
constructor.
const db = new Database("example.sql");
The Database
constructor takes the name of the database. Once connected, it provides two essential methods:
-
query
: Reads data from the database. -
execute
: Writes data to the database.
Both query
and execute
can accept parameters as an array or an object with placeholders like :AAA
, $AAA
, or @AAA
.
Remember, when working with Query and LiteFS proxy, use GET
to read data and DELETE|POST|PUT|PATCH
to write data.
Query follows a specific folder structure to organize functions and define routes. Here's an example:
functions
├── get.index.js // GET "/"
├── post.index.js // POST "/"
├── example
├── get.index.js // GET "/example"
├── get.[slug].js // GET "/example/:slug"
[slug]
├── get.index.js // GET "/:slug"
...
The prefix determines the method used in a file (delete|get|patch|post|put).*
. The remaining part of the file name defines the final segment of the route. For instance, if the file name ends with index
, it represents the root of the route.
If you're looking to deploy and replicate your databases across the globe quickly, Fly.io provides a seamless solution to run a Query Server in just a few minutes.
To incorporate Query into your deployment, your Dockerfile needs to include the Query Server. Consider using a multistage Dockerfile, with the final stage being a compatible x86_64-unknown-linux-gnu
image, such as debian:<suite>-slim
. Refer to the LiteFS documentation for critical information on this essential system component.
Here is a sample Dockerfile for your Query Server:
FROM debian:12-slim
ADD litefs.yml /etc/litefs.yml
COPY --from=flyio/litefs:0.5 /usr/local/bin/litefs /usr/local/bin/litefs
RUN apt-get update -qq && \
apt-get install -y --no-install-recommends \
ca-certificates \
sqlite3 \
fuse3 \
curl
# Download and install Query Server
RUN curl --proto '=https' --tlsv1.2 -LsSf https://github.com/gc-victor/query/releases/latest/download/query-server-installer.sh | sh
EXPOSE 3000
CMD ["litefs", "mount"]
Additionally, to kickstart the server, add this command to the litefs.yml configuration file:
...
exec:
- cmd: "~/.cargo/bin/query-server"
...
With these components in place, your Query Server will be ready to deploy on Fly, providing a robust and globally accessible solution.
Let's install the toolset to deploy the functions.
We have to install the Query CLI. It is a powerful tool that lets you manage your remote SQLite databases with ease and safety.
Form macOS and Linux (not NixOS, Alpine, or Asahi):
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/gc-victor/query/releases/latest/download/query-installer.sh | sh
The functions will bundle using esbuild. For that, it is required to install esbuild globally:
npm install --global esbuild
Finally, to deploy the functions, run:
query function
With their structured approach and database integration, Query functions offer a robust foundation for building scalable and efficient Function as a Service (FaaS).
Top comments (0)