This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
I'm trying to walk/update an xml/html-like tree structure, which looks like this:
{:tag :button,
:attrs {},
:content
["Text content" {:tag :span, :attrs {}, :content ["Text content"]}]}
I tried defining my own seq for it using tree-seq
, like this:
(defn tmpl-seq [tp] (tree-seq map? :content tp))
But when I walk it using the clojure walker functions, I get unexpected results:
(def tpseq (tmpl-seq @root-tp))
(pprint (prewalk (fn [x] x) tpseq)) ;; expecting to get the same tree structure back unchanged
=> ({:tag :button,
:attrs {},
:content
["Text content" {:tag :span, :attrs {}, :content ["Text content"]}]}
"Text content"
{:tag :span, :attrs {}, :content ["Text content"]}
"Text content")
the prewalk does return the same structure:
(= (prewalk (fn [x] x) (tmpl-seq a)) (tmpl-seq a)) ; true
but the tree-seq creates a seq of the various tree elements - try the tmpl-seq call on its own - I think that might be the unexpected piece
Oh right, I guess that's not how I expected/wanted the seq to work. I think I want it to return nodes only
I'm not sure how to solve it though. Basically I don't really care what the seq looks like, I just want to be able to do a nested update in the tree, and get back an updated tree root
tree-seq flattens a tree to a flat sequence. Sounds like that's not what you want? I'd try a straight prewalk or postwalk.
Huh, yeah, that magically works. I wasn't sure how postwalk would be able to tell how to walk through my special structure, but I guess it just navigates through everything so it doesn't really need to know what key the children are located at
Prewalk and postwalk have native support for associative collections and sequences. If you just have nested maps, it knows what to do :)
I think this line, specifically (into (empty form) ,,,) is what makes maps come out :) https://github.com/clojure/clojure/blob/master/src/clj/clojure/walk.clj#L50
I am trying to run this file tool/db/core_test.clj
with lein test
, and for some reason the count test fails
It seems like create-user
is not running, but I checked that it is because when I run it by removing {:rollback-only true}]
then I was able to see in my DB that a row was created
Is this is an issue of the create-user
not having fully finished commiting the row to the db by the time the get-users
runs? I'm using postgres though so I should be able to read the rows that were just created in the middle of the transaction.
Not sure why it's not working.
(ns tool
.db.core-test
(:require
[tool
.db.core :refer [*db*] :as db]
[java-time.pre-java8]
[luminus-migrations.core :as migrations]
[clojure.test :refer :all]
[next.jdbc :as jdbc]
[tool
.config :refer [env]]
[mount.core :as mount]))
(use-fixtures
:once
(fn [f]
(mount/start
#'tool
.config/env
#'tool
.db.core/*db*)
(migrations/migrate ["migrate"] (select-keys env [:database-url]))
(f)))
(deftest test-users
(jdbc/with-transaction [t-conn *db* {:rollback-only true}]
;; (jdbc/with-transaction [t-conn *db*]
(println (select-keys env [:database-url]))
(is (= 1 (db/create-user!
t-conn
{
:first_name "Sam"
:last_name "Smith"
:email ""
:role "user"
:password "pass"}
{:connection t-conn}
)))
(is (= 1
(count (db/get-users t-conn )))) ;; this test fails
))
is it possible that db/create-user!
does something that manipulates the connection in such a way that the transaction gets closed (and given the rollback-only option, rolls back the trx)? Have you tried replacing the create-user with a more primitive jdbc/execute call to help differentiate?
@U013JFLRFS8
This is my resources/sql/queires.sql
file. It's just a simple insert.
-- :name create-user! :! :n
-- :doc creates a new user record
INSERT INTO users
(first_name, last_name, email, password, role, created_at, updated_at, last_login)
VALUES (:first_name, :last_name, :email, :password, :role, now(), now(), now())
-- :name get-users :? :*
-- :doc retrieves all user records
SELECT * FROM users
-- :name get-user :? :1
-- :doc retrieves a user record given the id
SELECT * FROM users
WHERE id = :id
This is my first time using clojure so do you have some code or more detail on how I would use a "jdbc/execute" call?Ah ok something like this I assume
(jdbc/with-transaction [t-conn *db* {:rollback-only true}]
(jdbc/execute! t-conn ["
INSERT INTO users
(first_name, last_name, email, password, role, created_at, updated_at, last_login)
VALUES ('first_name', 'last_name', 'email', 'password', 'role', now(), now(), now())
"])
(is (= 1
(count (db/get-users t-conn ))))
I ran this, but same result where it sees 0 rowsin that case, I'd speculate that it might be an auto-commit thing, but I'm not too familiar with how auto-commit and rollback only play together in the context of a transaction - I'll see if I can spin up a repro, but it'll probably take me a little while (or someone smarter than me will come along with the right answer)
what is *db*
? I'm unable to re-create the situation you describe. Admittedly, I'm not using a test fixture or mount, but I'm always getting the row back from within the trx, and it gets rolled back and isn't there afterwards
Pardon a dummy jumping in but I googled a bit and it seems that is what :rollback-only
does, ie, execute the command and then rollback immediately, even on success. This is next.jdbc, but it sounds relevant. Look for ":rollback-only". https://cljdoc.org/d/seancorfield/next.jdbc/1.2.659/doc/getting-started/transactions hth
@U013JFLRFS8 here's my repo - should be able to reproduce it from this if you have a postgres db running locallly https://github.com/himat/del
@U0PUGPSFR I saw that, but it should rollback after the entire transaction right? Not in the middle. I have both create-user and get-users within the one overall transaction The line after that in the docs also agrees: "The latter can be particularly useful in tests, to run a series of SQL operations during a test and then roll them all back at the end."
i had a look at the code, apparently you need to do (db/get-users t-conn {})
so that it uses properly the connection pool. I think it might be conman, because I don't think i encountered this issue with hugsql. It's probably due to their automatic detection of the db component, so I guess (db/get-users t-conn)
was converted to (db/get-users *db* t-conn)
which missed the current transaction's writes. Btw you don't need that 3rd arg in db/create-user!