How to use variables from queries? How to run prepared queries?

In the following example, how to pass the argument object to the query?

```space-lua
function test(object)
  local objects = query[[
    from index.tag <object argument here>
  ]]
end
```
${test('some object')}

In the following example, how to run the prepared query?

```space-lua
local prepared_query = 'from index.tag "object"'

function test()
  local objects = <run the prepared_query here>
end
```
${test()}

I searched the documentation and could not find either of theese.

${test(ā€œvalue to be passedā€)}

A query I use is:
local quando = query[[from index.tag ā€œlinkā€
where string.startsWith(tostring(toPage), luogo)
and string.startsWith(page, ā€œDiario/ā€)
select{
page = page,
snippet = snippet
}
order by page desc
]]

and then the result is used as example:

for i = 1, #quando do
meta = page.meta(quando[i].page)
display = meta[1].displayName
data = date.format(estraiNome(quando[i].page), ā€œN2ā€)
text = text .. ā€œ[[ā€ .. quando[i].page .. ā€˜|’ .. data .. ']] ’ .. display .. ā€˜\n’
end

But that’s a particular query. I need to pass the variable into inside of query[[ ... ]] expressions. The issue is that it is indeed expression (addition to the Lua specific to space-lua dialect). That means that I cannot, e.g., do

local variable = 'object_name'
local results  = query[[ from index.tag ']] .. variable .. [[' select _ ]]

That would normally work in Lua but cannot work in space-lua because the query is not a function! Just try in Lua interpreter this: print([[foo']]..'bar'..[['baz]]) and you will get expected foo'bar'baz as the result. :slight_smile:

For the very same reason I also cannot do this:

local needed  = 'from index.tag "' .. variable .. '" select _'
local results = query(needed)

I still hope some way to pass the variables exist. And if no way to do it exists yet, I will fill feature request for adding the query[[ ... ]] expressions the possibility to concat with Lua strings (and other types, following the rules as concatenation normally works in Lua) and variables, if possible to achieve.

@zef Could you clarify this to some more extend, if needed, please? I may be wrong.

Does anyone has any other ideas on this topic, please?

What about wrapping it in squiggly brackets?

test = test or {}

test.queryObject = function (object)
  return query[[ from index.tag { object }]]
end

I don’t think that’s standard Lua, but it seems to work with Space Lua.

1 Like

This works, I even tried exactly that but with no success. Maybe I forgot to reload or there must had been some typo. Closing as solved. But still it would be nice if the concatenation worked. :slight_smile:

I’d love to see your full example, as I cannot get this to work. I am running edge if it makes a difference. I want to pass in a tag to a function and have it return the tasks for that tag.

When I try the example above (curly brackets) I just get an error:
error expected string, number, bigint, ArrayBufferView, boolean

@markwdev Here you are some self-contained example that works on the ā€œedgeā€ build version 2.0-beta (0.10.4-220-gf72e4bbfdbf4)…

```space-lua
function query_object(object)
  return query
  [[
    from
      index.tag {
        object
      }
    order by
      date desc
  ]]
end
```
Let’s add `#calendar` dataset now...
```#calendar
date: '2025-05-23'  # the hyphens MUST be escaped in YAML values
note: What a beautiful Friday it was!
---
date: '2025-05-22'
note: Nothing special happenned.
```
And some more data...
```#calendar
date: '2000-01-01'
note: Watched "The Apocalypse Now" on TV; twice...
```
Let's query the `#calendar` dataset with the `query_object()`...
${ query_object 'calendar' }

You should see a table rendered.

Note: Don’t forget to run System: Reload after each change to the function.

But there are still some limitations of this approach. For example query[[from index.tag {var}]] works, but query[[from ... where {var}]] always returns, even if the var is nil or false. It also does not seem the {var} get expanded in the limit {var} clause etc. @zef could you please describe the how the {...} precisely works, please? Thank you.

1 Like

TLDR: The [[ and ]] after the query keyword are not parsed as a string literal[1]. When parsed, they are delimiters for query clauses, like how () delimits the parameters for a function. Those query clauses start with the familiar keywords, from, limit, where, etc. and are followed by an expression. The {} hack I provided before meant the expression was being parsed as a table literal. Using () in that case is better because index.tag is a function. I’m not sure why it is not parsed correctly otherwise.

Limit does not need any special treatment. It can event collide with the keyword (not recommended):

test.objectAndLimit = function (object, limit)
  return query[[from t = index.tag(object) limit limit]]
end

-- outside the code block
${test.objectAndLimit('tag', 3)}

Dynamically changing a condition for where is trickier because you need to have a reference to each object in the possible results. You can do that with a function:

test.attrIsString = function (obj, attr, s)
  return obj[attr] == s
end

test.dynamicWhere = function (object, limit, where_fun, ...)
  return query[[from t = index.tag(object) where where_fun(t, unpack(..., 1)) limit limit]]
end

-- outside the space-lua block
${test.dynamicWhere('tag', 3, test.attrIsString, 'name', 'git')}
[1] Some notes from code that I used to try to explain what was going on.

From lua.grammar in source:

Query {
  kw<"query"> "[[" QueryClause* "]]" 
}

QueryClause {
  FromClause |
  WhereClause |
  OrderByClause |
  SelectClause |
  LimitClause
}

FromClause { ckw<"from"> (Name "=")? exp }
WhereClause { ckw<"where"> exp }
LimitClause { ckw<"limit"> exp ("," exp)? }
OrderByClause { ckw<"order">  ckw<"by"> list<OrderBy> }
OrderBy { exp ckw<"desc">? }
SelectClause { ckw<"select"> exp }

So the keyword ā€œqueryā€ is followed by zero or more QueryClauses surrounded by [[...]]. I think kw<> is how to specify keywords. I don’t know what ckw<> does, but I assume it is similar to providing a keyword. Note how they are all followed by exp, to some extent. Here is the definition for exp:

exp {
  kw<"nil"> | kw<"true"> | kw<"false"> | "..." |
  Number |
  LiteralString |
  prefixexp |
  BinaryExpression |
  UnaryExpression |
  TableConstructor |
  FunctionDef { kw<"function"> FuncBody } |
  Query
}

So I think my hack to wrap the argument in {..} before was a way to get the parser to interpret it as a TableConstructor argument to index.tag. Using (..) for index.tag makes it properly interpreted as a function call through prefixexp:

prefixexp {
  var |
  Parens { "(" exp ")" ~parens } |
  FunctionCall ~fcall
}
2 Likes

Sorry for the late reply, but what about just doing this?

function query_object(object)
  return query[[
    from index.tag(object)
    order by date desc
  ]]
end

index.tag is just a function you call. In Lua you can call a function without parentheses ONLY if the argument is either a literal string or table literal. In your case that’s not the case, since object is a variable, so all you have to do is simply add parentheses (like I did here). No magic. Nothing Space Lua specific here.

Just tested this, and works fine with e.g. ${query_object 'calendar'}

1 Like