React native with squint is such a breeze π π
hey i'm currently fiddling around with bun and i saw that they have a build in sqlite driver. Is there something like honysql for squnit?
HoneySQL supports cljs - if it doesn't work with Squint, lmk
I donβt think honeysql works today with squint since squint doesnβt have multimethods (yet). Maybe there is a JS library for it? What would be cool is if we could compile honeysql with squint so we can expose it to the entire JS world like we did with codemirror clojure-mode
I don't think HoneySQL uses multimethods...?
(v1 did but v2 does not)
Oh then I misremembered. I can give a shot at compiling honeysql with squint tomorrow to see if it works
that would be awesome especially for bun cause it has sql drivers allready
for postgres and sqlite that would be a total win imho
I had a quick look. Currently squint trips over the use of #'h/sym->kw since squint doesn't have vars (CLJS also doesn't have vars, but it fakes them when using this notation).
The next thing squint fails over is the usage of :extend-via-metadata
The next thing that fails is Error: nth not supported on this type function(a,b,c,d,e). No clue what this is yet.
Note that squint (currently) also doesn't have symbols. so symbol? won't work either
regarding the symbols wouldn't it work to use javascript native symbols?
Ah, the nth error is about using require without a vector like (:require clojure.string). Squint doesn't support that yet.
JavaScript symbols and Clojure symbols are very different things
ok got it compiling now:
$ npx squint compile
[squint] Compiling CLJS file: /private/tmp/honeysql/src/honey/sql/helpers.cljc
[squint] Wrote file: /private/tmp/honeysql/js/honey/sql/helpers.mjs
[squint] Compiling CLJS file: /private/tmp/honeysql/src/honey/sql/pg_ops.cljc
[squint] Wrote file: /private/tmp/honeysql/js/honey/sql/pg_ops.mjs
[squint] Compiling CLJS file: /private/tmp/honeysql/src/honey/sql/protocols.cljc
[squint] Wrote file: /private/tmp/honeysql/js/honey/sql/protocols.mjs
[squint] Compiling CLJS file: /private/tmp/honeysql/src/honey/sql/util.cljc
[squint] Wrote file: /private/tmp/honeysql/js/honey/sql/util.mjs
[squint] Compiling CLJS file: /private/tmp/honeysql/src/honey/sql.cljc
[squint] Wrote file: /private/tmp/honeysql/js/honey/sql.mjs
but haven't tried to use it yet, I think it'll fail due to symbol? etcit currently trips over a conflict between an alias and a function name:
import * as str from 'squint-cljs/src/squint/string.js';
import { str, join, split_by_separator, into_STAR_ } from './sql/util.mjs';
I guess I can just not use the more efficient str for now
now tripping over some invalid syntax produced here:
})()) : ((("else") ? (throw squint_core.ex_info("bigquery * only supports except and replace", ({ "clause": k36, "arg": arg37 }))) : (null))))));perhaps produced by compiling cond or so. interesting
ok, this is valid:
var x = "else" ? 1 : 2but apparently this isn't:
var x = "else" ? (throw 1) : 2I'll have to give up for now, but I think with some effort it can be made to work
I'll push my WIP to some repo
yeah the issue with throw is that when the expression is in value position, cond can produce code to be invalid. apparently you can't use throw anywhere in values in JS.
https://squint-cljs.github.io/squint/?src=KGxldCBbdiAoY29uZAogICAgICAgICAgKHRydWU%2FICg9IDEgMSkpCiAgICAgICAgICAodGhyb3cgKGV4LWluZm8gIk8gbm8iIHt9KSkpXSk%3D
I'll log that as an issue
ah clever, CLJS wraps the throw in an IIFE when in value position
found another bug in squint: https://github.com/squint-cljs/squint/issues/662 and when working around that found a bug in clj-kondo: https://github.com/clj-kondo/clj-kondo/issues/2535 I'm really the one winning here by finding new issues, thanks :)
now that I have stuff more or less running, I'm running into the Keyword stuff which doesn't exist in squint. I think I will run into the Symbol, PersistentVector, etc stuff as well which don't exist in squint
it's also running into this one:
(assert (= (set @base-clause-order)
(set @current-clause-order)
(set (keys @clause-format))))
since equality in squint is just JS equalitywow first non-erroring load in node (by commenting out stuff):
$ node
Welcome to Node.js v20.11.1.
Type ".help" for more information.
> var sql = await import("./js/honey/sql.mjs")> sql.format({"select": "*"})
Uncaught ReferenceError: binding is not defined
lol, yes, binding isn't defined in squint since binding totally doesn't work with ES6 modulesby hacking a little bit more, I got this running now:
> var sql = await import("./js/honey/sql.mjs")
undefined
> sql.format({"select": "*"})
[ 'SELECT *' ]
> sql.format({"select": "*", "from": "mytable"})
[ 'SELECT * FROM m, y, t, a, b, l, e' ]
So at least it's doing something π
btw honeysql does work with nbb on bun
π
you know whats really funny now if it works completly you can even use alasql π to query your json structures with honeysql. https://github.com/AlaSQL/alasql
yeah sure. should work with nbb today :)
yeah but it would be nice to have it on the frontend to π
even if my initial request was related to bun π
but now if i think further that would be super "technically" cool.
I've had an idea how I can have both keywords and strings in squint while maintaining backward compatibility in squint. If I would compile a keyword to x = new String("mykeyword"); x.keyword = true or so. Perhaps that could work in addition with keyword? etc. And comparing x to "mykeyword" as a string would still return true. But this would probably have an effect on performance and code size.
ok that looks interesting but sure i guess performance wise it would have impact
due to the fact that we have than an object
yeah probably not a good idea. It would also break this:
> var m = new Map();
undefined
m.set("foo", 1)
Map(1) { 'foo' => 1 }
> m.set(new String("foo"), 2)
Map(2) { 'foo' => 1, [String: 'foo'] => 2 }just a stupid idea that comes to my mind. keywords are basically global symbols right. Would it be possible to have them just in a global variable and reference them? i guess than the compilation would get more complicated. so like a global map
that's an optimization that can only be done globally if you are compiling a final artifact. The CLJS compiler does this in advanced mode. But in squint keywords are just strings
another way to do kind of the same is to use a WeakMap in JavaScript
but then you'd have to do a lookup in the map every time you create a keyword
exactly that was my point with the lookup it would be tedious π
and regarding having a simple tool at hand question is if its worth it
in JS you have a library callled squel.js - it's not as great as honeysql though as it doesn't really use data notation
yeah saw it too looked quite promising
btw i also had this scrappy fiddle around as i saw that i couldn't find an easy to use solution π
(defn prepare-select [{:keys [select from where order-by]}]
(str
"SELECT "
(map gen-columns select)
" FROM "
(name from)
(when where
" WHERE "
(map gen-conditions where))
(when order-by
" ORDER BY "
order-by)))
(defn gen-columns [cols]
(if (= cols :*)
"*"
(str/join ", " cols)))
(defn gen-condition [[op column value]]
(str
(name column)
" "
(name op)
" "
value))
(gen-condition [:= :test 123])
(defn gen-conditions [conds]
(str/join " AND "
(map gen-condition conds)))
(gen-conditions [[:= :test 123]
[:= :brokkli 1]])
(prepare-select {:select :*
:from :test
:where [[:= :test 123]
[:= :brokkli 323]]})
really poor mans version π