- Drop file:// URL prefix from generated plug imports; use plain
absolute paths instead (esbuild resolves these natively)
- Remove the file-url-resolver esbuild plugin that was only needed
to strip that prefix
Check for already-queryable objects (e.g. `DataStoreQueryCollection`)
before `LuaTable` extraction or `luaValueToJS` conversion, preventing
them from being destroyed by the collection normalization pipeline.
Signed-off-by: Matouš Jan Fialka <mjf@mjf.cz>
- Fix `group by` key building: populate array indices from
`keyParts` instead of only from `keyRecord`, which was empty for
some expressions (e.g. `tags[1]`).
- Fix collection handling: treat record-like `LuaTables` (no array part)
as items instead of extracting zero items.
- Update test suite.
Signed-off-by: Matouš Jan Fialka <mjf@mjf.cz>
* Fix `LUA_SQL_NULL` leaking into `order by` comparisons
Note: SQL `NULLS LAST` is now default behaviour!
* Fix `objectVariable` unset for empty groups
* Fix non-grouped `having` used wrong environment builder
Note: Queries similar to the following one now works correctly:
```sql
${query[[
from
tags.page
having
name == 'index'
]]}
```
* Fix `generateKey` did not handle `LUA_SQL_NULL`
* Refactor/deduplicate duplicated `order by` comparator
* Add `isSqlNull` helper
Signed-off-by: Matouš Jan Fialka <mjf@mjf.cz>
1. Fix `order by` inability to access `select` output aliases and
aggregate functions after `group by`.
2. Introduce `LUA_SQL_NULL` sentinel to preserve column ordering when
`select` expressions evaluate to `nil`.
Note: In Lua, setting a table key to `nil` deletes it so rows with
`nil` values lose those keys and produced inconsistent insertion
order across result tables.
Signed-off-by: Matouš Jan Fialka <mjf@mjf.cz>
The `select` part operates not over a single record, but over each group
(i.e., the set of records sharing the same group key). The `select`
clause's environment is generally:
* `name` (the group key)
* `group` (the table of records in the group)
Note: no `p` is bound (`p` is not set; it was the row variable during scan, but we are now at the group level).
In the `select { name = name }` the name refers to the group key (what
we `group by`-ed).
We typically use:
* `name = name` (group key, as in the query), or
* if we want data from the first record (say all grouped `p.name` are
the same and non-`nil`) then `name = group[1].name`.
Signed-off-by: Matouš Jan Fialka <mjf@mjf.cz>
* [LIQ] Extend with `group by` and `having` support
Also update documentation with extensive examples and add some parser
tests.
Note: `make generate` JS files included.
Signed-off-by: Matouš Jan Fialka <mjf@mjf.cz>
* Merge `liq-add-support-for-aggregators` branch
Signed-off-by: Matouš Jan Fialka <mjf@mjf.cz>
* Fix link, remove `_` example
Signed-off-by: Matouš Jan Fialka <mjf@mjf.cz>
* Wrap example LIQ queries inside `query [[ .. ]]` and replace `sql` code block type to `lua`
Signed-off-by: Matouš Jan Fialka <mjf@mjf.cz>
* Example self-consistency fix
Signed-off-by: Matouš Jan Fialka <mjf@mjf.cz>
* Fixed some queries
* Add experimental tags to LIQ aggregation/grouping
---------
Signed-off-by: Matouš Jan Fialka <mjf@mjf.cz>
Co-authored-by: Zef Hemel <zef@zef.me>
* Trim user input from prompts where appropriate
* Run formatter
* Use "page title" language instead of "page name" in notifications.
Existing language in prompt asks for a "page title".
* Use const for prefix inputs as they are never trimmed
The three binary-packing functions from Lua are now implemented in
a dedicated `string_pack.ts` module and wired into `stringApi`.
Format parsing follows the exact option set of Lua:
* signed and unsigned integers of configurable width
(`b`/`B`/`h`/`H`/`l`/`L`/`j`/`J`/`T`/`i`/`I`),
* IEEE 754 single and double precision floats (`f`/`d`/`n`),
* fixed-length strings (`c`),
* length-prefixed strings (`s`),
* zero-terminated strings (`z`),
* padding bytes (`x`),
* alignment padding (`X`), and
* endianness/alignment modifiers (`<`/`>`/`=`/`!`).
`string.packsize` rejects variable-length formats (`s` and `z`) as Lua
requires.
`string.unpack` returns all unpacked values followed by the
next position integer, matching the Lua contract exactly.
Test suite extended in separates `string_pack_test.lua` file. Passes
both Lua and Space Lua execution.
Signed-off-by: Matouš Jan Fialka <mjf@mjf.cz>
`table.pack` now routes element writes through `luaSet` so `__newindex`
metamethods are honoured, matching the exact Lua 5.4 semantics. The `n`
field is still written with `rawSet`, also matching Lua.
`table.unpack` now returns an empty `LuaMultiRes` instead of `null` for
an empty range `(i > j)`. Returning `null` would inject a single `nil`
argument at the call site; an empty `LuaMultiRes` correctly contributes
zero values, matching the exact Lua semantics.
The global `unpack` shim (for Lua 5.1 compatibility) has been removed
from `luaBuildStandardEnv`. Users who need the short alias can set it up
in `space-script` with a single line stating `unpack = table.unpack`.
Signed-off-by: Matouš Jan Fialka <mjf@mjf.cz>
Returning `1` when the comparator yields `false`/`nil` declares `a > b`
for equal elements. `asyncQuickSort` tolerates this today but any future
sort algorithm change could corrupt results. Changed to `0` so ties are
neutral.
Signed-off-by: Matouš Jan Fialka <mjf@mjf.cz>
Implement `table.move(a1, f, e, t [,a2])`.
The implementation copies elements `a1[f..e]` to `a2[t..t+(e-f)]`
defaulting `a2` to `a1` and returning `a2` as follows:
* empty ranges (`e < f`) are "no-op",
* for in-table copies where `t > f` loop backwards to prevent unread
source slots from being clobbered before they are read (note: the only
case where overlap is destructive,
* cross-table copies always run forwards since there is no aliasing.
Add test suite that covers:
* non-overlapping copies,
* cross-table copies,
* both overlap directions,
* same position identity,
* empty ranges, and
* single element moves.
Each of the above is tested with both scalar and nested-table values.
Signed-off-by: Matouš Jan Fialka <mjf@mjf.cz>
`tostring()` was delegating to `luaToString()` which calls `__tostring`
with a dead stack frame, breaking metamethods that call back into
globals. Now `tostringFunction` receives the live stack frame, looks up
`__tostring` via `rawGet`, calls it through `luaCall` with the live
frame, and validates the return is a string.
Also add tests covering the basic case, the nested-call case, and the
error path for a non-string return.
Signed-off-by: Matouš Jan Fialka <mjf@mjf.cz>
Replace raw `String(v)` calls with `luaFormatNumber` in the concatenation
operator and `table.concat`, so that floats are formatted according to Lua
semantics rather than JavaScript's. This fixes cases like `10.8*22..""`
producing `237.60000000000002` instead of `237.6`, and ensures
integer-valued floats carry the `.0` suffix as Lua requires.
Signed-off-by: Matouš Jan Fialka <mjf@mjf.cz>