Can't declare a variable in ArangoDB - nosql

I'm using ArangoDB 3.4.6-1 and would like to delete vertices with AQL (as stated here) in online console.
In the first step according to the tutorial you are supposed to save your Edges into a variable. In my case the statement looks like this:
LET edgeKeys = (FOR v, e, p IN 1..100 INBOUND 'Node/N3' GRAPH 'graph' RETURN e._key)
The For itself without the brackets returns the correct result:
[
"E3"
]
Yet, running the whole statement with the brackets just throws the following error:
Query: AQL: syntax error, unexpected end of query string near ')' at position 1:83 (while parsing)
I tried using a comparable command with other graphs or other returned values and objects, but always get the same error.
So far I wasn't able to find a proper solution online. The tutorial provides the following example code (copied 1:1):
LET edgeKeys = (FOR v, e IN 1..1 ANY 'persons/eve' GRAPH 'knows_graph' RETURN e._key)
And I'm getting exactly the same error, it's not even able to check the collections.
What am I doing wrong?

Only defining a variable with LET is not a valid AQL statement.
From the AQL Syntax documentation:
An AQL query must either return a result (indicated by usage of the
RETURN keyword) or execute a data-modification operation (indicated by
usage of one of the keywords INSERT, UPDATE, REPLACE, REMOVE or
UPSERT). The AQL parser will return an error if it detects more than
one data-modification operation in the same query or if it cannot
figure out if the query is meant to be a data retrieval or a
modification operation.
Using the full AQL block that is stated in the tutorial the execution works as expected since the query is executing a data-modification with REMOVE in this case. Just a RETURN operation inside the LET variable declaration is not sufficient to run an AQL query. When removing the LET operation the query works as well since in this case the AQL query directly returns the result.
Complete AQL query:
LET edgeKeys = (FOR v, e IN 1..1 ANY 'persons/eve' GRAPH 'knows_graph' RETURN e._key)
LET r = (FOR key IN edgeKeys REMOVE key IN knows)
REMOVE 'eve' IN persons
An additional RETURN also makes the query work:
LET edgeKeys = (FOR v, e IN 1..1 ANY 'persons/eve' GRAPH 'knows_graph' RETURN e._key)
RETURN edgeKeys

Related

Postgres LIKE %% syntax errors

I have been trying to do a LIKE comparison in postgres but repeatedly receive an error telling me that the column "%#firstname%" doesn't exist.
I should clarify, this query is executed in a function, "#firstname" is the parameter passed into the function.
The relevant section of the query is below:
WHERE u."firstname" LIKE "%#firstname%"
I do not want an exact comparison which is why I am trying to add the %% to the query. It works just fine without them for exact queries. Whenever, I add the % then it assumes that they are part of the variable name and subsequently can't find it.
I have also tried the following:
'%"#firstname"%' which results in an empty array being returned even though it should have matched
"%'#firstname'%" which results in error: column "%'#filter'%" does not exist
%"#firstname"% which results in error: column "%'#filter'%" does not exist
If "#firstname" is a parameter you need something like:
WHERE u.firstname LIKE concat('%', "#firstname", '%');

How to use asynchronous feature of pyscopg2?

I'm trying to execute 3 different postgresql queries with different table. Each query takes 2 seconds to execute. I was wondering if it's possible to run all 3 queries at the same time so that I can save 4 seconds. I tried using the asynchronous feature of pyscopg2 but it only returns the result of last query. Can anyone point out what I'm doing wrong ?
import select
import psycopg2
import psycopg2.extensions
def wait(conn):
while 1:
state = conn.poll()
if state == psycopg2.extensions.POLL_OK:
break
elif state == psycopg2.extensions.POLL_WRITE:
select.select([], [conn.fileno()], [])
elif state == psycopg2.extensions.POLL_READ:
select.select([conn.fileno()], [], [])
else:
raise psycopg2.OperationalError("poll() returned %s" % state)
aconn = psycopg2.connect(
dbname=pg_name,
user=pg_username,
host=pg_host,
password=pg_password,
async=1)
wait(aconn)
acurs = aconn.cursor()
acurs.execute(
"SELECT 1;"
"SELECT ST_Length(ST_GeomFromText"
"('LINESTRING(743238 2967416,743238 2967450)',4326));"
"SELECT 3;"
)
wait(acurs.connection)
result = acurs.fetchall()
print result
This only prints: "result": [[3]]
Per the Psycopg Introduction:
[Psycopg] is a wrapper for the libpq, the official PostgreSQL client library.
Then, looking at the libpq documentation for PQexec() (the function used to send SQL queries to the PostgreSQL database), we see the following note (emphasis mine):
Multiple queries sent in a single PQexec call are processed in a single transaction, unless there are explicit BEGIN/COMMIT commands included in the query string to divide it into multiple transactions. Note however that the returned PGresult structure describes only the result of the last command executed from the string.
So, unfortunately, what you're trying to do is simply not supported by psycopg2 and libpq. (This isn't to say that other client interfaces to PostgreSQL don't support it, though, but that's out of scope for this question.)
So to answer your question, what you're doing wrong is executing multiple SQL queries in one execute() call and trying to retrieve all of their results afterwards, when in fact it's not possible. You need to explicitly execute each query and retrieve the results individually, or else try and find another API to PostgreSQL that supports returning multiple result sets at once.
The Python Database API 2.0 specification does allow for the optional nextset() method to be implemented by the library which moves the cursor to the next result set returned from the queries executed, but this method is not implemented in psycopg2 (for obvious reasons) and in fact raises a NotSupportedError exception if you try to call it (see the docs).
It looks like it is now supported as of version 2.2
def wait(conn):
while True:
state = conn.poll()
if state == psycopg2.extensions.POLL_OK:
break
elif state == psycopg2.extensions.POLL_WRITE:
select.select([], [conn.fileno()], [])
elif state == psycopg2.extensions.POLL_READ:
select.select([conn.fileno()], [], [])
else:
raise psycopg2.OperationalError("poll() returned %s" % state)
Source: https://www.psycopg.org/docs/advanced.html#asynchronous-support

ArangoDB AQL is affected by the injection issue?

I'm working with AQL in these days, and I'm creating a library for dynamically creating the AQL script.
Because I didn't find anything related to the PARAMETER INJECTION issue (like SQL INJECTION) do you think that is secure if I set my FILTER variable directly inside the AQL query string?
If you are using bindParameters for all user-defined input the value inserted will not be evaluated by the AQL parser and hence injected code will not be executed.
Safe query:
FOR x IN items FILTER x.name == #name RETURN x
Unsafe query:
"FOR x IN items FILTER x.name == " + name + " RETURN x"
Inserting sth. like
'a' LET t = (FOR h IN items DELETE h)
in name will return all elements having exactly this string in the save query (not harmful).
In the unsafe query it will drop all elements in items (harmful).

(kdb+/q) append to dictionary

I am trying to programmatically construct arguments to functional select call having the form:
?[ `t; () ; groupBy; ()]
The problematic part is groupBy, which should be a dictionary.
Suppose the objective is to arrive at the parse tree in the form:
parse "select by sym,month:`date$dt.month from t"
I start constructing the by part with:
groupBy: enlist[`sym]!enlist(`sym)
Then I try to append the month part of the group by statement (note that periodicity is parameterised):
per: `month / monthly periodicity
groupBy,: {enlist[x]!enlist[ $[x = `day;
`dt;
$[x=`month;
((parse "select by month:`date$dt.month from x")#3)#`month
;` sv (`dt,x)]
]]
}[per]
However, that throws type error. What goes wrong?
I think it doesn't like the compound assignment
groupBy,:{...}
Try
groupBy:groupBy,{...}
The difference is that in the first case it's trying to directly alter the data in memory without creating a copy, whereas in the second case it is creating a copy of the data in memory and then re-assigning it to that variable. Perhaps the compound assignment only works when the types are uniform

Erlang mnesia equivalent of "select * from Tb"

I'm a total erlang noob and I just want to see what's in a particular table I have. I want to just "select *" from a particular table to start with. The examples I'm seeing, such as the official documentation, all have column restrictions which I don't really want. I don't really know how to form the MatchHead or Guard to match anything (aka "*").
A very simple primer on how to just get everything out of a table would be very appreciated!
For example, you can use qlc:
F = fun() ->
Q = qlc:q([R || R <- mnesia:table(foo)]),
qlc:e(Q)
end,
mnesia:transaction(F).
The simplest way to do it is probably mnesia:dirty_match_object:
mnesia:dirty_match_object(foo, #foo{_ = '_'}).
That is, match everything in the table foo that is a foo record, regardless of the values of the fields (every field is '_', i.e. wildcard). Note that since it uses record construction syntax, it will only work in a module where you have included the record definition, or in the shell after evaluating rr(my_module) to make the record definition available.
(I expected mnesia:dirty_match_object(foo, '_') to work, but that fails with a bad_type error.)
To do it with select, call it like this:
mnesia:dirty_select(foo, [{'_', [], ['$_']}]).
Here, MatchHead is _, i.e. match anything. The guards are [], an empty list, i.e. no extra limitations. The result spec is ['$_'], i.e. return the entire record. For more information about match specs, see the match specifications chapter of the ERTS user guide.
If an expression is too deep and gets printed with ... in the shell, you can ask the shell to print the entire thing by evaluating rp(EXPRESSION). EXPRESSION can either be the function call once again, or v(-1) for the value returned by the previous expression, or v(42) for the value returned by the expression preceded by the shell prompt 42>.