yuppiechef / datomic-schema Goto Github PK
View Code? Open in Web Editor NEWMakes it easier to see your Datomic schema without sacrificing any features.
License: MIT License
Makes it easier to see your Datomic schema without sacrificing any features.
License: MIT License
Hello there, I'm just getting my feet wet a bit with clojure/datomic and I like your defpart and defschema macros -- they seem a lot lispier to me than the standard boilerplate required for schema definition. Unfortunately I'm having a bit of an issue with the last expression in your example:
(d/transact (d/connect db-url) (s/build-schema d/tempid)
which yields the exception:
ExceptionInfo :transact/bad-data Invalid db/id: #db/id[:db.part/core -1000008]
clojure.core/ex-info (core.clj:4327)
The dependencies I'm using are as follows:
[org.clojure/clojure "1.5.1"]
[com.datomic/datomic-free "0.8.4020.26"]
[datomic-schema "1.0.1"]
I've enclosed the code that causes the condition and a longer stack trace below. Any insight you might have would be much appreciated.
(ns sandbox.core
(:use [clojure.core])
(:use [clojure.pprint])
(:use [datomic-schema.schema :only [defpart defschema fields part]])
(:use [clojure.repl :only [doc find-doc apropos]])
(:require [datomic.api :as d])
(:require [datomic-schema.schema :as s])
(:gen-class))
(defonce db-url "datomic:mem://sandbox")
(defpart core)
(defschema user (part core)
(fields
[username :string :indexed]
[pwd :string "Hashed password string"]
[email :string :indexed]
[status :enum [:pending :active :inactive :cancelled]]
[group :ref :many]))
(defschema group (part core)
(fields
[name :string]
[permission :string :many]))
(defn -main [& args]
(d/create-database db-url)
(d/transact (d/connect db-url) (s/build-parts d/tempid))
(d/transact (d/connect db-url) (s/build-schema d/tempid)))
java.util.concurrent.ExecutionException: clojure.lang.ExceptionInfo: :transact/bad-data Invalid db/id: #db/id[:db.part/core -1000008] {:db/error :transact/bad-data}
at datomic.promise$throw_executionexception_if_throwable.invoke (promise.clj:10)
datomic.promise$settable_future$reify__5429.deref (promise.clj:54)
clojure.core$deref.invoke (core.clj:2128)
clojure.core/fn (core_print.clj:383)
clojure.lang.MultiFn.invoke (MultiFn.java:231)
clojure.core$pr_on.invoke (core.clj:3322)
clojure.core$pr.invoke (core.clj:3334)
clojure.tools.nrepl.middleware.pr_values$pr_values$fn$reify__570$fn__572.invoke (pr_values.clj:23)
clojure.tools.nrepl.middleware.pr_values$pr_values$fn$reify__570.send (pr_values.clj:23)
clojure.tools.nrepl.middleware.interruptible_eval$evaluate$fn__591$fn__602.invoke (interruptible_eval.clj:67)
clojure.main$repl$read_eval_print__6588.invoke (main.clj:260)
clojure.main$repl$fn__6597.invoke (main.clj:277)
clojure.main$repl.doInvoke (main.clj:277)
clojure.lang.RestFn.invoke (RestFn.java:1096)
clojure.tools.nrepl.middleware.interruptible_eval$evaluate$fn__591.invoke (interruptible_eval.clj:56)
clojure.lang.AFn.applyToHelper (AFn.java:159)
clojure.lang.AFn.applyTo (AFn.java:151)
clojure.core$apply.invoke (core.clj:617)
clojure.core$with_bindings_STAR_.doInvoke (core.clj:1788)
clojure.lang.RestFn.invoke (RestFn.java:425)
clojure.tools.nrepl.middleware.interruptible_eval$evaluate.invoke (interruptible_eval.clj:41)
clojure.tools.nrepl.middleware.interruptible_eval$interruptible_eval$fn__632$fn__635.invoke (interruptible_eval.clj:171)
clojure.core$comp$fn__4154.invoke (core.clj:2330)
clojure.tools.nrepl.middleware.interruptible_eval$run_next$fn__625.invoke (interruptible_eval.clj:138)
clojure.lang.AFn.run (AFn.java:24)
java.util.concurrent.ThreadPoolExecutor$Worker.runTask (ThreadPoolExecutor.java:895)
java.util.concurrent.ThreadPoolExecutor$Worker.run (ThreadPoolExecutor.java:918)
java.lang.Thread.run (Thread.java:680)
I think it may be good to remove the link to crossclj since it has been shut down, and bump the copyright date so that this project doesn't appear to be abandonware.
Hi,
Thank you for releasing this library. I found it useful indeed.
I would love to see an example for component entities, as explained in the official docs.
This is perhaps the most befuzzling thing I've come across in a while.
I have a big vector of schemas generated by this library. They are all returned by (get-all-schemas)
which has the job of loading all the schemas in from the namespaces under api.datomic-schemas.*
.
When I call (s/generate-schema (get-all-schemas))
, I get
CompilerException java.lang.ClassCastException: clojure.lang.PersistentVector cannot be cast to clojure.lang.Named
Hmm...surely there must be an issue with an element or two in this array
after much debugging
; Like nth but removes instead of retrieves the item
(defn drop-nth [n coll] (->> coll (map vector (iterate inc 1)) (remove #(zero? (mod (first %) n))) (map second)))
(s/generate-schema (drop-nth 5 (get-all-schemas))) ; Error
(s/generate-schema (drop-nth 10 (get-all-schemas))) ; Error
(s/generate-schema (drop-nth 12 (get-all-schemas))) ; Error
(s/generate-schema (drop-nth 18 (get-all-schemas))) ; No error! 18 is the problem child
; To confirm:
(s/generate-schema (vector (nth (get-all-schemas) 18))) ; No error
; wat
Here's the value of (vector (nth (get-all-schemas) 18))
[{:fields {"description" [:string #{}], "weight" [:double #{}], "genus" [:string #{}]}, :name "species", :basetype :species, :namespace "species"}]
UPDATE:
Removed the "problem-child" schema to see if it would work without it. Same error, different schema BUT still number 18. Does this library somehow have a problem with the number 18? There are 30 total schemas returned by (get-all-schemas)
A unique identity attribute is always indexed by value, in order to support uniqueness checks. Specifying :db/index true is redundant and not recommended.
The MIT License is GPL compatible and it is not required to disclose the source code of the project (unlike EPL).
I'm adding this as an issue to gather the feedback of whoever might be interested in this change. Please comment before the 21st January 2015, otherwise I'll probably change the License to MIT.
For reference:
http://opensource.org/licenses/MIT
http://www.eclipse.org/legal/epl-v10.html
http://choosealicense.com/licenses/
I had to do a big of debugging to understand why
(fields
[thing :many :string])
Was invalid. Didn't realize until I took a look at the source. I would add a PR for the README explaining that opts are last, but perhaps it makes more send to have options in hash w/ boolean values or a nested vector or something. What do you think?
#10 is an example of the pain brought on by this ๐
Would it possible to add this? It'd be super useful for easing schema diffs.
I'm suggesting that since datomic is an EAV database it will be more semantic to name the schema
api as entity
and the field
as attribute
.
To illustrate:
Instead of
(defn dbschema []
[(schema user
(fields
[username :string :indexed]
[pwd :string "Hashed password string"]
[email :string :indexed]
[status :enum [:pending :active :inactive :cancelled]]
[group :ref :many]))
(schema group
(fields
[name :string]
[permission :string :many]))])
we could have
(defn dbschema []
[(entity user
(attributes
[username :string :indexed]
[pwd :string "Hashed password string"]
[email :string :indexed]
[status :enum [:pending :active :inactive :cancelled]]
[group :ref :many]))
(entity group
(attributes
[name :string]
[permission :string :many]))])
What do you think?
Hi,
I very much like using datomic-schema, thank you for making it.
When I use it, I avoid using the macros and instead
(defn collect-fields
[field-defs]
{:fields (reduce collect-field {} field-defs)})
(defn expand-to-datomic [entity-defs]
(s/generate-schema
(for [[entity fields] entity-defs]
(s/schema* (name entity) (collect-fields fields)))
{:gen-all? false}))
(def my-schema
'{assessment
{type [:ref :one]
assessee [:ref :one]
assessor [:ref :one]
status [:enum [:pending :complete :cancelled]]
date [:instant]
duration-minutes [:long]}})
(expand-to-datomic my-schema)
If you think this might be useful for other people, it might be good to add these functions in (happy to submit a pull request also). They don't break existing usage.
I find this particularly useful because I also have some basic functions which produce a DataScript schema from the same data.
(defn map-intersection
[m1 m2]
(into {}
(for [[k v] m1
:when (= v (m2 k))]
[k v])))
(def datascript-attrs
{:db/cardinality :db.cardinality/many
:db/valueType :db.type/ref
:db/index true})
(defn reshape [{:keys [db/ident] :as m}]
[ident (map-intersection datascript-attrs m)])
(defn expand-to-datascript [entity-defs]
(->> entity-defs
(expand-to-datomic)
(filter map?)
(map reshape)
(into {})))
(def datascript-schema
(expand-to-datascript my-schema))
Regards,
Timothy
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.