# Yaal
Yaal compiles a SQL string into dialect SQL and ordered bind values. You write the full statement, mark the parts that depend on arguments, and pass a JSON object. Yaal removes the unused parts and returns the SQL plus the binds. It does not open a database, shape rows, or track entities.
```sql
--(id, active)--
select *
from users u
where optional(u.id = {{id}})
and optional(u.active = {{active}})
```
`{"id": 1}` compiles to `select * from users u where (u.id = ?)` with one bind. An omitted or null argument drops its `optional(...)` block. A list expands only where the placeholder is written with `...`:
```sql
--(id)--
where optional(u.user_id in ({{id}}...))
```
`{"id": [1, 2]}` becomes `in (?, ?)` and binds `[1, 2]`.
License: [MIT](LICENSE).
## Library
```rust
let params = serde_json::json!({"id": [1, 2]}).as_object().unwrap().clone();
let compiled = yaal::compile(sql, ¶ms, &yaal::CompileOptions::default())?;
```
`CompileOptions.placeholder` is `?` or `$1`, `$2`, …. `--sql--` splits the input into separate statements that share the same parameters. Each statement numbers its own `$1`.
The result is JSON:
```json
{
"statements": [
{
"sql": "select * from users u where (u.user_id in (?, ?))",
"parameters": [
{"name": "id", "type": "integer", "value": 1},
{"name": "id", "type": "integer", "value": 2}
]
}
]
}
```
## CLI
```bash
cargo run -p yaal-cli -- compile --sql query.sql --params params.json
cargo run -p yaal-cli -- compile --sql query.sql --param id=1 --placeholder numbered
```
SQL is read from stdin when `--sql` is omitted and stdin is not a terminal. `yaal compile` with no SQL exits instead of waiting.
## Bindings
`cargo build -p yaal-ffi` produces the shared library. Set `YAAL_LIB` to that file (`libyaal_ffi.so`, `libyaal_ffi.dylib`, or `yaal_ffi.dll`). The C functions are `yaal_compile` and `yaal_free` (`bindings/yaal.h`). Each binding returns the same JSON: `statements` of `sql` plus `parameters` (`name`, `type`, `value`). A compiler failure raises the language's compile error.
```python
import yaal
compiled = yaal.compile(sql, {"id": 1}, placeholder="question")
```
`pip install yaal-sql` installs that module with the shared library inside the wheel. The PyPI project is `yaal-sql` because the name `yaal` is already taken.
```csharp
var compiled = Yaal.Compiler.Compile(sql, new { id = 1 }, "question");
```
The NuGet package targets .NET Standard 2.0, so .NET Framework 4.6.1, .NET Core 2.0, and later can reference it. The package includes the native compiler for Linux x86_64, macOS Apple silicon, and Windows x64.
```go
import "github.com/kirubasankars/yaal/bindings/go"
compiled, err := yaal.Compile(sql, map[string]any{"id": 1}, "question")
```
`go get github.com/kirubasankars/yaal/bindings/go@v1.1.0` installs that module. The module tag is `bindings/go/v1.1.0`, and the module contains the native compiler for Linux x86_64, macOS Apple silicon, and Windows x64. `Compile` loads `YAAL_LIB` when that variable is set, then the embedded library, then the shared library built under `target/debug` or `target/release`.
```java
Yaal.Compiled compiled = Yaal.compile(sql, Map.of("id", 1), "question");
```
Java calls the library with the foreign function API, so the program needs `--enable-native-access=ALL-UNNAMED`. The Maven coordinate is `io.github.kirubasankars:yaal`. That jar contains the native compiler for Linux x86_64, macOS Apple silicon, and Windows x64.
```xml
<dependency>
<groupId>io.github.kirubasankars</groupId>
<artifactId>yaal</artifactId>
<version>1.1.0</version>
</dependency>
```
## Syntax
- [Languages](docs/languages.md)
- [Parameter header](docs/header.md)
- [optional and optional_when](docs/optional.md)
- [optional groups](docs/groups.md)
- [Nested](docs/nested.md)
- [sort and dir](docs/sort.md)
- [Safety](docs/safety.md)
- [examples](docs/examples.md)
## Build
```bash
make test
make ci
make docs
```
`make ci` is what GitHub Actions runs: the Rust tests, the language bindings, and `cargo fmt --check`.
`make docs` serves this README and the syntax pages at http://127.0.0.1:8080. Set `DOCS_PORT` to use another port. A push to `main` publishes the same pages to https://kirubasankars.github.io/yaal/.
`make test` runs the Rust tests, then the Python, Go, C#, and Java bindings against `libyaal_ffi`. The Java step needs a JDK.