Skip to main content

VillageSQL is a drop-in replacement for MySQL with extensions.

All examples in this guide work on VillageSQL. Install Now →
This guide uses a preview capability. Start the server with --vsql_allow_preview_extensions=ON, or INSTALL EXTENSION is refused.
Putting a read-only JSON endpoint in front of a few tables usually means writing a small service, deploying it, giving it a database account, and keeping it alive. VillageSQL’s vsql_rest extension serves those tables from inside the server process instead, so there is no second process and no new deployment. The defaults are built for a developer machine, not for a network. Read “Before you expose the port” below before you open it to anything.

Turning it on

Create the database and its tables first. The listener reads the database layout when it starts and caches it for vsql_rest.schema_ttl seconds, 60 by default, so a table created afterwards answers table not found until that cache expires.
Then name the database, name the tables you are willing to serve, and start the listener:

Reading

A table is a path, and the query string does the filtering. Each filter is column=operator.value:
Ask for the columns you want, and nothing else:
Combine conditions with or=(...):
Page through with limit and offset:
The operators are eq, neq, lt, lte, gt, gte, like, cs_like, in and is. in takes a list, as in ?id=in.(1,3), and is takes null, as in ?price=is.null or ?price=is.not.null. A request with no limit returns at most vsql_rest.max_rows rows, which starts at 1000.

The allowlist

A table that is not on allowed_tables does not exist as far as the API is concerned:
The response is 404, and it reads the same whether the table is absent or merely withheld.
Leaving allowed_tables empty does not mean no tables. It means all of them. Set it to the tables you intend to publish before you enable the listener.

Restricting methods per table

table_methods says which HTTP methods each table accepts, as table:METHOD,METHOD with a | between tables:
By default every table accepts every method, so set this before the listener starts. A method the table does not grant is refused:
Granting writes is the same setting:
A successful insert answers 201 with an empty body. A duplicate key comes back as 409:

Watching it work

Five status counters report on the listener, including the port it actually bound:
http_port reads 0 when nothing is listening, which is the quickest way to tell whether the listener started. Setting vsql_rest.port to 0 asks the operating system to choose a port, and this counter is where you read which one it chose.

Before you expose the port

The defaults leave the door open, and each one is reasonable alone. require_auth starts at OFF, so no request carries or needs a token. An empty allowed_tables publishes the whole schema. An empty table_methods allows every method, including DELETE, and a DELETE against a listener in that state succeeds:
It answers 204, and the row is gone. Put together, a listener switched on with nothing else configured lets anyone who can reach the port read, insert, update, and delete every table in the schema. On a laptop that is convenient. Anywhere else, change four things before enabling it:
Then serve it over HTTPS by setting ssl_cert and ssl_key. There is no bind-address setting, and the listener binds every interface from the moment it starts, so block the port at the firewall and let only a reverse proxy reach it.

Troubleshooting

See also