sql

All things SQL and JDBC...
teodorlu 2020-02-10T11:27:47.086200Z

Hello! I'm using jdbc.next to work with a PostgreSQL table with a column containing JSON. When I select from the table, I get data like #object[org.postgresql.util.PGobject 0xb1fe4db ... . Any recommendations for working with JSON using jdbc.next? Do people just "convert to maps" when running the select query?

teodorlu 2020-02-10T11:32:20.086700Z

I'm aware that I can use str with a normal JSON parser, but I'm suspecting that ad-hoc json/string conversion all around the codebase might not be desirable:

(with-open [conn (jdbc/get-connection db-datasource)]
  (-> (jdbc.sql/query conn ["SELECT * from my_table LIMIT 1"])
      first
      :my_table/data
      str
      json/read-str))

Andrew 2020-02-10T11:59:59.086900Z

I haven’t tried this, but perhaps it’ll work / be useful. I’d extend ReadableColumn to PGobject as described here https://github.com/seancorfield/next-jdbc/blob/master/doc/result-set-builders.md#readablecolumn When the type of the object as reported by .`getType` is "jsonb" or "json" call json/read-str on the result of .getValue, otherwise return the result fo .getValue

👍 1
teodorlu 2020-02-10T13:21:06.087300Z

Found an article that seems to cover insertion as well, but it's for clojure.jdbc and not jdbc.next: https://web.archive.org/web/20161024231548/http://hiim.tv/clojure/2014/05/15/clojure-postgres-json/

Andrew 2020-02-10T13:34:02.087800Z

This says how to do the reverse

teodorlu 2020-02-10T13:53:36.088Z

That's right, the article documents how to do it both ways. Both articles rely on switching on the object type before converting to PGObjects. Thanks.

jwoods 2020-02-10T13:58:57.089100Z

Does anyone have an example of importing data from csv into postgres or any other db?

teodorlu 2020-02-10T14:02:16.089200Z

At least psql can output to CSV, but I haven't found a way to input. From man psql:

-F separator
       --field-separator=separator
           Use separator as the field separator for unaligned output. This is equivalent to \pset
           fieldsep or \f.

dharrigan 2020-02-10T14:59:08.089600Z

In psql...

dharrigan 2020-02-10T15:00:16.090300Z

\copy my-funky-table from '/home/foo/this-is-my.csv' with delimiter as ',' csv header

dharrigan 2020-02-10T15:00:29.090600Z

you can remove the header if you csv doesn't include a header.

jwoods 2020-02-10T16:15:52.091400Z

Thanks

jwoods 2020-02-10T16:17:03.091500Z

Instead of passing a file can I do it with csv data in memory?

fabrao 2020-02-10T22:47:12.092800Z

hello all, about jdbc.next what is the way to use jdbc driver that is not in list of available

fabrao 2020-02-10T22:47:13.093Z

?

2020-02-10T22:50:02.093700Z

you provide jdbc drivers via the classpath, which should be getting it via project.clj or deps.edn depending on how you manage your project

fabrao 2020-02-10T22:57:42.093900Z

I got

Unhandled clojure.lang.ExceptionInfo
   Unknown dbtype:

2020-02-10T22:59:06.094900Z

OK - that's either an issue with the classpath where the db driver wasn't loaded, or you misconfigured the db spec itself - I can't help with the latter

2020-02-10T22:59:14.095200Z

can you show more of the message / context?

fabrao 2020-02-10T23:00:34.095500Z

Unhandled clojure.lang.ExceptionInfo
   Unknown dbtype:
   {:class "dbmaker.jdbc.ws.client.Driver",
    :dbname "DEFAULT",
    :user "SYSADMIN",
    :password "1234",
    :host "127.0.0.1",
    :port 1054}
            connection.clj:  201  next.jdbc.connection/spec->url+etc
            connection.clj:  141  next.jdbc.connection/spec->url+etc
            connection.clj:  267  next.jdbc.connection/eval959/fn
             protocols.clj:   14  next.jdbc.protocols/eval723/fn/G
            connection.clj:  283  next.jdbc.connection/eval979/fn
             protocols.clj:   24  next.jdbc.protocols/eval753/fn/G
                  jdbc.clj:  134  next.jdbc/get-connection
                  jdbc.clj:  117  next.jdbc/get-connection
                      REPL:   12  app.core/eval13801
                      REPL:   12  app.core/eval13801
             Compiler.java: 7177  clojure.lang.Compiler/eval
             Compiler.java: 7132  clojure.lang.Compiler/eval
                  core.clj: 3214  clojure.core/eval
                  core.clj: 3210  clojure.core/eval
                  main.clj:  437  clojure.main/repl/read-eval-print/fn
                  main.clj:  437  clojure.main/repl/read-eval-print
                  main.clj:  458  clojure.main/repl/fn
                  main.clj:  458  clojure.main/repl
                  main.clj:  368  clojure.main/repl
               RestFn.java:  137  clojure.lang.RestFn/applyTo
                  core.clj:  665  clojure.core/apply
                  core.clj:  660  clojure.core/apply
                regrow.clj:   18  refactor-nrepl.ns.slam.hound.regrow/wrap-clojure-repl/fn
               RestFn.java: 1523  clojure.lang.RestFn/invoke
    interruptible_eval.clj:   79  nrepl.middleware.interruptible-eval/evaluate
    interruptible_eval.clj:   55  nrepl.middleware.interruptible-eval/evaluate
    interruptible_eval.clj:  142  nrepl.middleware.interruptible-eval/interruptible-eval/fn/fn
                  AFn.java:   22  clojure.lang.AFn/run
               session.clj:  171  nrepl.middleware.session/session-exec/main-loop/fn
               session.clj:  170  nrepl.middleware.session/session-exec/main-loop
                  AFn.java:   22  clojure.lang.AFn/run
               Thread.java:  748  java.lang.Thread/run

fabrao 2020-02-10T23:01:16.096200Z

for

(jdbc/get-connection
 {:class "dbmaker.jdbc.ws.client.Driver"
 :dbname "DEFAULT"
 :user "SYSADMIN"
 :password "1234"
 :host "127.0.0.1"
 :port 1054})

seancorfield 2020-02-10T23:01:35.097Z

You must provide :dbtype.

seancorfield 2020-02-10T23:01:55.097200Z

Per the docs:

If you want to use a database that is not in this list, you can specify a new :dbtype along with the class name of the JDBC driver in :classname. You will also need to specify :port. For example:

{:dbtype "acme" :classname "com.acme.JdbcDriver" ...}

seancorfield 2020-02-10T23:03:33.097700Z

Add :dbtype "dbmaker" to your hash map and it should work.

seancorfield 2020-02-10T23:04:31.098900Z

next.jdbc caches certain aspects of driver handling based on the db type so you have to provide a unique value for each different type of database (driver) you want to use.

fabrao 2020-02-10T23:04:56.099200Z

sorry about that. I only read the get-datasource help

seancorfield 2020-02-10T23:05:58.099800Z

FWIW, Getting Started links to that documentation in the https://cljdoc.org/d/seancorfield/next.jdbc/1.0.13/doc/getting-started#the-db-spec-hash-map section.

fabrao 2020-02-10T23:06:54.100600Z

any other advice? :dbtype "dbmaker" didn´t work

seancorfield 2020-02-10T23:07:27.100900Z

Oh :class is wrong. Should be :classname

seancorfield 2020-02-10T23:07:38.101200Z

get-datasource says

In the first format, these keys are required:

:dbtype -- a string indicating the type of the database

seancorfield 2020-02-10T23:07:47.101400Z

and

:classname -- if you need to override the default for the :dbtype (or you want to use a database that next.jdbc does not know about!)

seancorfield 2020-02-10T23:08:14.101700Z

Let me know if I can make that clearer.

seancorfield 2020-02-10T23:08:49.102500Z

I guess I could link from the get-datasource docstring to the #dbtypes section of the next.jdbc.connection namespace...

fabrao 2020-02-10T23:09:52.103500Z

oh, you right, I´m dumb*ss , that was the problem, :classname

fabrao 2020-02-10T23:10:49.104Z

the docs of driver says that we have to include other parameter to it

fabrao 2020-02-10T23:11:00.104300Z

Class.forName("dbmaker.jdbc.ws.client.Driver");
Connection conn =
DriverManager.getConnection("jdbc:dbmaker:<type3://127.0.0.1:8083/JDBCTES>
T", "SYSADM", abc");

fabrao 2020-02-10T23:11:25.104800Z

what is the way to include :type3 ?

fabrao 2020-02-10T23:12:13.105500Z

or the best way is to provide the url directly?

seancorfield 2020-02-10T23:12:20.105700Z

:dbtype "dbmaker:type3" should work.

seancorfield 2020-02-10T23:12:58.106300Z

That's what the DB type is: the driver-specific segment of the JDBC URL.

fabrao 2020-02-10T23:13:40.106800Z

Best regards Sean, thank you, now is working

1
fabrao 2020-02-10T23:14:06.107300Z

have you heard about this database?

seancorfield 2020-02-10T23:15:13.107600Z

Nope, never heard of it.

seancorfield 2020-02-10T23:15:29.108Z

BTW, going back to the docstring for that dbtypes Var:

The value of :dbtype should be the string that the driver is associated with in the JDBC URL, i.e., the value that comes between the jdbc: prefix and the ://&lt;host&gt;... part. In the above example, the JDBC URL that would be generated would be jdbc:acme://&lt;host&gt;:&lt;port&gt;/&lt;dbname&gt;.

seancorfield 2020-02-10T23:16:16.108800Z

(I wanted to double-check I was describing the relationship between :dbtype and the JDBC URL somewhere -- and I would have added that if it wasn't already present!)

fabrao 2020-02-10T23:19:22.109800Z

my customer is using COBOL in JVM, 🙂

fabrao 2020-02-10T23:19:44.110100Z

and this database

fabrao 2020-02-10T23:20:17.110400Z

the old new technology

fabrao 2020-02-10T23:21:57.111100Z

the Cobol code is transpiled to Java and is compiled

dpsutton 2020-02-10T23:26:09.111800Z

You are taking to the absolutely perfect person then :)