Skip to content
This repository has been archived by the owner on Nov 9, 2022. It is now read-only.

Allow running JavaScript using execute_query #821

Closed
grtjn opened this issue Jul 3, 2017 · 3 comments
Closed

Allow running JavaScript using execute_query #821

grtjn opened this issue Jul 3, 2017 · 3 comments

Comments

@grtjn
Copy link
Contributor

grtjn commented Jul 3, 2017

Would only take passing in :javascript => true in properties, and responding to that. Could be a ML8+ only..

While at it, could also support sparql, by calling /v1/graphs/sparql. ML8+ only though..

@sashamitrovich
Copy link

Excellent idea, goes towards more support for SJS by the MarkLogic ecosystem of tools.

@grtjn
Copy link
Contributor Author

grtjn commented Jan 9, 2018

As a workaround, drop this into app_specific to make it work:

  def execute_query_8(query, properties = {})
    # check input like in older versions
    if properties[:db_name] != nil
      db_id = get_db_id(properties[:db_name])
      raise ExitException.new("No Database with name #{properties[:db_name]} found") if db_id.nil?
    elsif properties[:app_name] != nil
      sid = get_sid(properties[:app_name])
      raise ExitException.new("No Server with name #{properties[:app_name]} found") if sid.nil?
    end

    headers = {
      "Content-Type" => "application/x-www-form-urlencoded"
    }
    params = {}

    # If app_name is specified, wrap the eval in an xdmp:eval to create an eval context
    # that matches that of the selected app-server
    if properties[:app_name] != nil
      eval_type = "javascript-" if properties[:javascript] != nil
      params[:xquery] = %Q{
        xquery version "1.0-ml";
        (: derived from qconsole-amped.xqy :)
        declare function local:eval-options(
          $server-id as xs:unsignedLong
        ) as element()
        {
          let $database-id := xdmp:server-database($server-id)
          let $collation := xdmp:server-collation($server-id)
          let $modules-id := xdmp:server-modules-database($server-id)
          let $xquery-version := xdmp:server-default-xquery-version($server-id)
          let $modules-root := xdmp:server-root($server-id)
          let $default-coordinate-system :=
            (: xdmp:server-coordinate-system not supported in ML8 and older :)
            for $f in fn:function-lookup(xs:QName("xdmp:server-coordinate-system"), 1)
            return $f($server-id)
          return
            <options xmlns="xdmp:eval">{
              if ($database-id eq xdmp:database()) then ()
              else element database { $database-id },
              if ($modules-id eq xdmp:modules-database()) then ()
              else element modules { $modules-id },
              if ($collation eq default-collation()) then ()
              else element default-collation { $collation },
              if (empty($default-coordinate-system)) then ()
              else element default-coordinate-system { $default-coordinate-system },
              if ($xquery-version eq xdmp:xquery-version()) then ()
              else element default-xquery-version { $xquery-version },
              (: we should always have a root path, but better safe than sorry :)
              if (empty($modules-root) or $modules-root eq xdmp:modules-root()) then ()
              else element root { $modules-root },
              element isolation { "different-transaction" }
            }</options>
        };
        let $query := <query><![CDATA[#{query}]]></query>
        return xdmp:#{eval_type}eval(
          string($query),
          (),
          local:eval-options(xdmp:server("#{properties[:app_name]}"))
        )
      }
    else
      # No app_name, just run the straight query
      if properties[:javascript] != nil
        params[:javascript] = query
      else
        params[:xquery] = query
      end

      # Pass through selected database if specified, otherwise run against App-Services
      if properties[:db_name] != nil
        params[:database] = properties[:db_name]
      end
    end

    r = go "#{@protocol}://#{@hostname}:#{@qconsole_port}/v1/eval", "post", headers, params

    raise ExitException.new(JSON.pretty_generate(JSON.parse(r.body))) if r.body.match(/\{"error"/)

    r
  end

@grtjn grtjn self-assigned this Jan 10, 2018
@grtjn grtjn added this to the January 2018 milestone Jan 10, 2018
grtjn added a commit to grtjn/roxy that referenced this issue Jan 10, 2018
grtjn added a commit that referenced this issue Jan 10, 2018
@grtjn
Copy link
Contributor Author

grtjn commented Jan 10, 2018

Fixed in dev. I'll create a separate ticket to support sparql (and sql?)

Example code:

  def testxqy
    # in XQuery || means concat, e.g. result should be 'foobar'
    r = execute_query %Q{
      "foo" || "bar"
    }
    r.body = parse_body r.body
    puts r.body

    true
  end

  def testsjs
    # In JavaScript || means OR, e.g. result should be 'foo'
    r = execute_query %Q{
      "foo" || "bar"
    }, { :javascript => true }
    r.body = parse_body r.body
    puts r.body

    true
  end

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

2 participants