A PartiQL evaluator for MoonBit.
Dependencies
moon add moonrockz/partiql-evalimport {
"moonrockz/partiql-eval" @eval,
"moonrockz/partiql-value" @value,
"moonrockz/partiql-value/ion" @partiql_ion,
"moonrockz/ion/ion" @ion,
"moonbitlang/x/time",
}import { "moonrockz/expect" } for "test"test {
let value = @eval.evaluate_text("1 + 2", env=@eval.Bindings::empty())
@expect.expect(value).to_equal(@value.Value::from_int(3))
}test {
let value = @eval.evaluate_text(
"SELECT VALUE x * 10 FROM [1, 2, 3] AS x WHERE x > 1",
env=@eval.Bindings::empty(),
)
@expect.expect(value == @value.Value::from_bag(@value.Bag([@value.Value::from_int(20), @value.Value::from_int(30)]))).to_be_true()
}test {
let value = @eval.evaluate_text(
"SELECT VALUE x FROM [3, 1, 2] AS x ORDER BY x DESC LIMIT 2",
env=@eval.Bindings::empty(),
)
@expect.expect(value == @value.Value::from_list([@value.Value::from_int(3), @value.Value::from_int(2)])).to_be_true()
}test {
let value = @eval.evaluate_text(
"SELECT r, SUM(s.n) AS total FROM [{'r': 'a', 'n': 1}, {'r': 'a', 'n': 2}] AS s GROUP BY s.r AS r",
env=@eval.Bindings::empty(),
)
@expect.expect(value ==
@value.Value::from_bag(
@value.Bag([
@value.Value::from_tuple(@value.Tuple([("r", @value.Value::from_string("a")), ("total", @value.Value::from_int(3))])),
]),
)).to_be_true()
}test {
let value = @eval.evaluate_text(
"UPPER(TRIM(' straße '))",
env=@eval.Bindings::empty(),
)
@expect.expect(value == @value.Value::from_string("STRASSE")).to_be_true()
}test {
let value = @eval.evaluate_text(
"CAST('3.14159' AS DECIMAL(4, 2))",
env=@eval.Bindings::empty(),
)
@expect.expect(value == @value.Value::from_decimal(@ion.Decimal::parse("3.14"))).to_be_true()
}test {
let value = @eval.evaluate_text(
"TO_STRING(DATE_ADD(day, 30, DATE '2024-02-15'), 'MMMM d, yyyy')",
env=@eval.Bindings::empty(),
)
@expect.expect(value == @value.Value::from_string("March 16, 2024")).to_be_true()
}test {
let clock = @eval.Clock::fixed(@time.date_time(2026, 10, 16, hour=9))
let value = @eval.evaluate_text(
"CURRENT_DATE",
env=@eval.Bindings::empty(),
clock~,
)
@expect.expect(value == @value.Value::from_date(@value.Date(year=2026, month=10, day=16))).to_be_true()
}test {
let input = @partiql_ion.write_bytes(@partiql_ion.read_text("{a: 2, b: $bag::[1, 3]}"))
let session = @eval.Session::Session(env=@eval.Bindings::from_ion_bytes(input))
let output = session.evaluate_ion_bytes("a + 1; SELECT VALUE x * a FROM b AS x")
@expect.expect(@partiql_ion.read_bytes(output)).to_equal(@partiql_ion.read_text("3 $bag::[2, 6]"))
}| Package | Purpose |
|---|---|
| moonrockz/partiql-eval | evaluate, evaluate_text, Bindings, Session; re-exported mode, errors, clock and zone types |
| moonrockz/partiql-eval/plan | Lowered expression and relation ADTs with source spans |
| moonrockz/partiql-eval/lower | AST-to-plan validation and name resolution |
| moonrockz/partiql-eval/ops | Pure value operators, casts, functions and clock abstraction |
| moonrockz/partiql-eval/interp | Plan execution with a fresh context per statement |
test "reusable session" {
let env = @eval.Bindings::of_pairs([("x", @value.Value(4))])
let session = @eval.Session(env~, mode=@eval.Mode::Strict)
@expect.expect(session.evaluate_script("x + 1; x * 2")).to_equal([@value.Value(5), @value.Value(8)])
}pub struct Bindings {
// private fields
}fn Bindings::from_ion_bytes(source : BytesView, catalog? : Catalog, validation? : Validation) -> Bindings raise IonDataErrorfn Bindings::from_ion_text(source : StringView, catalog? : Catalog, validation? : Validation) -> Bindings raise IonDataErrortest {
let session = @eval.Session()
@expect.expect(session.evaluate_script("1 + 2; 3 * 4")).to_equal([
@value.Value(3),
@value.Value(12),
])
}fn Session::evaluate_ion_text(self : Session, source : String, pretty? : Bool) -> String raise SessionErrortest {
let env = @eval.Bindings::of_pairs([("x", @value.Value(7))])
@expect.expect(@eval.evaluate_text("x + 1", env~)).to_equal(@value.Value(8))
}Install
Download zipA PartiQL evaluator for MoonBit.
Dependencies