Lua Queries: make object attributes variables
parent
bf6a34f82c
commit
cbf227fa49
|
@ -257,7 +257,7 @@ export function evalExpression(
|
|||
if (!findFromClause) {
|
||||
throw new LuaRuntimeError("No from clause found", sf.withCtx(e.ctx));
|
||||
}
|
||||
const objectVariable = findFromClause.name || "_";
|
||||
const objectVariable = findFromClause.name;
|
||||
const objectExpression = findFromClause.expression;
|
||||
return Promise.resolve(evalExpression(objectExpression, env, sf)).then(
|
||||
async (collection: LuaValue) => {
|
||||
|
|
|
@ -124,11 +124,10 @@ Deno.test("ArrayQueryCollection", async () => {
|
|||
assertEquals(result8[2], "Jane Doe");
|
||||
assertEquals(result8[3], "Bob Johnson");
|
||||
|
||||
// Test select with native function
|
||||
// Test select with native function and implicit object variable
|
||||
const result9 = await collection2.query(
|
||||
{
|
||||
objectVariable: "p",
|
||||
select: parseExpressionString("build_name(p.firstName, p.lastName)"),
|
||||
select: parseExpressionString("build_name(firstName, lastName)"),
|
||||
},
|
||||
rootEnv,
|
||||
LuaStackFrame.lostFrame,
|
||||
|
|
|
@ -1,12 +1,31 @@
|
|||
import type { LuaExpression } from "$common/space_lua/ast.ts";
|
||||
import { LuaEnv, type LuaStackFrame } from "$common/space_lua/runtime.ts";
|
||||
import {
|
||||
LuaEnv,
|
||||
luaGet,
|
||||
luaKeys,
|
||||
type LuaStackFrame,
|
||||
} from "$common/space_lua/runtime.ts";
|
||||
import { evalExpression } from "$common/space_lua/eval.ts";
|
||||
import { asyncQuickSort } from "$common/space_lua/util.ts";
|
||||
import type { DataStore } from "$lib/data/datastore.ts";
|
||||
|
||||
function buildItemEnv(objectVariable: string, item: any, env: LuaEnv): LuaEnv {
|
||||
function buildItemEnv(
|
||||
objectVariable: string | undefined,
|
||||
item: any,
|
||||
env: LuaEnv,
|
||||
sf: LuaStackFrame,
|
||||
): LuaEnv {
|
||||
const itemEnv = new LuaEnv(env);
|
||||
itemEnv.setLocal(objectVariable, item);
|
||||
if (!objectVariable) {
|
||||
// Inject all item keys as variables
|
||||
for (const key of luaKeys(item)) {
|
||||
itemEnv.setLocal(key, luaGet(item, key, sf));
|
||||
}
|
||||
// As well as _
|
||||
itemEnv.setLocal("_", item);
|
||||
} else {
|
||||
itemEnv.setLocal(objectVariable, item);
|
||||
}
|
||||
return itemEnv;
|
||||
}
|
||||
|
||||
|
@ -19,7 +38,7 @@ export type LuaOrderBy = {
|
|||
* Represents a query for a collection
|
||||
*/
|
||||
export type LuaCollectionQuery = {
|
||||
objectVariable: string;
|
||||
objectVariable?: string;
|
||||
// The filter expression evaluated with Lua
|
||||
where?: LuaExpression;
|
||||
// The order by expression evaluated with Lua
|
||||
|
@ -55,7 +74,7 @@ export class ArrayQueryCollection<T> implements LuaQueryCollection {
|
|||
|
||||
// Filter the array
|
||||
for (const item of this.array) {
|
||||
const itemEnv = buildItemEnv(query.objectVariable, item, env);
|
||||
const itemEnv = buildItemEnv(query.objectVariable, item, env, sf);
|
||||
if (query.where && !await evalExpression(query.where, itemEnv, sf)) {
|
||||
continue;
|
||||
}
|
||||
|
@ -77,8 +96,8 @@ async function applyTransforms(
|
|||
result = await asyncQuickSort(result, async (a, b) => {
|
||||
// Compare each orderBy clause until we find a difference
|
||||
for (const { expr, desc } of query.orderBy!) {
|
||||
const aEnv = buildItemEnv(query.objectVariable, a, env);
|
||||
const bEnv = buildItemEnv(query.objectVariable, b, env);
|
||||
const aEnv = buildItemEnv(query.objectVariable, a, env, sf);
|
||||
const bEnv = buildItemEnv(query.objectVariable, b, env, sf);
|
||||
|
||||
const aVal = await evalExpression(expr, aEnv, sf);
|
||||
const bVal = await evalExpression(expr, bEnv, sf);
|
||||
|
@ -99,7 +118,7 @@ async function applyTransforms(
|
|||
if (query.select) {
|
||||
const newResult = [];
|
||||
for (const item of result) {
|
||||
const itemEnv = buildItemEnv(query.objectVariable, item, env);
|
||||
const itemEnv = buildItemEnv(query.objectVariable, item, env, sf);
|
||||
newResult.push(await evalExpression(query.select, itemEnv, sf));
|
||||
}
|
||||
result = newResult;
|
||||
|
@ -134,7 +153,7 @@ export class DataStoreQueryCollection implements LuaQueryCollection {
|
|||
) {
|
||||
// Enrich
|
||||
this.dataStore.enrichObject(value);
|
||||
const itemEnv = buildItemEnv(query.objectVariable, value, env);
|
||||
const itemEnv = buildItemEnv(query.objectVariable, value, env, sf);
|
||||
if (query.where && !await evalExpression(query.where, itemEnv, sf)) {
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -61,8 +61,8 @@ Space Lua has a feature called [[Space Lua/Lua Integrated Query]], which integra
|
|||
|
||||
${query[[
|
||||
from tag "page"
|
||||
order by _.lastModified desc
|
||||
select _.name
|
||||
order by lastModified desc
|
||||
select name
|
||||
limit 3
|
||||
]]}
|
||||
|
||||
|
|
|
@ -44,7 +44,7 @@ And the shorter:
|
|||
|
||||
from <<expression>>
|
||||
|
||||
implicitly binding each item to the variable `_`.
|
||||
implicitly binding each item to the variable `_` as well as making all attributes directly available as variables.
|
||||
|
||||
Example without variable binding:
|
||||
${query[[from {1, 2, 3} select _]]}
|
||||
|
@ -52,8 +52,8 @@ ${query[[from {1, 2, 3} select _]]}
|
|||
With variable binding:
|
||||
${query[[from n = {1, 2, 3} select n]]}
|
||||
|
||||
A more realist example using `tag`:
|
||||
${query[[from t = tag "page" limit 3 select t.name]]}
|
||||
A more realistic example using `tag`:
|
||||
${query[[from tag "page" order by lastModified select name limit 3]]}
|
||||
|
||||
## `where <expression>`
|
||||
The `where` clause allows you to filter data. When the expression evaluated to a truthy value, the item is included in the result.
|
||||
|
@ -64,7 +64,7 @@ ${query[[from {1, 2, 3, 4, 5} where _ > 2]]}
|
|||
|
||||
Or to select all pages tagged with `#meta`:
|
||||
|
||||
${query[[from tag "page" where table.includes(_.tags, "meta")]]}
|
||||
${query[[from tag "page" where table.includes(tags, "meta")]]}
|
||||
|
||||
## `order by <expression> [desc]`
|
||||
The `order by` clause allows you to sort data, when `desc` is specified it reverts the sort order.
|
||||
|
@ -72,8 +72,8 @@ The `order by` clause allows you to sort data, when `desc` is specified it rever
|
|||
As an example, the last 3 modified pages:
|
||||
${query[[
|
||||
from tag "page"
|
||||
order by _.lastModified desc
|
||||
select _.name
|
||||
order by lastModified desc
|
||||
select name
|
||||
limit 3
|
||||
]]}
|
||||
|
||||
|
@ -101,10 +101,10 @@ ${query[[from tag "page" select _.name limit 3]]}
|
|||
|
||||
You can also return tables or other complex values:
|
||||
${query[[
|
||||
from tag "page"
|
||||
from p = tag "page"
|
||||
select {
|
||||
name = _.name,
|
||||
modified = _.lastModified
|
||||
name = p.name,
|
||||
modified = p.lastModified
|
||||
}
|
||||
limit 3
|
||||
]]}
|
||||
|
|
Loading…
Reference in New Issue