Search code examples
marklogicmarklogic-optic-api

MarkLogic Optic API from-sql binding parameters


I'm trying to use the Optic API using from-sql and XQuery. I'm finding it's a great way to get the data I need but I'm trying to find clear examples of passing parameters to placeholders using op:from-sql.

For example

let $result := op:from-sql('
                  SELECT name, sum(value) 
                  FROM db.namevalue
                  WHERE client=''IBM''
                    and department in (''IT'', ''ACCOUNTS'')
                  GROUP BY name
                  ORDER BY 2 DESC
                  limit 30
               ')
             => op:result()
return $result 

works nicely and gives the results I expect.

What I need though it to parameterize so i can use variables instead of literals. I have seen the op:param but I suspect it isn't used to specify placeholders like the ? in traditional SQL environments.

eg which I know is wrong;

let $client  = "IBM
let $dept    = ("IT", "ACCOUNT")

let $result := op:from-sql('
                  SELECT name, sum(value) 
                  FROM db.namevalue
                  WHERE client=?
                    and department in (?)
                  GROUP BY name
                  ORDER BY 2 DESC
                  limit 30
               ')
             => op:result((), map:entry("$1", $client) => map:entry("$2", $dept))
return $result 

So is there an clear example of how i can do this?

Thanks,

Stephen


Solution

  • Does it work to use @ as the prefix in the SQL string? As in:

    op:from-sql('
                  SELECT name, sum(value) 
                  FROM db.namevalue
                  WHERE client=@client and department in (@department)
                  GROUP BY name
                  ORDER BY 2 DESC
                  limit 30
               ')
             => op:result((),
                 map:entry("client", $client)
                 => map:with("department", $dept))
    

    An alternative would be to express the fixed structure with Optic builder methods and to parameterize the entire SQL condition along the lines of the following untested sketch:

    op:from-view('db', 'namevalue')
        => op:where(op:sql-condition(op:param("condition")))
        => op:group-by("name", op:sum("valueSum", "value"))
        => op:order-by(op:desc("valueSum"))
        => op:limit(30)
        => op:result((), map:entry("condition", $condition))
    

    Hoping that helps,