Clojure JDBC - This ResultSet is closed - postgresql

I am currently learning using Clojure and connection with postgresql and I am stuck. In my code, I can successfully query using SELECT using java.jdbc dependency but got an exception when I UPDATE or INSERT
I am using these dependencies
[org.clojure/java.jdbc "0.7.8"]
[postgresql "9.3-1102.jdbc41"]
This is my working code for SELECT-ing from a table called public."user"
(ns knp-api.model.user
(:require [clojure.java.jdbc :as sql]))
(def db "jdbc:postgresql://ampersanda#localhost:5432/idjoesoft_klinik")
(defn get-count [q]
"Get count key from query
It takes jdbc.query as parameter"
(:count (first (into [] q))))
(defn is-user-email-available? [e]
"Returns boolean when email is available.
Take one parameter, it's email"
(let [q "SELECT COUNT(*) FROM public.\"user\" t WHERE user_email = ?"]
(sql/query db [q e] {:result-set-fn #(= 1 (get-count %))})))
and this is not my code which makes an exception appear
(defn set-user-timestamp-and-token [email token timestamp]
"update user current token and last login time inside database.
Takes email, token, and current timestamp as parameter"
(sql/update! db
"public.\"user\""
{:user_last_login (str "to_timestamp(" timestamp ")")
:user_token token}
["user_email = ?" email]))
and this is the exception
UPDATE
I also try using REPL to create table and I also get the same results.
knp-api.handler=> (require '[clojure.java.jdbc :as sql])
nil
knp-api.handler=> (sql/db-do-commands "jdbc:postgresql://ampersanda#localhost:5432/idjoesoft_klinik" (sql/create-table-ddl :testing [[:data :text]]))
PSQLException This ResultSet is closed. org.postgresql.jdbc2.AbstractJdbc2ResultSet.checkClosed (AbstractJdbc2ResultSet.java:2852)

I suspect the update is happening fine, and then it's trying to return the rows that changed, and it's trying to do so as a lazy sequence. the thing that tries to print/process that lazy sequence of results may be doing so after the connection is closed.
try wrapping the select statement in a call to doall to ensure that it's read immediately and not allowed to be a lazy database.

Having run into the same issue today, the root cause is the postgresql java driver.
postgresql "9.3-1102.jdbc41" is five years old, after upgrading to 42.2.6 the issue went away.

I remember having this problem, but it's many years ago and I can't remember the solution. However, wrapping raw JDBC in Clojure is not a good idea. There are a number of excellent Clojure libraries which make working with databases much easier. I'd particularly recomment SQL Korma and Hug SQL.

Having spent a while trying to get this solved I can confirm in my case updating the postgresql java driver solved this issue, if anybody is having the same issue try to use the newest driver from clojars/maven, Clojars even has a message telling you that you should use the version from maven central.

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.

operator does not exist: # timestamp without time zone

In a parameterized query issued from c# code to PostgreSQL 10.14 via dotConnect 7.7.832 .NET connector, I select either a parameter value or the local timestamp, if the parameter is NULL:
using (var cmd = new PgSqlCommand("select COALESCE(#eventTime, LOCALTIMESTAMP)", connection)
When executed, this statement throws the error in subject. If I comment out the corresponding parameter
cmd.Parameters.Add("#eventTime", PgSqlType.TimeStamp).Value = DateTime.Now;
and hardcode
using (var cmd = new PgSqlCommand("select COALESCE('11/6/2020 2:36:58 PM', LOCALTIMESTAMP)", connection)
or if I cast the parameter
using (var cmd = new PgSqlCommand("select COALESCE(cast(#eventTime as timestamp without time zone), LOCALTIMESTAMP)", connection)
then it works. Can anyone explain what # operator in the error is referring to and why the error?
In the case that doesn't work, your .Net connection library seems to be passing an SQL command containing a literal # to the database, rather than substituting it. The database assumes you are trying to use # as a user defined operator, as it doesn't know what else it could possibly be. But no such operator has been defined.
Why is it doing that? I have no idea. That is a question about your .Net connection library, not about PostgreSQL itself, so you might want to add tag.
The error message you get from the database should include the text of the query it received (as opposed to the text you think it was sent) and it is often useful to see that in situations like this. If that text is not present in the client's error message (some connection libraries do not faithfully pass this info along) you should be able to pull it directly from the PostgreSQL server's log file.

Issue With Using Cursor After Initial Pipe Is Closed – MongoDB

I'm attempting to use a MongoDB Cursor in Haskell. I use a pipe (connection to my MongoDB database) to obtain the value of this cursor, then close the pipe and give the value of the cursor. After opening another pipe, I have errors when accessing the cursor, although the Haskell MongoDB docs state that:
a cursor is not closed when the pipe is closed, so you can open another pipe to the same server and continue using the cursor.
at http://hackage.haskell.org/package/mongoDB-2.5.0.0/docs/Database-MongoDB-Query.html#t:Cursor
I have tried using cursors when the pipe does not close between the initialisation and usage of them: this does work, however this is not the solution I want to integrate into my web-app (I will want to use pooling in the future.) I am also left wondering why closing the pipe causes the cursor to no longer work.
I have looked through the MongoDB source code, and have only found one area where closeCursor is used (https://github.com/mongodb-haskell/mongodb/blob/33f2aca7b736c34d915916bc978bc5435baae533/Database/MongoDB/Query.hs#L1214). I am not sure if the error I'm having is a problem with a mismatch between the documentation of the client and my actual MongoDB Community Server (v4.0.10).
I have created a reproducible example of an IO Action causing this error.
firstFiveOver20 :: IO ()
firstFiveOver20 = (DB.withDB . find $ (select [] "test"))
>>= (() <$) . DB.withDB . Database.MongoDB.nextN 5
find, select, and nextN are from the MongoDB package.
The function withDB is defined as:
withDB :: Action IO a -> IO a
withDB action = (connect $ host "127.0.0.1") >>= (\pipe -> access pipe master databaseName action <* close pipe)
The expected result is for nothing to be logged (as I don't expect any errors). However, the error ConnectionFailure Handle has been closed: does not exist is given. From my perception, this seems to mean that the MongoDB Database is reporting the cursor as not existing. This either means that the Haskell client has closed it or it was closed by the MongoDB Database when the connection was dropped. These both contradict the statement in the docs (http://hackage.haskell.org/package/mongoDB-2.5.0.0/docs/Database-MongoDB-Query.html#t:Cursor).

GreenPlum Substring - Getting part of a long text

say I have a long URL
xyz = 'www.google.com/xyz?para1=value1&para2=value2&para3=value3....'
I am trying to get the 'para1' out of this long URL
So, I have
select TRIM(Leading '?' from Substring(xyz from '%#"?%=#"%' for '#'))
The answer I get for this particular statement is
para1=value1&para2=value2&para3=
How can I get just 'para1' using the select statement above (or any other similar method?)
I am using Greenplum (as mentioned in the topic heading)
Since you apparently have the regexp_ functions (I didn't think Greenplum supported them) use:
select (regexp_matches(
'www.google.com/xyz?para1=value1&para2=value2&para3=value3....',
'\?([^&]+)='
))[1];

Rails - Heroku Postgresql SQL Error - Works on Local SQLite - Error "ActiveRecord:Invalid Relation"

Hi here is my ActiveRelation query that works fine on local development environment (SQLite)
#table2_items = #table1var.table2_items.find(:all, conditions: ["status1 is ? AND status2 is ? AND start_datetime > ?", true, nil, Time.now.to_datetime], order: [:field_id, :created_at])
I think it's just a syntax error... Can anyone help? Thanks
Your SQL ends up with this in it:
status1 is 't'
and that's invalid: is is only used with is null, is distinct from, and similar constructs.
You should upgrade to a more modern syntax and leave most of the work to ActiveRecord:
#table2_items = #table1var.table2_items
.where(:status1 => true, :status2 => nil)
.where('start_datetime > ?', Time.now)
.order(:field_id, :created_at)
That leaves most of the "how do I compare things?" logic up ActiveRecord and is a bit easier to read as the placeholders and their values aren't separated from each other.
Once you have this problem sorted out, you really should install PostgreSQL in your development environment so that you're developing and deploying on the same stack. There are all sorts of differences between databases that no ORM can protect you from.