sql

All things SQL and JDBC...
practicalli-john 2020-08-26T13:35:44.088600Z

I am assuming that using Migratus or Ragtime is a more common approach to creating multiple tables in a database, rather than using a 'builder' style function (i.e. a builder function creates a table from a schema passed as an argument). I only have a few tables, so was just planning to create a separate function to create each table to start with, until I adopt Migratus (probably). Does that make sense?

synthomat 2020-08-26T14:12:01.090200Z

actually both projects felt quite lightweight to me so far; maybe there’s less effort to adopt to that than you might think

dpsutton 2020-08-26T14:15:49.090600Z

we use migratus and it is quite pleasant to work with

lukasz 2020-08-26T14:31:44.091700Z

+1 on ragtime (migratus looks v similar). Managing table structure without proper migrations (event if they are lightweight) very quickly becomes a pain - I'm actually migrating πŸ˜‰ one project from this approach

dpsutton 2020-08-26T14:36:57.092700Z

migratus uses timestamps for migration names rather than integers so it is far easier to merge branches which each have migrations. i've never used ragtime so can't speak to it but migratus has been rock solid for us

lukasz 2020-08-26T14:54:51.093500Z

I think in ragtime the migration IDs just have to be ordered - we have a small shell script which generates up/down files and uses unix timestamp as the ID (just like Rails does)

kulminaator 2020-08-26T17:03:01.093600Z

recently moved stuff to flyway as well. it seems to work for the basic needs.

Jan Winkler 2020-08-26T17:58:10.104200Z

hi. I'm playing with jdbc-next. I can qualify a column with a namespace using as, but I can't read it in the reduction:

(into #{}
      (map (juxt keys
                 (comp namespace first keys)
                 (comp name first keys)
                 :qualified/column))
      (jdbc/plan ds ["select 'foo' as \"qualified/column\""]))
=> #{[(:qualified/column) "qualified" "column" nil]}
I suspect sneaking in the namespace the way I did is silly, and probably works only by accident. am I right or should this (somehow) work?

seancorfield 2020-08-26T18:01:13.106100Z

@jan.wnklr SQL doesn't know about namespace-qualification so you've created a column label that is "qualified/column" -- if you use (get row "qualified/column") it would probably work. But, basically, don't do that πŸ™‚

Jan Winkler 2020-08-26T18:03:41.107100Z

I've tried that too, still getting nil. but I'd feel filthy if it worked. πŸ™‚

seancorfield 2020-08-26T18:04:27.108Z

Also, plan is working with the raw result set, not a hash map, so it is expected that you use simple (unqualified) keywords for column access.

seancorfield 2020-08-26T18:04:55.108600Z

Although you're using keys which realizes the result set as a hash map so you're getting a weird combination of data.

Jan Winkler 2020-08-26T18:06:54.110100Z

interestingly, using qualified kws for columns that come from a table works

seancorfield 2020-08-26T18:07:44.110700Z

user=> (into #{} (map #(get % "qualified/column")) (jdbc/plan ds ["select 'foo' as `qualified/column`"]))
#{"foo"}

seancorfield 2020-08-26T18:07:59.111100Z

(that's with MySQL hence the backtick quoting)

seancorfield 2020-08-26T18:08:43.111800Z

If you use a qualified keyword in lookup access when you reduce-over-plan, the code only uses the name portion.

seancorfield 2020-08-26T18:09:20.112Z

user=> (into #{} (map :ignore/qualified/column) (jdbc/plan ds ["select 'foo' as `qualified/column`"]))
#{"foo"}

Jan Winkler 2020-08-26T18:10:02.112600Z

oh, it works now, I must have brainfarted somewhere

seancorfield 2020-08-26T18:10:30.113100Z

Since you are using keys, and realizing the result set, you are losing all the performance benefit of plan

seancorfield 2020-08-26T18:10:56.113600Z

(although you can still use it to stream very large result sets, even if you realize each row)

Jan Winkler 2020-08-26T18:12:57.114900Z

my intention, originally, was to convert a string column value to keyword using (map #(update % :that/column keyword)). would that also result in row realization?

seancorfield 2020-08-26T18:13:29.115200Z

Yes.

Jan Winkler 2020-08-26T18:14:32.116Z

how wouldn't it, right? thanks, I needed a little kick. πŸ™‚

seancorfield 2020-08-26T18:26:26.117600Z

Compare to this (where there is a table name to do the qualification):

user=> (into #{} (map #(update % :status/name keyword)) (jdbc/plan ds ["select id,name from status"]))
#{#:status{:id 3, :name :rejected} #:status{:id 2, :name :new} #:status{:id 1, :name :approved}}
user=> (into #{} (map (comp keyword :name)) (jdbc/plan ds ["select id,name from status"]))
#{:rejected :new :approved}
user=> 
In the second case, we are not realizing a row -- we're just selecting the name column and we can use an unqualified keyword; in the first case we are realizing the row (because update needs a hash map) so we must use a qualified keyword.

seancorfield 2020-08-26T18:27:37.118300Z

But in that second case, we could use a qualified keyword -- the qualifier is simply ignored:

user=> (into #{} (map (comp keyword :status/name)) (jdbc/plan ds ["select id,name from status"]))
#{:rejected :new :approved}
user=> (into #{} (map (comp keyword :this-part-is-ignored/name)) (jdbc/plan ds ["select id,name from status"]))
#{:rejected :new :approved}

seancorfield 2020-08-26T18:27:50.118700Z

I hope that clarifies the behavior @jan.wnklr?

Jan Winkler 2020-08-26T18:35:01.119800Z

yup, I get it now. this was very helpful and incredibly quick response. thank you.