Fork me on GitHub
#sql
<
2018-05-04
>
xlevus09:05:48

I've written a thing to generate CREATE INDEX statements using honeysql. The final SQL list destined for jdbc looks sane to me...

["CREATE UNIQUE INDEX IF NOT EXISTS dfidx_docufant_email__account__uniq ON docufant ((_data -> ?)) WHERE _type = ?"
 "email"
 "account"]
Two ?, two values after the query in the list. But I get the error
org.postgresql.util.PSQLException: ERROR: there is no parameter $2
                                     Position: 113
    java.sql.BatchUpdateException: Batch entry 0 CREATE UNIQUE INDEX IF NOT EXISTS dfidx_docufant_email__account__uniq ON docufant ((_data -> 'email')) WHERE _type = 'account' was aborted: ERROR: there is no parameter $2
                                     Position: 113  Call getNextException to see other errors in the batch.
when executing it. If I run the query directly unparametrized it's fine.

xlevus09:05:38

stumped. (and coincidentally, I could have sworn this worked two weeks ago.)

seancorfield15:05:05

@xlevus How are you actually executing that generated SQL?

seancorfield15:05:01

(and what does that weird-looking syntax ((_data -> 'email')) actually mean??)

tanzoniteblack15:05:51

@seancorfield it's a postgres operator for getting an item out of a json object/array https://www.postgresql.org/docs/current/static/functions-json.html

tanzoniteblack15:05:59

@myguidingstar 🙂 I'm not the one with an issue. And I don't think he's trying to use the ? operator. He's using the -> operator: (_data -> ?)

myguidingstar15:05:59

sorry I misread your question

tanzoniteblack15:05:13

and the ? is supposed to be a parameter insertion

seancorfield15:05:41

I suspect the problem here is in how @xlevus actually executes the SQL. It's using BatchUpdateException which suggests he's using execute! but I don't think all drivers allow DDL to be executed that way. I think db-do-commands is needed here.

seancorfield15:05:44

Ah, but db-do-commands doesn't accept SQL parameters, just SQL statements (for DDL).

xlevus15:05:03

I'm using the same syntax and functions to do queries too.

xlevus15:05:17

and the index object in question would look like {:type :account :path [:email] :unique true}

seancorfield15:05:49

@xlevus Can you share enough of the stacktrace so I can tell exactly what in java.jdbc is throwing that exception? Also, which version of java.jdbc are you using?

xlevus15:05:51

just pumping it into a repl now

tanzoniteblack15:05:55

(jdbc/with-db-transaction [conn (config/db)]
                         (jdbc/execute! conn ["CREATE TABLE test_table (json_column jsonb, data_type text);"])
                         (jdbc/execute! conn ["CREATE UNIQUE INDEX IF NOT EXISTS test_uniq ON test_table((json_column -> 'field')) WHERE (data_type = 'dog');"]))
so for me this works

tanzoniteblack15:05:59

but with the param:

tanzoniteblack15:05:14

the code that generated that exception:

(jdbc/with-db-transaction [conn (config/db)]
                         (jdbc/execute! conn ["CREATE TABLE test_table (json_column jsonb, data_type text);"])
                         (jdbc/execute! conn ["CREATE UNIQUE INDEX IF NOT EXISTS test_uniq ON test_table((json_column -> 'field')) WHERE (data_type = ?);" "dog"]))

tanzoniteblack15:05:24

the second message came from a slightly different query, hence the complaint about $2

(jdbc/with-db-transaction [conn (config/db)]
                         (jdbc/execute! conn ["CREATE TABLE test_table (json_column jsonb, data_type text);"])
                         (jdbc/execute! conn ["CREATE UNIQUE INDEX IF NOT EXISTS test_uniq ON test_table((json_column -> ?)) WHERE (data_type = ?);" "dog" "cat"]))

seancorfield16:05:05

I wonder if there's something about the Hikari proxy causing trouble?

xlevus16:05:26

hm, no, I get the same thing using just a db-spec

seancorfield16:05:42

OK, good to eliminate that as the source of a problem.

xlevus16:05:13

i wonder if it's postgres

seancorfield16:05:06

And which pg driver are you using?

xlevus16:05:38

https://github.com/xlevus/docufant-clj/blob/master/project.clj

[org.clojure/clojure "1.9.0"]
                 [org.clojure/java.jdbc "0.7.3"]
[org.postgresql/postgresql "42.1.4"]

tanzoniteblack16:05:01

removing another source of confusion, it's not related to the json stuff:

(jdbc/with-db-transaction [conn (config/db)]
                         (jdbc/execute! conn ["CREATE TABLE test_table (json_column text, data_type text);"])
                         (jdbc/execute! conn ["CREATE UNIQUE INDEX IF NOT EXISTS test_uniq ON test_table(json_column) where data_type = ?;" "data_type"]))
has the same error

tanzoniteblack16:05:27

and I'm testing this with [org.postgresql/postgresql "42.2.0"]

xlevus16:05:16

maybe it's postgres.

docufant_test> PREPARE dfidx(a, b) AS
                 CREATE UNIQUE INDEX IF NOT EXISTS dfidx_docufant_email__account__uniq ON docufant ((_data -> $1)) WHERE _type = $2;

syntax error at or near "CREATE"
LINE 2:   CREATE UNIQUE INDEX IF NOT EXISTS dfidx_docufant_email__ac...
          ^

Time: 0.005s

seancorfield16:05:06

My gut instinct says you can't run DDL with parameters through a PreparedStatement but I don't know if that's true.

tanzoniteblack16:05:31

@seancorfield that's the same thing I'm thinking. Can't find anything either way on the topic so far

seancorfield16:05:05

I think that's the origin of why db-do-commands doesn't use a prepared statement -- it just creates a basic statement based on the SQL (only, no parameters).

xlevus16:05:09

looks like that might be the problem.

xlevus16:05:11

guess I'm going to have to manually escape ... stuff.

xlevus16:05:30

Cheers for the help guys

xlevus16:05:13

oh lord D: manual escaping.