Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passing parameters to db.query with arangojs

Tags:

arangodb

I'm having problems sending parameters with the ArangoJS library and was wondering if anyone could help.

With the example below, it is possible to execute db.query if parameter values are in the query, but as soon as I try to use bindVars I get silent errors and I can't extract any error details.

var db = require('arangojs')("http://127.0.0.1:8529");

/*
The '_system' database contains a collection called 'test' that contains one document:
 {
   "a": 1,
   "b": 2
 }
 */

// This works
db.query('FOR t IN test FILTER t.a == 1 RETURN t')
  .then((cursor) => {
    cursor.all()
      .then(vals => {
        console.log("\nNo bindVars");
        console.log(vals);
      });
  });

// This does not work
db.query("FOR t IN @first FILTER t.a == @second RETURN t", { first: "test", second: 1 })
  .then((cursor) => {
    cursor.all()
      .then(vals => {
        console.log("\nUsing bindVars");
        console.log(vals);
      });
  });

I'm new to Node.js and ArangoDB and would love to be able to use properly parameterized queries.

I'm also assuming that this use of parameters protects you from SQL Injection style attacks?

Thanks!

like image 338
David Thomas Avatar asked Jan 07 '16 08:01

David Thomas


1 Answers

The problem isn't with the JavaScript driver or Node, the problem is with the query itself:

FOR t IN @first FILTER t.a == @second RETURN t

In AQL collection names can't be injected with ordinary bind parameters. This is because you're not actually trying to use the parameter as a string value but to refer to a collection with that name. To quote the AQL documentation:

A special type of bind parameter exists for injecting collection names. This type of bind parameter has a name prefixed with an additional @ symbol (thus when using the bind parameter in a query, two @ symbols must be used).

In other words, in AQL it has to be called @@first (instead of @first) and in the bind parameters argument to db.query it has to be called @first (instead of just first).

When using arangojs it's actually possible to avoid this entirely by using the aqlQuery template handler:

var aqlQuery = require('arangojs').aqlQuery;
var first = db.collection('test');
var second = 1;

db.query(aqlQuery`
  FOR t IN ${first}
  FILTER t.a == ${second}
  RETURN t
`).then(
  cursor => cursor.all()
).then(vals => {
  console.log('Using aqlQuery');
  console.log(vals);
});

This way you don't have to think about bind parameter syntax when writing queries and can write more complex queries without having to mess with extremely long strings. Note that it will recognize arangojs collection instances and handle them accordingly. Using a string instead of a collection instance would result in the same problems as in your example.

Additionally note that the template handler also exists in the arangosh shell and in ArangoDB itself (e.g. when using Foxx).

like image 198
Alan Plum Avatar answered Oct 17 '22 13:10

Alan Plum