Many of the APIs we develop these days are simple CRUD (Create Read Update Delete) which are simply proxies over wherever your data is stored. Occasionally, we will need to create APIs that allow for both complex queries (ex. filters) while also being flexible to support different types of queries. A classic example is an analytics dashboard where users can perform sorting, filtering, and other transformations.
One approach to building these APIs is to simply expose your database via API. This allows frontend applications and external services to interact with our data securely and efficiently. Building SQL queries from clients is difficult and can lead to SQL injections, so how can we translate complex SQL queries into REST API requests? In this guide, we'll explore three popular query languages and frameworks—RQL, OData, and PostgREST—that help bridge the gap between SQL and REST.
Table of Contents
- Resource Query Language (RQL)
- Open Data Protocol (OData)
- PostgREST
- Comparative Analysis
- Code Samples
- FAQ: SQL to REST API Conversion
Resource Query Language (RQL)
What is RQL?
RQL stands for Resource Query Language. It's a query language designed to be used in URIs to filter and manipulate data. RQL provides a standard way to express complex queries in a RESTful API.
- Official GitHub Repository: https://github.com/persvr/rql
- CloudBlue RQL Documentation: https://connect.cloudblue.com/community/developers/api/rql/
RQL Syntax and Examples
RQL uses a syntax inspired by Lisp, using parentheses to denote operations.
Example SQL Query:
Equivalent RQL Query:
Explanation:
ge(age,18): age >= 18eq(status,'active'): status = 'active'sort(+name): ORDER BY name ASClimit(10,20): LIMIT 10 OFFSET 20
RQL Pros and Cons
Pros:
- Expressive Syntax: Can represent complex queries.
- Standardized: Provides a consistent query language across APIs.
- URL-Friendly: Designed to be used within URIs.
Cons:
- Learning Curve: Unfamiliar Lisp-like syntax.
- Complexity: Can become verbose for complex queries.
- Tooling: Less widespread support compared to OData.
RQL Tools and Libraries
- Node.js RQL Parser: rql-node
- Python RQL Parser: rql-py
- Middleware: Integrations available for Express.js and other frameworks.
Open Data Protocol (OData)
What is OData?
OData (Open Data Protocol) is an open protocol that allows the creation and consumption of queryable and interoperable RESTful APIs. It was initiated by Microsoft and has become an OASIS standard.
- Official Website: https://www.odata.org/documentation/
OData Syntax and Examples
OData uses URL query parameters prefixed with $ to denote operations.
Example SQL Query:
Equivalent OData Query:
Explanation:
$filter: Filters records.$orderby: Sorts the results.$skip: Skips the first N records.$top: Limits the number of records returned.
OData Pros and Cons
Pros:
- Widely Adopted: Broad support across languages and platforms.
- Rich Query Options: Supports complex querying, including aggregation.
- Metadata: Can provide data model metadata.
Cons:
- Complex Specification: Can be heavy for simple use cases.
- Overhead: Might introduce unnecessary complexity.
- Learning Curve: The syntax can be verbose.
Odata Tools and Libraries
PostgREST
What is PostgREST?
PostgREST is a standalone web server that turns your PostgreSQL database directly into a RESTful API. It maps HTTP requests to SQL queries efficiently and securely. Even if you aren't using Postgres, you can adopt the syntax structure (lets call it PostgREST-Flavored Query Syntax or PFQS).
- Official Query Syntax Docs: https://docs.postgrest.org/en/v12/references/api/tables_views.html
PostgREST Syntax and Examples
PostgREST uses query parameters to filter, order, and limit results.
Example SQL Query:
Equivalent PostgREST Query:
Explanation:
department=eq.Sales: department = 'Sales'salary=gt.50000: salary > 50000order=hire_date.asc: ORDER BY hire_date ASClimit=5: LIMIT 5
PostgREST Pros and Cons
Pros:
- Automatic API Generation: If you are using Postgres, there's no need to write controllers.
- Security: Leverages PostgreSQL's role-based access control.
Cons:
- Database-Specific: Only works with PostgreSQL. If you're using a different database then you'll have to write your own parser and query builder.
- Difficult to Write and Parse: At a glance, the syntax definitely seems harder to parse than RQL (the parenthesis for operations can be easily processed with recursion).
PostgREST Tools and Libraries
- PostgREST Docker Image: Docker Hub
- PostgREST Client Libraries:
- JavaScript: postgrest-js
- Python: PostgREST-py
- GUI Clients: Tools like Supabase use PostgREST under the hood.
- Standalone Converter: If you just want the syntax conversion from SQL to REST, checkout Supabase's sql-to-rest project.
We've actually built several samples using PostgREST syntax, including PostgREST + Neon and PostgREST + MySQL.
Comparative Analysis
| Feature | RQL | OData | PostgREST |
|---|---|---|---|
| Adoption | Niche | Widely adopted | Growing among PostgreSQL users |
| Complexity | Moderate | High | Low to Moderate (tooling helps a lot) |
| Flexibility | High | High | Tied to PostgreSQL capabilities |
| Ease of Use | Requires learning Lisp-like syntax | Verbose syntax | Straightforward query parameters, but queries can be difficult to build and parse manually |
| Tooling | Limited but sufficient | Extensive across platforms | Good support in JavaScript and Python |
| Database Support | Database-agnostic | Database-agnostic | PostgreSQL only |
Code Samples
Let's look at how to perform basic queries using curl and TypeScript.
Using curl
Example: Get all active users aged 18 or older, sorted by name.
RQL:
OData:
PostgREST:
Using TypeScript
RQL with TypeScript
We'll use the rql-query library to build RQL.
OData with Typescript
Let's use odata-query for this one.
PostgREST with TypeScript
We'll use the @supabase/postgrest-js library provided by Supabase.
Conclusion
Converting SQL queries to REST API requests doesn't have to be daunting. Tools like RQL, OData, and PostgREST provide robust solutions to bridge the gap between databases and RESTful services. Exposing your database via REST API can cause unforeseen security issues, even if you do protect from SQL injections. You should always use an API gateway like Zuplo to add security measures like authentication, rate-limiting, and even custom code to filter out malicious queries.