Elixir Ecto where Query Throwing `Protocol not implemented Error` - postgresql

I have what I believe to be a relatively simple Ecto query in Elixir and it is throwing an error "protocol not implemented for" and I am very confused as to why.
So here is the query:
head_children_list = Comments
|> where([c], c.inserted_at in ^head_children)
|> Enum.sort_by(& &1["votetotal"])
So head_children is a list with one string timestamp value in it. This is the confirmed terminal output:
value of head_children
["2018-10-11 14:08:15.021033"]
So I know for a fact that this is a list. However when I try and perform the above query I get the following:
[info] Sent 500 in 168ms
[error] #PID<0.401.0> running AlbatrossWeb.Endpoint (cowboy_protocol) terminated
Server: localhost:4000 (http)
Request: POST /voteComment
** (exit) an exception was raised:
** (Protocol.UndefinedError) protocol Enumerable not implemented for #Ecto.Query<from c in Albatross.Comments, where: c.inserted_at in ^[["2018-10-11 14:08:15.021033"]]>. This protocol is implemented for: DBConnection.PrepareStream, DBConnection.Stream, Date.Range, Ecto.Adapters.SQL.Stream, File.Stream, Function, GenEvent.Stream, HashDict, HashSet, IO.Stream, List, Map, MapSet, Postgrex.Stream, Range, Stream
Notice that this says protocol is implemented for lists. But this is a list! So I am very confused. I have tried using ^[head_children], which just wraps it in another list, but this also fails with the same error.
Does anyone know what is going on?

where(Comments, [c], c.inserted_at in ^head_children) returns an %Ecto.Query{}, which is piped into Enum.sort_by/2. %Ecto.Query{} is a struct not a list, which is not Enumerable.
You probably want
head_children_list =
Comments
|> where([c], c.inserted_at in ^head_children)
|> Repo.all()
|> Enum.sort_by(& &1["votetotal"])

Related

Why are identical SQL calls behaving differently?

I'm working on a web app in Rust. I'm using Tokio Postgres, Rocket and Tera (this may be relevant).
I'm using the following to connect to my DB which doesn't fail in either case.
(sql_cli, connection) = match tokio_postgres::connect("postgresql://postgres:*my_password*#localhost:8127/*AppName*", NoTls).await{
Ok((sql_cli, connection)) => (sql_cli, connection),
Err(e) => return Err(Redirect::to(uri!(error_display(MyError::new("Failed to make SQLClient").details)))),
};
My query is as follows. I keep my queries in a separate file (I'm self taught and find that easier).
let query= sql_cli.query(mycharactersquery::get_characters(user_id).as_str(), &[]).await.unwrap();
The get characters is as follows. It takes a user ID and should return the characters that they have made in the past.
pub fn get_characters(user_id: i16) -> String {
format!("SELECT * FROM player_characters WHERE user_id = {} ORDER BY char_id ASC;", user_id)
}
In my main file, I have one GET which is /mycharacters/<user_id> which works. This GET returns an HTML file. I have another GET which is /<user_id> which returns a Tera template. The first works fine and loads the characters, the second doesn't: it just loads indefinitely. I initially thought this was to do my lack of familiarity with Tera.
After some troubleshooting, I put some printouts in my code, the one before and after the SQL call work in /mycharacters/<user_id>, but only the one before writes to the terminal in /<user_id>. This makes me think that Tera isn't the issue as it isn't making it past the SQL call.
I've found exactly where it is going wrong, but I don't know why as it isn't giving an error.
Could someone please let me know if there is something obvious that I am missing or provide some assistance?
P.S. The database only has 3 columns, so an actual timeout isn't the cause.
I expected both of these SQL calls to function as I am connected to my database properly and the call is copied from the working call.

Why do I get a "unterminated quoted string at or near" error using python postgresql, and not in pgadmin, whith the same request?

I have this query :
INSERT INTO lytnobjects.devices (id,idedge,uniqueref,constructeur,ipaddress,macaddress,
hostname,devicetype,isfirewall,isvisible,iscorporate,
ishub,osname,osversion,datecreation,lasttrafic,
hourtrafic,daytrafic,monthtrafic)
VALUES ('e1e455e98b6ed0037a58d0c1f5dc245a',3183,'TODO','TODO','192.168.143.49',
'b0:0c:d1:bb:36:1c','HPBB361C','Other',False,False,False,False,'','',
'2021-10-29T00:58:53.709','2021-01-01T00:00:00','0/0','0/0','0/0')
When I execute the query using python 3.9 and psycopg2_binary (PostgreSQL), I get an error :
unterminated quoted string at or near "'HPBB361C"
conn is the opened connection to the database (AWS RDS PostgreSQL)
sql is a string with the query above
def SQLExec(conn,sql):
try: cur = conn.cursor()
cur.execute(sql)
except (Exception, psycopg2.DatabaseError) as error:
print("***** ERROR:",error)
cur.close()
If I execute the same request from pgAdmin, I get no error !
There is no missing quote as you can see in the query, and no reason to point an error at this place!
So, I have a string (sql) with the query ("INSERT ...")
I call execute from psycopg2, and get an error: unterminated quoted string at or near "'HPBB361C"
I copy/paste the same string into pgAdmin, and the query is executed with no error
The same string (query)
Any idea why I get an error from my python app?
I am looking for an answer since many hours, but find no explanation, and I don't know how to fix the problem (which doesn't exist for me)
Your help is very appreciated
Thank you
I finaly found the answer!
I build the sql query (string) using some variables coming from various sources, like Amazon S3 for instance.
I assumed that the variable was really a string, with nothing "bizarre" in it... But in fact, sometimes, the "string" was ended with a "\x00" char, that is not displayed, so the string looks just normal :-/
When I execute my query (string) with psycopg2, it receives the extra \x00 char, which ends the string at this place! This is why it says there is a missing quote
I put a trace in the code to display the .encode() version of my string, and it revealed the \x00 at the end. So now I "clean" all string variables used in my queries, just with myvariable.replace("\x00","")
And it works now. There is probably a more conventional way to fix this...
I hope it may help somebody sometime! ;-)

Can't declare a variable in ArangoDB

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

Error message from filter array

So I have tried to get the error message from a filter array in a logic app workflow, this is what i have tried:
#body('Filter_array')['error']
#actions('Filter_array')['outputs']['body']['error']
Am I missing something or doing something wrong here?
Thanks.
UPDATE:
It says: "cannot be evaluated because property 'error' cannot be selected. ".
But i can clearly see the "error" in the body object in the output.
Ok so i managed to figure it out, i missed the fact that the array doesnt give me a single object as i thought i set it up to. so the solution was this:
#string(actions('Filter_array')['outputs']['body'][0]['error'])
Thanks for the help! :)
Can you try with #actions('Filter_array')['error'] ?
You have to distinguish 2 types of errors.
First error can occur during execution of your connector. Eg. The filter did not match. In this case, the connector executed and returns an output with an error-message.
Second error is a runtime error that can occur on the connector. For example if the input of your connector is invalid and the executing of the connector can't be triggered. In this case, the connector does not generate an output or result. In that case, you have to catch the exception with #actions('Filter_array')['error']

How to get the sql state from libpq?

I program with libpq.so. I want to get the error code which is called sql state in SQL Standard.How should I get this in my c code?
The obvious Google search for libpq get sqlstate finds the libpq-exec documentation. Searching that for SQLSTATE finds PG_DIAG_SQLSTATE in the PQresultErrorField section.
Thus, you can see that you can call PQresultErrorField(thePgResult, PG_DIAG_SQLSTATE) to get the SQLSTATE.
This is just addition I can not leave in form of comment due to reputation reasons.
Note that you can not portably get SQLSTATE for errors that can occur during PQconnectdb. In theory, you can read pg_conn (internal struct) field last_sqlstate which contains correct value.
For example, if you try to connect with invalid login/password, it will give you 28P01. For wrong database it will contain 3D000.
I wish they defined publically available getter for this field.
You can check this one as well:
libpq: How to get the error code after a failed PGconn connection