Skip to content
Permalink
Branch: master
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
1305 lines (1187 sloc) 54.7 KB
package molecule.examples.seattle
import molecule.api.in2_out8._
import molecule.ast.model._
import molecule.ast.query._
import molecule.examples.seattle.dsl.seattle._
import scala.language.reflectiveCalls
class SeattleTransformationTests extends SeattleSpec {
"A first query" >> {
// Testing that a molecule goes correctly through 3 transformations:
m(Community.name) --> {
// Dsl --> Model
// Each attribute is modelled as an "Atom"
Model(List(
Atom("Community", "name", "String", 1, VarValue)))
} --> {
// Model --> Query
// Each atom transforms to one or more query clauses and we
// introduce value markers (like 'a) to connect elements
Query(
Find(List(
Var("b"))),
Where(List(
DataClause("a", KW("Community", "name"), "b"))))
} --> {
// Query --> Query string
// The Query object is transformed to a query string
"""[:find ?b
| :where [?a :Community/name ?b]]""".stripMargin
}
}
"Querying _for_ attribute values" >> {
// Multiple attributes
m(Community.name.url.category) -->
Model(List(
Atom("Community", "name", "String", 1, VarValue),
Atom("Community", "url", "String", 1, VarValue),
Atom("Community", "category", "String", 2, VarValue))
) -->
Query(
Find(List(
Var("b"),
Var("c"),
AggrExpr("distinct", List(), Var("d")))),
Where(List(
DataClause("a", KW("Community", "name"), "b"),
DataClause("a", KW("Community", "url"), "c"),
DataClause("a", KW("Community", "category"), "d")))
) -->
"""[:find ?b ?c (distinct ?d)
| :where [?a :Community/name ?b]
| [?a :Community/url ?c]
| [?a :Community/category ?d]]""".stripMargin
}
"Querying _by_ attribute values" >> {
// Names of twitter communities
m(Community.name.type_("twitter")) -->
Model(List(
Atom("Community", "name", "String", 1, VarValue),
Atom("Community", "type_", "String", 1, Eq(List("twitter")), Some(":Community.type/")))
) -->
Query(
Find(List(
Var("b"))),
Where(List(
DataClause("a", KW("Community", "name"), "b"),
DataClause("a", KW("Community", "type"), Val(":Community.type/twitter"))))
) -->
"""[:find ?b
| :where [?a :Community/name ?b]
| [?a :Community/type ":Community.type/twitter"]]""".stripMargin
// Categories (many-cardinality) of the Belltown Community
m(Community.name_("belltown").category) -->
Model(List(
Atom("Community", "name_", "String", 1, Eq(List("belltown"))),
Atom("Community", "category", "String", 2, VarValue))
) -->
Query(
Find(List(
AggrExpr("distinct", List(), Var("c")))),
Where(List(
DataClause(ImplDS, Var("a"), KW("Community", "name"), Val("belltown"), Empty),
DataClause(ImplDS, Var("a"), KW("Community", "category"), Var("c"), Empty)))
) -->
"""[:find (distinct ?c)
| :where [?a :Community/name "belltown"]
| [?a :Community/category ?c]]""".stripMargin
// Names of news or arts communities - transforms to a query using Rules
m(Community.name.category_("news", "arts")) -->
Model(List(
Atom("Community", "name", "String", 1, VarValue),
Atom("Community", "category_", "String", 2, Eq(List("news", "arts")), None))
) -->
Query(
Find(List(
Var("b"))),
In(List(), List(
Rule("rule1", List(Var("a")), List(DataClause(ImplDS, Var("a"), KW("Community", "category"), Val("news"), Empty))),
Rule("rule1", List(Var("a")), List(DataClause(ImplDS, Var("a"), KW("Community", "category"), Val("arts"), Empty)))), List(DS)),
Where(List(
DataClause(ImplDS, Var("a"), KW("Community", "name"), Var("b"), Empty),
RuleInvocation("rule1", List(Var("a")))))
) -->
"""[:find ?b
| :in $ %
| :where [?a :Community/name ?b]
| (rule1 ?a)]
|
|INPUTS:
|List(
| 1 datomic.db.Db@xxx
| 2 [[(rule1 ?a) [?a :Community/category "news"]]
| [(rule1 ?a) [?a :Community/category "arts"]]]
|)""".stripMargin
}
"Querying across references" >> {
// Communities in north eastern region
// Ref's are modelelled as "Bond"'s (between Atoms)
m(Community.name.Neighborhood.District.region_("ne")) -->
Model(List(
Atom("Community", "name", "String", 1, VarValue, None),
Bond("Community", "neighborhood", "Neighborhood", 1),
Bond("Neighborhood", "district", "District", 1),
Atom("District", "region_", "String", 1, Eq(List("ne")), Some(":District.region/")))
) -->
Query(
Find(List(
Var("b"))),
Where(List(
DataClause(ImplDS, Var("a"), KW("Community", "name"), Var("b"), Empty),
DataClause(ImplDS, Var("a"), KW("Community", "neighborhood", "Neighborhood"), Var("c"), Empty, NoBinding),
DataClause(ImplDS, Var("c"), KW("Neighborhood", "district", "District"), Var("d"), Empty, NoBinding),
DataClause(ImplDS, Var("d"), KW("District", "region"), Val(":District.region/ne"), Empty)))
) -->
"""[:find ?b
| :where [?a :Community/name ?b]
| [?a :Community/neighborhood ?c]
| [?c :Neighborhood/district ?d]
| [?d :District/region ":District.region/ne"]]""".stripMargin
// Communities and their region
m(Community.name.Neighborhood.District.region) -->
Model(List(
Atom("Community", "name", "String", 1, VarValue, None),
Bond("Community", "neighborhood", "Neighborhood", 1),
Bond("Neighborhood", "district", "District", 1),
Atom("District", "region", "String", 1, EnumVal, Some(":District.region/")))
) -->
Query(
Find(List(
Var("b"),
Var("e2"))),
Where(List(
DataClause(ImplDS, Var("a"), KW("Community", "name"), Var("b"), Empty, NoBinding),
DataClause(ImplDS, Var("a"), KW("Community", "neighborhood", "Neighborhood"), Var("c"), Empty, NoBinding),
DataClause(ImplDS, Var("c"), KW("Neighborhood", "district", "District"), Var("d"), Empty, NoBinding),
DataClause(ImplDS, Var("d"), KW("District", "region"), Var("e"), Empty, NoBinding),
DataClause(ImplDS, Var("e"), KW("db", "ident"), Var("e1"), Empty, NoBinding),
Funct("name", List(Var("e1")), ScalarBinding(Var("e2")))))
) -->
"""[:find ?b ?e2
| :where [?a :Community/name ?b]
| [?a :Community/neighborhood ?c]
| [?c :Neighborhood/district ?d]
| [?d :District/region ?e]
| [?e :db/ident ?e1]
| [(name ?e1) ?e2]]""".stripMargin
}
"Advanced queries - parameterizing queries" >> {
/** ******* Single input parameter **************************/
// Community input molecule awaiting some type value
m(Community.name.type_(?)) -->
Model(List(
Atom("Community", "name", "String", 1, VarValue, None),
Atom("Community", "type_", "String", 1, Qm, Some(":Community.type/")))
) -->
Query(
Find(List(
Var("b"))),
In(
List(
Placeholder(Var("a"), KW("Community", "type"), Var("c2"), Some(":Community.type/"))),
List(),
List(DS)),
Where(List(
DataClause(ImplDS, Var("a"), KW("Community", "name"), Var("b"), Empty, NoBinding),
DataClause(ImplDS, Var("a"), KW("Community", "type"), Var("c"), Empty, NoBinding),
DataClause(ImplDS, Var("c"), KW("db", "ident"), Var("c1"), Empty, NoBinding),
Funct("name", Seq(Var("c1")), ScalarBinding(Var("c2")))))
) -->
"""[:find ?b
| :in $ ?c2
| :where [?a :Community/name ?b]
| [?a :Community/type ?c]
| [?c :db/ident ?c1]
| [(name ?c1) ?c2]]""".stripMargin
// Applying a value as input
m(Community.name.type_(?)).apply("twitter") -->
Model(List(
Atom("Community", "name", "String", 1, VarValue, None),
Atom("Community", "type_", "String", 1, Qm, Some(":Community.type/")))
) -->
Query(
Find(List(
Var("b"))),
In(
List(
InVar(ScalarBinding(Var("c")), Seq(Seq(":Community.type/twitter")))),
List(),
List(DS)),
Where(List(
DataClause(ImplDS, Var("a"), KW("Community", "name"), Var("b"), Empty, NoBinding),
DataClause(ImplDS, Var("a"), KW("Community", "type"), Var("c"), Empty, NoBinding)))
) -->
"""[:find ?b
| :in $ ?c
| :where [?a :Community/name ?b]
| [?a :Community/type ?c]]
|
|INPUTS:
|List(
| 1 datomic.db.Db@xxx
| 2 :Community.type/twitter
|)""".stripMargin
// Omit underscore to return a `type` value
m(Community.name.`type`(?)) -->
Model(List(
Atom("Community", "name", "String", 1, VarValue, None),
Atom("Community", "type", "String", 1, Qm, Some(":Community.type/")))
) -->
Query(
Find(List(
Var("b"),
Var("c2"))),
In(
List(
Placeholder(Var("a"), KW("Community", "type"), Var("c2"), Some(":Community.type/"))),
List(),
List(DS)),
Where(List(
DataClause(ImplDS, Var("a"), KW("Community", "name"), Var("b"), Empty, NoBinding),
DataClause(ImplDS, Var("a"), KW("Community", "type"), Var("c"), Empty, NoBinding),
DataClause(ImplDS, Var("c"), KW("db", "ident"), Var("c1"), Empty, NoBinding),
Funct("name", Seq(Var("c1")), ScalarBinding(Var("c2")))))
) -->
"""[:find ?b ?c2
| :in $ ?c2
| :where [?a :Community/name ?b]
| [?a :Community/type ?c]
| [?c :db/ident ?c1]
| [(name ?c1) ?c2]]""".stripMargin
m(Community.name.`type`(?)).apply("twitter") -->
Model(List(
Atom("Community", "name", "String", 1, VarValue, None),
Atom("Community", "type", "String", 1, Qm, Some(":Community.type/")))
) -->
Query(
Find(List(
Var("b"),
Var("c2"))),
In(
List(
InVar(ScalarBinding(Var("c2")), Seq(Seq("twitter")))),
List(),
List(DS)),
Where(List(
DataClause(ImplDS, Var("a"), KW("Community", "name"), Var("b"), Empty, NoBinding),
DataClause(ImplDS, Var("a"), KW("Community", "type"), Var("c"), Empty, NoBinding),
DataClause(ImplDS, Var("c"), KW("db", "ident"), Var("c1"), Empty, NoBinding),
Funct("name", Seq(Var("c1")), ScalarBinding(Var("c2")))))
) -->
"""[:find ?b ?c2
| :in $ ?c2
| :where [?a :Community/name ?b]
| [?a :Community/type ?c]
| [?c :db/ident ?c1]
| [(name ?c1) ?c2]]
|
|INPUTS:
|List(
| 1 datomic.db.Db@xxx
| 2 twitter
|)""".stripMargin
// Multiple input values - logical OR ------------------------
m(Community.name.`type`(?)).apply("facebook_page" or "twitter") -->
Model(List(
Atom("Community", "name", "String", 1, VarValue, None),
Atom("Community", "type", "String", 1, Qm, Some(":Community.type/")))
) -->
Query(
Find(List(
Var("b"),
Var("c2"))),
In(
List(
InVar(CollectionBinding(Var("c2")), Seq(Seq("facebook_page", "twitter")))),
List(),
List(DS)),
Where(List(
DataClause(ImplDS, Var("a"), KW("Community", "name"), Var("b"), Empty, NoBinding),
DataClause(ImplDS, Var("a"), KW("Community", "type"), Var("c"), Empty, NoBinding),
DataClause(ImplDS, Var("c"), KW("db", "ident"), Var("c1"), Empty, NoBinding),
Funct("name", Seq(Var("c1")), ScalarBinding(Var("c2")))))
) -->
"""[:find ?b ?c2
| :in $ [?c2 ...]
| :where [?a :Community/name ?b]
| [?a :Community/type ?c]
| [?c :db/ident ?c1]
| [(name ?c1) ?c2]]
|
|INPUTS:
|List(
| 1 datomic.db.Db@xxx
| 2 [facebook_page, twitter]
|)""".stripMargin
// Finding communities of type "facebook_page" OR "twitter"
// The following 3 notation variations transform in the same way
m(Community.name.`type`(?)).apply("facebook_page" or "twitter") -->
// or
// m(Community.name.`type`(?))("facebook_page", "twitter") -->
// m(Community.name.`type`(?))(List("facebook_page", "twitter")) -->
Model(List(
Atom("Community", "name", "String", 1, VarValue, None),
Atom("Community", "type", "String", 1, Qm, Some(":Community.type/")))
) -->
Query(
Find(List(
Var("b"),
Var("c2"))),
In(
List(
InVar(CollectionBinding(Var("c2")), Seq(Seq("facebook_page", "twitter")))),
List(),
List(DS)),
Where(List(
DataClause(ImplDS, Var("a"), KW("Community", "name"), Var("b"), Empty, NoBinding),
DataClause(ImplDS, Var("a"), KW("Community", "type"), Var("c"), Empty, NoBinding),
DataClause(ImplDS, Var("c"), KW("db", "ident"), Var("c1"), Empty, NoBinding),
Funct("name", Seq(Var("c1")), ScalarBinding(Var("c2")))))
) -->
"""[:find ?b ?c2
| :in $ [?c2 ...]
| :where [?a :Community/name ?b]
| [?a :Community/type ?c]
| [?c :db/ident ?c1]
| [(name ?c1) ?c2]]
|
|INPUTS:
|List(
| 1 datomic.db.Db@xxx
| 2 [facebook_page, twitter]
|)""".stripMargin
/** ******* Multiple input parameters **************************/
// Single tuple of input values - AND-semantics ------------------------
m(Community.name.type_(?).orgtype_(?)) -->
Model(List(
Atom("Community", "name", "String", 1, VarValue, None),
Atom("Community", "type_", "String", 1, Qm, Some(":Community.type/")),
Atom("Community", "orgtype_", "String", 1, Qm, Some(":Community.orgtype/")))
) -->
Query(
Find(List(
Var("b"))),
In(
List(
Placeholder(Var("a"), KW("Community", "type"), Var("c2"), Some(":Community.type/")),
Placeholder(Var("a"), KW("Community", "orgtype"), Var("d2"), Some(":Community.orgtype/"))),
List(),
List(DS)),
Where(List(
DataClause(ImplDS, Var("a"), KW("Community", "name"), Var("b"), Empty, NoBinding),
DataClause(ImplDS, Var("a"), KW("Community", "type"), Var("c"), Empty, NoBinding),
DataClause(ImplDS, Var("c"), KW("db", "ident"), Var("c1"), Empty, NoBinding),
Funct("name", Seq(Var("c1")), ScalarBinding(Var("c2"))),
DataClause(ImplDS, Var("a"), KW("Community", "orgtype"), Var("d"), Empty, NoBinding),
DataClause(ImplDS, Var("d"), KW("db", "ident"), Var("d1"), Empty, NoBinding),
Funct("name", Seq(Var("d1")), ScalarBinding(Var("d2")))))
) -->
"""[:find ?b
| :in $ ?c2 ?d2
| :where [?a :Community/name ?b]
| [?a :Community/type ?c]
| [?c :db/ident ?c1]
| [(name ?c1) ?c2]
| [?a :Community/orgtype ?d]
| [?d :db/ident ?d1]
| [(name ?d1) ?d2]]""".stripMargin
// The following 3 notation variations transform in the same way
m(Community.name.type_(?).orgtype_(?)).apply("email_list" and "community") -->
// or
// m(Community.name.type_(?).orgtype_(?)).apply("email_list", "community") -->
// m(Community.name.type_(?).orgtype_(?)).apply(List(("email_list", "community"))) -->
Model(List(
Atom("Community", "name", "String", 1, VarValue, None),
Atom("Community", "type_", "String", 1, Qm, Some(":Community.type/")),
Atom("Community", "orgtype_", "String", 1, Qm, Some(":Community.orgtype/")))
) -->
Query(
Find(List(
Var("b"))),
In(
List(
InVar(ScalarBinding(Var("c")), Seq(Seq(":Community.type/email_list"))),
InVar(ScalarBinding(Var("d")), Seq(Seq(":Community.orgtype/community")))),
List(),
List(DS)),
Where(List(
DataClause(ImplDS, Var("a"), KW("Community", "name"), Var("b"), Empty, NoBinding),
DataClause(ImplDS, Var("a"), KW("Community", "type"), Var("c"), Empty, NoBinding),
DataClause(ImplDS, Var("a"), KW("Community", "orgtype"), Var("d"), Empty, NoBinding)))
) -->
"""[:find ?b
| :in $ ?c ?d
| :where [?a :Community/name ?b]
| [?a :Community/type ?c]
| [?a :Community/orgtype ?d]]
|
|INPUTS:
|List(
| 1 datomic.db.Db@xxx
| 2 :Community.type/email_list
| 3 :Community.orgtype/community
|)""".stripMargin
// Multiple tuples of input values ------------------------
// Communities of some `type` AND some `orgtype` (include input values)
m(Community.name.`type`(?).orgtype(?)) -->
Model(List(
Atom("Community", "name", "String", 1, VarValue, None),
Atom("Community", "type", "String", 1, Qm, Some(":Community.type/")),
Atom("Community", "orgtype", "String", 1, Qm, Some(":Community.orgtype/")))
) -->
Query(
Find(List(
Var("b"),
Var("c2"),
Var("d2"))),
In(
List(
Placeholder(Var("a"), KW("Community", "type"), Var("c2"), Some(":Community.type/")),
Placeholder(Var("a"), KW("Community", "orgtype"), Var("d2"), Some(":Community.orgtype/"))),
List(),
List(DS)),
Where(List(
DataClause(ImplDS, Var("a"), KW("Community", "name"), Var("b"), Empty, NoBinding),
DataClause(ImplDS, Var("a"), KW("Community", "type"), Var("c"), Empty, NoBinding),
DataClause(ImplDS, Var("c"), KW("db", "ident"), Var("c1"), Empty, NoBinding),
Funct("name", Seq(Var("c1")), ScalarBinding(Var("c2"))),
DataClause(ImplDS, Var("a"), KW("Community", "orgtype"), Var("d"), Empty, NoBinding),
DataClause(ImplDS, Var("d"), KW("db", "ident"), Var("d1"), Empty, NoBinding),
Funct("name", Seq(Var("d1")), ScalarBinding(Var("d2")))))
) -->
"""[:find ?b ?c2 ?d2
| :in $ ?c2 ?d2
| :where [?a :Community/name ?b]
| [?a :Community/type ?c]
| [?c :db/ident ?c1]
| [(name ?c1) ?c2]
| [?a :Community/orgtype ?d]
| [?d :db/ident ?d1]
| [(name ?d1) ?d2]]""".stripMargin
// The following 3 notation variations transform in the same way
// m(Community.name.`type`(?!).orgtype(?!)).apply(("email_list" and "community") or ("website" and "commercial")) -->
// m(Community.name.`type`(?!).orgtype(?!)).apply(("email_list", "community"), ("website", "commercial")) -->
m(Community.name.`type`(?).orgtype(?))(Seq(("email_list", "community"), ("website", "commercial"))) -->
Model(List(
Atom("Community", "name", "String", 1, VarValue, None),
Atom("Community", "type", "String", 1, Qm, Some(":Community.type/")),
Atom("Community", "orgtype", "String", 1, Qm, Some(":Community.orgtype/")))
) -->
Query(
Find(List(
Var("b"),
Var("c2"),
Var("d2"))),
In(
List(),
List(
Rule("rule1", Seq(Var("a")), Seq(
DataClause(ImplDS, Var("a"), KW("Community", "type"), Val(":Community.type/email_list"), Empty, NoBinding),
DataClause(ImplDS, Var("a"), KW("Community", "orgtype"), Val(":Community.orgtype/community"), Empty, NoBinding))),
Rule("rule1", Seq(Var("a")), Seq(
DataClause(ImplDS, Var("a"), KW("Community", "type"), Val(":Community.type/website"), Empty, NoBinding),
DataClause(ImplDS, Var("a"), KW("Community", "orgtype"), Val(":Community.orgtype/commercial"), Empty, NoBinding)))),
List(DS)),
Where(List(
DataClause(ImplDS, Var("a"), KW("Community", "name"), Var("b"), Empty, NoBinding),
DataClause(ImplDS, Var("a"), KW("Community", "type"), Var("c"), Empty, NoBinding),
DataClause(ImplDS, Var("c"), KW("db", "ident"), Var("c1"), Empty, NoBinding),
Funct("name", Seq(Var("c1")), ScalarBinding(Var("c2"))),
RuleInvocation("rule1", Seq(Var("a"))),
DataClause(ImplDS, Var("a"), KW("Community", "orgtype"), Var("d"), Empty, NoBinding),
DataClause(ImplDS, Var("d"), KW("db", "ident"), Var("d1"), Empty, NoBinding),
Funct("name", Seq(Var("d1")), ScalarBinding(Var("d2")))))
) -->
"""[:find ?b ?c2 ?d2
| :in $ %
| :where [?a :Community/name ?b]
| [?a :Community/type ?c]
| [?c :db/ident ?c1]
| [(name ?c1) ?c2]
| (rule1 ?a)
| [?a :Community/orgtype ?d]
| [?d :db/ident ?d1]
| [(name ?d1) ?d2]]
|
|INPUTS:
|List(
| 1 datomic.db.Db@xxx
| 2 [[(rule1 ?a)
| [?a :Community/type ":Community.type/email_list"]
| [?a :Community/orgtype ":Community.orgtype/community"]]
| [(rule1 ?a)
| [?a :Community/type ":Community.type/website"]
| [?a :Community/orgtype ":Community.orgtype/commercial"]]]
|)""".stripMargin
}
"Invoking functions in queries" >> {
m(Community.name < "C") -->
Model(List(
Atom("Community", "name", "String", 1, Lt("C")))
) -->
Query(
Find(List(
Var("b"))),
Where(List(
DataClause(ImplDS, Var("a"), KW("Community", "name"), Var("b"), Empty),
Funct(".compareTo ^String", List(Var("b"), Val("C")), ScalarBinding(Var("b2"))),
Funct("<", List(Var("b2"), Val(0)), NoBinding)))
) -->
"""[:find ?b
| :where [?a :Community/name ?b]
| [(.compareTo ^String ?b "C") ?b2]
| [(< ?b2 0)]]""".stripMargin
m(Community.name < ?) -->
Model(List(
Atom("Community", "name", "String", 1, Lt(Qm)))
) -->
Query(
Find(List(
Var("b"))),
In(
List(
Placeholder(Var("a"), KW("Community", "name"), Var("b1"), None)),
List(),
List(DS)),
Where(List(
DataClause(ImplDS, Var("a"), KW("Community", "name"), Var("b"), Empty, NoBinding),
Funct(".compareTo ^String", Seq(Var("b"), Var("b1")), ScalarBinding(Var("b2"))),
Funct("<", Seq(Var("b2"), Val(0)), NoBinding)))
) -->
"""[:find ?b
| :in $ ?b1
| :where [?a :Community/name ?b]
| [(.compareTo ^String ?b ?b1) ?b2]
| [(< ?b2 0)]]""".stripMargin
m(Community.name < ?).apply("C") -->
Model(List(
Atom("Community", "name", "String", 1, Lt(Qm)))
) -->
Query(
Find(List(
Var("b"))),
In(List(
InVar(ScalarBinding(Var("b1")), List(List("C"))))),
Where(List(
DataClause(ImplDS, Var("a"), KW("Community", "name"), Var("b"), Empty, NoBinding),
Funct(".compareTo ^String", List(Var("b"), Var("b1")), ScalarBinding(Var("b2"))),
Funct("<", List(Var("b2"), Val(0)), NoBinding)))
) -->
"""[:find ?b
| :in $ ?b1
| :where [?a :Community/name ?b]
| [(.compareTo ^String ?b ?b1) ?b2]
| [(< ?b2 0)]]
|
|INPUTS:
|List(
| 1 datomic.db.Db@xxx
| 2 C
|)""".stripMargin
}
"Querying with fulltext search" >> {
m(Community.name contains "Wallingford") -->
Model(List(
Atom("Community", "name", "String", 1, Fulltext(List("Wallingford"))))
) -->
Query(
Find(List(
Var("b"))),
Where(List(
Funct("fulltext", Seq(DS, KW("Community", "name"), Val("Wallingford")), RelationBinding(List(Var("a"), Var("b"))))))
) -->
"""[:find ?b
| :where [(fulltext $ :Community/name "Wallingford") [[ ?a ?b ]]]]""".stripMargin
m(Community.name contains ?) -->
Model(List(
Atom("Community", "name", "String", 1, Fulltext(Seq(Qm))))
) -->
Query(
Find(List(
Var("b"))),
In(
List(
Placeholder(Var("a"), KW("Community", "name"), Var("b1"), None)),
List(),
List(DS)),
Where(List(
Funct("fulltext", Seq(DS, KW("Community", "name"), Var("b1")), RelationBinding(List(Var("a"), Var("b"))))))
) -->
"""[:find ?b
| :in $ ?b1
| :where [(fulltext $ :Community/name ?b1) [[ ?a ?b ]]]]""".stripMargin
m(Community.name contains ?).apply("Wallingford") -->
Model(List(
Atom("Community", "name", "String", 1, Fulltext(List(Qm))))
) -->
Query(
Find(List(
Var("b"))),
In(
List(
InVar(ScalarBinding(Var("b1")), Seq(Seq("Wallingford")))),
List(),
List(DS)),
Where(List(
Funct("fulltext", Seq(DS, KW("Community", "name"), Var("b1")), RelationBinding(List(Var("a"), Var("b"))))))
) -->
"""[:find ?b
| :in $ ?b1
| :where [(fulltext $ :Community/name ?b1) [[ ?a ?b ]]]]
|
|INPUTS:
|List(
| 1 datomic.db.Db@xxx
| 2 Wallingford
|)""".stripMargin
// Fulltext search on many-attribute (`category`)
m(Community.name.type_("website").category contains "food") -->
Model(List(
Atom("Community", "name", "String", 1, VarValue, None),
Atom("Community", "type_", "String", 1, Eq(List("website")), Some(":Community.type/")),
Atom("Community", "category", "String", 2, Fulltext(List("food")), None))
) -->
Query(
Find(List(
Var("b"),
AggrExpr("distinct", Seq(), Var("d")))),
In(
List(),
List(
Rule("rule1", Seq(Var("a")), Seq(
Funct("fulltext", Seq(DS(""), KW("Community", "category"), Val("food")), RelationBinding(List(Var("a"), Var("a_1"))))))),
List(DS)),
Where(List(
DataClause(ImplDS, Var("a"), KW("Community", "name"), Var("b"), Empty, NoBinding),
DataClause(ImplDS, Var("a"), KW("Community", "type"), Val(":Community.type/website"), Empty, NoBinding),
DataClause(ImplDS, Var("a"), KW("Community", "category"), Var("d"), Empty, NoBinding),
RuleInvocation("rule1", Seq(Var("a")))))
) -->
"""[:find ?b (distinct ?d)
| :in $ %
| :where [?a :Community/name ?b]
| [?a :Community/type ":Community.type/website"]
| [?a :Community/category ?d]
| (rule1 ?a)]
|
|INPUTS:
|List(
| 1 datomic.db.Db@xxx
| 2 [[(rule1 ?a) [(fulltext $ :Community/category "food") [[ ?a ?a_1 ]]]]]
|)""".stripMargin
m(Community.name.type_(?).category contains ?) -->
Model(List(
Atom("Community", "name", "String", 1, VarValue, None),
Atom("Community", "type_", "String", 1, Qm, Some(":Community.type/")),
Atom("Community", "category", "String", 2, Fulltext(List(Qm)), None))
) -->
Query(
Find(List(
Var("b"),
AggrExpr("distinct", Seq(), Var("d")))),
In(
List(
Placeholder(Var("a"), KW("Community", "type"), Var("c2"), Some(":Community.type/")),
Placeholder(Var("a"), KW("Community", "category"), Var("d1"), None)),
List(),
List(DS)),
Where(List(
DataClause(ImplDS, Var("a"), KW("Community", "name"), Var("b"), Empty, NoBinding),
DataClause(ImplDS, Var("a"), KW("Community", "type"), Var("c"), Empty, NoBinding),
DataClause(ImplDS, Var("c"), KW("db", "ident"), Var("c1"), Empty, NoBinding),
Funct("name", Seq(Var("c1")), ScalarBinding(Var("c2"))),
Funct("fulltext", Seq(DS, KW("Community", "category"), Var("d1")), RelationBinding(List(Var("a"), Var("d"))))))
) -->
"""[:find ?b (distinct ?d)
| :in $ ?c2 ?d1
| :where [?a :Community/name ?b]
| [?a :Community/type ?c]
| [?c :db/ident ?c1]
| [(name ?c1) ?c2]
| [(fulltext $ :Community/category ?d1) [[ ?a ?d ]]]]""".stripMargin
m(Community.name.type_(?).category contains ?).apply("website", Set("food")) -->
Model(List(
Atom("Community", "name", "String", 1, VarValue, None),
Atom("Community", "type_", "String", 1, Qm, Some(":Community.type/")),
Atom("Community", "category", "String", 2, Fulltext(List(Qm)), None))
) -->
Query(
Find(List(
Var("b"),
AggrExpr("distinct", Seq(), Var("d")))),
In(
List(
InVar(ScalarBinding(Var("c")), Seq(Seq(":Community.type/website")))),
List(
Rule("rule1", Seq(Var("a")), Seq(
Funct("fulltext", Seq(DS(""), KW("Community", "category"), Val("food")), RelationBinding(List(Var("a"), Var("d1_1"))))))),
List(DS)),
Where(List(
DataClause(ImplDS, Var("a"), KW("Community", "name"), Var("b"), Empty, NoBinding),
DataClause(ImplDS, Var("a"), KW("Community", "type"), Var("c"), Empty, NoBinding),
DataClause(ImplDS, Var("a"), KW("Community", "category"), Var("d"), Empty, NoBinding),
RuleInvocation("rule1", Seq(Var("a")))))
) -->
"""[:find ?b (distinct ?d)
| :in $ % ?c
| :where [?a :Community/name ?b]
| [?a :Community/type ?c]
| [?a :Community/category ?d]
| (rule1 ?a)]
|
|INPUTS:
|List(
| 1 datomic.db.Db@xxx
| 2 [[(rule1 ?a) [(fulltext $ :Community/category "food") [[ ?a ?d1_1 ]]]]]
| 3 :Community.type/website
|)""".stripMargin
}
"Querying with rules (logical OR)" >> {
// Social media
m(Community.name.type_("twitter" or "facebook_page")) -->
Model(List(
Atom("Community", "name", "String", 1, VarValue, None),
Atom("Community", "type_", "String", 1, Eq(List("twitter", "facebook_page")), Some(":Community.type/")))
) -->
Query(
Find(List(
Var("b"))),
In(List(), List(
Rule("rule1", List(Var("a")), List(
DataClause(ImplDS, Var("a"), KW("Community", "type"), Val(":Community.type/twitter"), Empty))),
Rule("rule1", List(Var("a")), List(
DataClause(ImplDS, Var("a"), KW("Community", "type"), Val(":Community.type/facebook_page"), Empty)))), List(DS)),
Where(List(
DataClause(ImplDS, Var("a"), KW("Community", "name"), Var("b"), Empty),
RuleInvocation("rule1", List(Var("a")))))
) -->
"""[:find ?b
| :in $ %
| :where [?a :Community/name ?b]
| (rule1 ?a)]
|
|INPUTS:
|List(
| 1 datomic.db.Db@xxx
| 2 [[(rule1 ?a) [?a :Community/type ":Community.type/twitter"]]
| [(rule1 ?a) [?a :Community/type ":Community.type/facebook_page"]]]
|)""".stripMargin
m(Community.name.Neighborhood.District.region("ne" or "sw")) -->
Model(List(
Atom("Community", "name", "String", 1, VarValue, None),
Bond("Community", "neighborhood", "Neighborhood", 1),
Bond("Neighborhood", "district", "District", 1),
Atom("District", "region", "String", 1, Eq(List("ne", "sw")), Some(":District.region/")))
) -->
Query(
Find(List(
Var("b"),
Var("e2"))),
In(List(), List(
Rule("rule1", List(Var("d")), List(
DataClause(ImplDS, Var("d"), KW("District", "region"), Val(":District.region/ne"), Empty))),
Rule("rule1", List(Var("d")), List(
DataClause(ImplDS, Var("d"), KW("District", "region"), Val(":District.region/sw"), Empty)))), List(DS)),
Where(List(
DataClause(ImplDS, Var("a"), KW("Community", "name"), Var("b"), Empty, NoBinding),
DataClause(ImplDS, Var("a"), KW("Community", "neighborhood", "Neighborhood"), Var("c"), Empty, NoBinding),
DataClause(ImplDS, Var("c"), KW("Neighborhood", "district", "District"), Var("d"), Empty, NoBinding),
DataClause(ImplDS, Var("d"), KW("District", "region"), Var("e"), Empty, NoBinding),
DataClause(ImplDS, Var("e"), KW("db", "ident"), Var("e1"), Empty, NoBinding),
Funct("name", List(Var("e1")), ScalarBinding(Var("e2"))),
RuleInvocation("rule1", List(Var("d")))))
) -->
"""[:find ?b ?e2
| :in $ %
| :where [?a :Community/name ?b]
| [?a :Community/neighborhood ?c]
| [?c :Neighborhood/district ?d]
| [?d :District/region ?e]
| [?e :db/ident ?e1]
| [(name ?e1) ?e2]
| (rule1 ?d)]
|
|INPUTS:
|List(
| 1 datomic.db.Db@xxx
| 2 [[(rule1 ?d) [?d :District/region ":District.region/ne"]]
| [(rule1 ?d) [?d :District/region ":District.region/sw"]]]
|)""".stripMargin
// Social media in southern regions
m(Community.name.type_("twitter" or "facebook_page").Neighborhood.District.region_("sw" or "s" or "se")) -->
Model(List(
Atom("Community", "name", "String", 1, VarValue, None),
Atom("Community", "type_", "String", 1, Eq(List("twitter", "facebook_page")), Some(":Community.type/")),
Bond("Community", "neighborhood", "Neighborhood", 1),
Bond("Neighborhood", "district", "District", 1),
Atom("District", "region_", "String", 1, Eq(List("sw", "s", "se")), Some(":District.region/")))
) -->
Query(
Find(List(
Var("b"))),
In(List(), List(
Rule("rule1", List(Var("a")), List(
DataClause(ImplDS, Var("a"), KW("Community", "type"), Val(":Community.type/twitter"), Empty))),
Rule("rule1", List(Var("a")), List(
DataClause(ImplDS, Var("a"), KW("Community", "type"), Val(":Community.type/facebook_page"), Empty))),
Rule("rule2", List(Var("e")), List(
DataClause(ImplDS, Var("e"), KW("District", "region"), Val(":District.region/sw"), Empty))),
Rule("rule2", List(Var("e")), List(
DataClause(ImplDS, Var("e"), KW("District", "region"), Val(":District.region/s"), Empty))),
Rule("rule2", List(Var("e")), List(
DataClause(ImplDS, Var("e"), KW("District", "region"), Val(":District.region/se"), Empty)))), List(DS)),
Where(List(
DataClause(ImplDS, Var("a"), KW("Community", "name"), Var("b"), Empty),
RuleInvocation("rule1", List(Var("a"))),
DataClause(ImplDS, Var("a"), KW("Community", "neighborhood", "Neighborhood"), Var("d"), Empty),
DataClause(ImplDS, Var("d"), KW("Neighborhood", "district", "District"), Var("e"), Empty),
RuleInvocation("rule2", List(Var("e")))))
) -->
"""[:find ?b
| :in $ %
| :where [?a :Community/name ?b]
| (rule1 ?a)
| [?a :Community/neighborhood ?d]
| [?d :Neighborhood/district ?e]
| (rule2 ?e)]
|
|INPUTS:
|List(
| 1 datomic.db.Db@xxx
| 2 [[(rule1 ?a) [?a :Community/type ":Community.type/twitter"]]
| [(rule1 ?a) [?a :Community/type ":Community.type/facebook_page"]]
| [(rule2 ?e) [?e :District/region ":District.region/sw"]]
| [(rule2 ?e) [?e :District/region ":District.region/s"]]
| [(rule2 ?e) [?e :District/region ":District.region/se"]]]
|)""".stripMargin
m(Community.name.type_(?).Neighborhood.District.region_(?)) -->
Model(List(
Atom("Community", "name", "String", 1, VarValue, None),
Atom("Community", "type_", "String", 1, Qm, Some(":Community.type/")),
Bond("Community", "neighborhood", "Neighborhood", 1),
Bond("Neighborhood", "district", "District", 1),
Atom("District", "region_", "String", 1, Qm, Some(":District.region/")))
) -->
Query(
Find(List(
Var("b"))),
In(
List(
Placeholder(Var("a"), KW("Community", "type"), Var("c2"), Some(":Community.type/")),
Placeholder(Var("e"), KW("District", "region"), Var("f2"), Some(":District.region/"))),
List(),
List(DS)),
Where(List(
DataClause(ImplDS, Var("a"), KW("Community", "name"), Var("b"), Empty, NoBinding),
DataClause(ImplDS, Var("a"), KW("Community", "type"), Var("c"), Empty, NoBinding),
DataClause(ImplDS, Var("c"), KW("db", "ident"), Var("c1"), Empty, NoBinding),
Funct("name", Seq(Var("c1")), ScalarBinding(Var("c2"))),
DataClause(ImplDS, Var("a"), KW("Community", "neighborhood", "Neighborhood"), Var("d"), Empty, NoBinding),
DataClause(ImplDS, Var("d"), KW("Neighborhood", "district", "District"), Var("e"), Empty, NoBinding),
DataClause(ImplDS, Var("e"), KW("District", "region"), Var("f"), Empty, NoBinding),
DataClause(ImplDS, Var("f"), KW("db", "ident"), Var("f1"), Empty, NoBinding),
Funct("name", Seq(Var("f1")), ScalarBinding(Var("f2")))))
) -->
"""[:find ?b
| :in $ ?c2 ?f2
| :where [?a :Community/name ?b]
| [?a :Community/type ?c]
| [?c :db/ident ?c1]
| [(name ?c1) ?c2]
| [?a :Community/neighborhood ?d]
| [?d :Neighborhood/district ?e]
| [?e :District/region ?f]
| [?f :db/ident ?f1]
| [(name ?f1) ?f2]]""".stripMargin
m(Community.name.type_(?).Neighborhood.District.region_(?)).apply(
("twitter" or "facebook_page") and ("sw" or "s" or "se")
// or
// Seq("twitter", "facebook_page"), Seq("sw", "s", "se")
) -->
Model(List(
Atom("Community", "name", "String", 1, VarValue, None),
Atom("Community", "type_", "String", 1, Qm, Some(":Community.type/")),
Bond("Community", "neighborhood", "Neighborhood", 1),
Bond("Neighborhood", "district", "District", 1),
Atom("District", "region_", "String", 1, Qm, Some(":District.region/")))
) -->
Query(
Find(List(
Var("b"))),
In(
List(
InVar(CollectionBinding(Var("c")), Seq(Seq(":Community.type/twitter", ":Community.type/facebook_page"))),
InVar(CollectionBinding(Var("f")), Seq(Seq(":District.region/sw", ":District.region/s", ":District.region/se")))),
List(),
List(DS)),
Where(List(
DataClause(ImplDS, Var("a"), KW("Community", "name"), Var("b"), Empty, NoBinding),
DataClause(ImplDS, Var("a"), KW("Community", "type"), Var("c"), Empty, NoBinding),
DataClause(ImplDS, Var("a"), KW("Community", "neighborhood", "Neighborhood"), Var("d"), Empty, NoBinding),
DataClause(ImplDS, Var("d"), KW("Neighborhood", "district", "District"), Var("e"), Empty, NoBinding),
DataClause(ImplDS, Var("e"), KW("District", "region"), Var("f"), Empty, NoBinding)))
) -->
"""[:find ?b
| :in $ [?c ...] [?f ...]
| :where [?a :Community/name ?b]
| [?a :Community/type ?c]
| [?a :Community/neighborhood ?d]
| [?d :Neighborhood/district ?e]
| [?e :District/region ?f]]
|
|INPUTS:
|List(
| 1 datomic.db.Db@xxx
| 2 [:Community.type/twitter, :Community.type/facebook_page]
| 3 [:District.region/sw, :District.region/s, :District.region/se]
|)""".stripMargin
m(Community.name.type_(?).Neighborhood.District.region_(?)).apply(
("twitter" or "facebook_page") and ("sw" or "s" or "se")
// or
// Seq("twitter", "facebook_page"), Seq("sw", "s", "se")
) -->
Model(List(
Atom("Community", "name", "String", 1, VarValue, None),
Atom("Community", "type_", "String", 1, Qm, Some(":Community.type/")),
Bond("Community", "neighborhood", "Neighborhood", 1),
Bond("Neighborhood", "district", "District", 1),
Atom("District", "region_", "String", 1, Qm, Some(":District.region/")))
) -->
Query(
Find(List(
Var("b"))),
In(
List(
InVar(CollectionBinding(Var("c")), Seq(Seq(":Community.type/twitter", ":Community.type/facebook_page"))),
InVar(CollectionBinding(Var("f")), Seq(Seq(":District.region/sw", ":District.region/s", ":District.region/se")))),
List(),
List(DS)),
Where(List(
DataClause(ImplDS, Var("a"), KW("Community", "name"), Var("b"), Empty, NoBinding),
DataClause(ImplDS, Var("a"), KW("Community", "type"), Var("c"), Empty, NoBinding),
DataClause(ImplDS, Var("a"), KW("Community", "neighborhood", "Neighborhood"), Var("d"), Empty, NoBinding),
DataClause(ImplDS, Var("d"), KW("Neighborhood", "district", "District"), Var("e"), Empty, NoBinding),
DataClause(ImplDS, Var("e"), KW("District", "region"), Var("f"), Empty, NoBinding)))
) -->
"""[:find ?b
| :in $ [?c ...] [?f ...]
| :where [?a :Community/name ?b]
| [?a :Community/type ?c]
| [?a :Community/neighborhood ?d]
| [?d :Neighborhood/district ?e]
| [?e :District/region ?f]]
|
|INPUTS:
|List(
| 1 datomic.db.Db@xxx
| 2 [:Community.type/twitter, :Community.type/facebook_page]
| 3 [:District.region/sw, :District.region/s, :District.region/se]
|)""".stripMargin
}
"Working with time" >> {
m(Schema.txInstant) -->
Model(List(
Generic("Schema", "txInstant", "schema", NoValue))
) -->
Query(
Find(List(
Var("txInstant"))),
Where(List(
DataClause(ImplDS, Var("_"), KW("db.install", "attribute"), Var("id"), Var("tx"), NoBinding),
DataClause(ImplDS, Var("id"), KW("db", "ident"), Var("idIdent"), NoBinding, NoBinding),
Funct("namespace", Seq(Var("idIdent")), ScalarBinding(Var("nsFull"))),
Funct(".matches ^String", Seq(Var("nsFull"), Val("(db|db.alter|db.excise|db.install|db.part|db.sys|fressian)")), ScalarBinding(Var("sys"))),
Funct("=", Seq(Var("sys"), Val(false)), NoBinding),
Funct("molecule.util.fns/partNs", Seq(Var("nsFull")), ScalarBinding(Var("partNs"))),
Funct("first", Seq(Var("partNs")), ScalarBinding(Var("part"))),
Funct("second", Seq(Var("partNs")), ScalarBinding(Var("ns"))),
Funct("molecule.util.fns/live", Seq(Var("nsFull")), NoBinding),
DataClause(ImplDS, Var("tx"), KW("db", "txInstant"), Var("txInstant"), Empty, NoBinding)))
) -->
"""[:find ?txInstant
| :where [_ :db.install/attribute ?id ?tx]
| [?id :db/ident ?idIdent]
| [(namespace ?idIdent) ?nsFull]
| [(.matches ^String ?nsFull "(db|db.alter|db.excise|db.install|db.part|db.sys|fressian)") ?sys]
| [(= ?sys false)]
| [(molecule.util.fns/partNs ?nsFull) ?partNs]
| [(first ?partNs) ?part]
| [(second ?partNs) ?ns]
| [(molecule.util.fns/live ?nsFull)]
| [?tx :db/txInstant ?txInstant]]""".stripMargin
}
"Manipulating data - insert" >> {
/** Insert data into molecule and save ***********************************************/
testInsertMolecule(
Community
.name("AAA")
.url("myUrl")
.`type`("twitter")
.orgtype("personal")
.category("my", "favorites")
.Neighborhood.name("myNeighborhood")
.District.name("myDistrict").region("nw")
) -->
Model(List(
Atom("Community", "name", "String", 1, Eq(List("AAA")), None),
Atom("Community", "url", "String", 1, Eq(List("myUrl")), None),
Atom("Community", "type", "String", 1, Eq(List("twitter")), Some(":Community.type/")),
Atom("Community", "orgtype", "String", 1, Eq(List("personal")), Some(":Community.orgtype/")),
Atom("Community", "category", "String", 2, Eq(List("my", "favorites")), None),
Bond("Community", "neighborhood", "Neighborhood", 1),
Atom("Neighborhood", "name", "String", 1, Eq(List("myNeighborhood")), None, List()),
Bond("Neighborhood", "district", "District", 1),
Atom("District", "name", "String", 1, Eq(List("myDistrict")), None),
Atom("District", "region", "String", 1, Eq(List("nw")), Some(":District.region/")))
) -->
// Some things to notice:
// - Enum values are prefixed with their namespace ("nw" becomes ":District.region/nw")
// - Multiple values of many-cardinality attributes each get their own statement ("my" + "favorites")
//
// operation temp id attribute value
"""List(
| List(:db/add, #db/id[:db.part/user -1000001], :Community/name , AAA ),
| List(:db/add, #db/id[:db.part/user -1000001], :Community/url , myUrl ),
| List(:db/add, #db/id[:db.part/user -1000001], :Community/type , :Community.type/twitter ),
| List(:db/add, #db/id[:db.part/user -1000001], :Community/orgtype , :Community.orgtype/personal ),
| List(:db/add, #db/id[:db.part/user -1000001], :Community/category , my ),
| List(:db/add, #db/id[:db.part/user -1000001], :Community/category , favorites ),
| List(:db/add, #db/id[:db.part/user -1000001], :Community/neighborhood, #db/id[:db.part/user -1000002]),
| List(:db/add, #db/id[:db.part/user -1000002], :Neighborhood/name , myNeighborhood ),
| List(:db/add, #db/id[:db.part/user -1000002], :Neighborhood/district , #db/id[:db.part/user -1000003]),
| List(:db/add, #db/id[:db.part/user -1000003], :District/name , myDistrict ),
| List(:db/add, #db/id[:db.part/user -1000003], :District/region , :District.region/nw )
|)""".stripMargin
/** Use molecule as template to insert matching data sets ********************************************/
m(Community.name.url.`type`.orgtype.category.Neighborhood.name.District.name.region) -->
Model(List(
Atom("Community", "name", "String", 1, VarValue, None),
Atom("Community", "url", "String", 1, VarValue, None),
Atom("Community", "type", "String", 1, EnumVal, Some(":Community.type/")),
Atom("Community", "orgtype", "String", 1, EnumVal, Some(":Community.orgtype/")),
Atom("Community", "category", "String", 2, VarValue, None),
Bond("Community", "neighborhood", "Neighborhood", 1),
Atom("Neighborhood", "name", "String", 1, VarValue, None),
Bond("Neighborhood", "district", "District", 1),
Atom("District", "name", "String", 1, VarValue, None),
Atom("District", "region", "String", 1, EnumVal, Some(":District.region/")))
) -->
List(
List("DDD Blogging Georgetown", "http://www.blogginggeorgetown.com/", "blog", "commercial", Set("DD cat 1", "DD cat 2"), "DD Georgetown", "Greater Duwamish", "s"),
List("DDD Interbay District Blog", "http://interbayneighborhood.neighborlogs.com/", "blog", "community", Set("DD cat 3"), "DD Interbay", "Magnolia/Queen Anne", "w")
) -->
// Semantically identical to the previous transaction
"""List(
| List(:db/add, #db/id[:db.part/user -1000001], :Community/name , DDD Blogging Georgetown ),
| List(:db/add, #db/id[:db.part/user -1000001], :Community/url , http://www.blogginggeorgetown.com/ ),
| List(:db/add, #db/id[:db.part/user -1000001], :Community/type , :Community.type/blog ),
| List(:db/add, #db/id[:db.part/user -1000001], :Community/orgtype , :Community.orgtype/commercial ),
| List(:db/add, #db/id[:db.part/user -1000001], :Community/category , DD cat 1 ),
| List(:db/add, #db/id[:db.part/user -1000001], :Community/category , DD cat 2 ),
| List(:db/add, #db/id[:db.part/user -1000001], :Community/neighborhood, #db/id[:db.part/user -1000002] ),
| List(:db/add, #db/id[:db.part/user -1000002], :Neighborhood/name , DD Georgetown ),
| List(:db/add, #db/id[:db.part/user -1000002], :Neighborhood/district , #db/id[:db.part/user -1000003] ),
| List(:db/add, #db/id[:db.part/user -1000003], :District/name , Greater Duwamish ),
| List(:db/add, #db/id[:db.part/user -1000003], :District/region , :District.region/s ),
| List(:db/add, #db/id[:db.part/user -1000004], :Community/name , DDD Interbay District Blog ),
| List(:db/add, #db/id[:db.part/user -1000004], :Community/url , http://interbayneighborhood.neighborlogs.com/),
| List(:db/add, #db/id[:db.part/user -1000004], :Community/type , :Community.type/blog ),
| List(:db/add, #db/id[:db.part/user -1000004], :Community/orgtype , :Community.orgtype/community ),
| List(:db/add, #db/id[:db.part/user -1000004], :Community/category , DD cat 3 ),
| List(:db/add, #db/id[:db.part/user -1000004], :Community/neighborhood, #db/id[:db.part/user -1000005] ),
| List(:db/add, #db/id[:db.part/user -1000005], :Neighborhood/name , DD Interbay ),
| List(:db/add, #db/id[:db.part/user -1000005], :Neighborhood/district , #db/id[:db.part/user -1000006] ),
| List(:db/add, #db/id[:db.part/user -1000006], :District/name , Magnolia/Queen Anne ),
| List(:db/add, #db/id[:db.part/user -1000006], :District/region , :District.region/w )
|)""".stripMargin
}
"Manipulating data - update/retract" >> {
val belltownId = Community.e.name_("belltown").get.head
// One-cardinality attributes ..............................
// Assert new value
testUpdateMolecule(
Community(belltownId).name("belltown 2").url("url 2")
) -->
Model(List(
Generic("Community", "e_", "datom", Eq(List(17592186045886L))),
Atom("Community", "name", "String", 1, Eq(List("belltown 2")), None),
Atom("Community", "url", "String", 1, Eq(List("url 2")), None))
) -->
"""List(
| List(:db/add, 17592186045886 , :Community/name, belltown 2),
| List(:db/add, 17592186045886 , :Community/url , url 2 )
|)""".stripMargin
// Many-cardinality attributes ............................
// Replace category
// Retracts current value an asserts new value
testUpdateMolecule(
Community(belltownId).category.replace("news" -> "Cool news")
) -->
Model(List(
Generic("Community", "e_", "datom", Eq(List(17592186045886L))),
Atom("Community", "category", "String", 2, ReplaceValue(Seq("news" -> "Cool news")), None))
) -->
"""List(
| List(:db/retract, 17592186045886 , :Community/category, news ),
| List(:db/add , 17592186045886 , :Community/category, Cool news)
|)""".stripMargin
// Replace multiple categories
testUpdateMolecule(
Community(belltownId).category.replace(
"Cool news" -> "Super cool news",
"events" -> "Super cool events"
)
) -->
Model(List(
Generic("Community", "e_", "datom", Eq(List(17592186045886L))),
Atom("Community", "category", "String", 2, ReplaceValue(Seq(
"Cool news" -> "Super cool news",
"events" -> "Super cool events")), None))
) -->
"""List(
| List(:db/retract, 17592186045886 , :Community/category, Cool news ),
| List(:db/add , 17592186045886 , :Community/category, Super cool news ),
| List(:db/retract, 17592186045886 , :Community/category, events ),
| List(:db/add , 17592186045886 , :Community/category, Super cool events)
|)""".stripMargin
// Add a category
testUpdateMolecule(
Community(belltownId).category.assert("extra category")
) -->
Model(List(
Generic("Community", "e_", "datom", Eq(List(17592186045886L))),
Atom("Community", "category", "String", 2, AssertValue(List("extra category")), None))
) -->
"""List(
| List(:db/add, 17592186045886 , :Community/category, extra category)
|)""".stripMargin
// Remove a category
testUpdateMolecule(
Community(belltownId).category.retract("Super cool events")
) -->
Model(List(
Generic("Community", "e_", "datom", Eq(List(17592186045886L))),
Atom("Community", "category", "String", 2, RetractValue(List("Super cool events")), None))
) -->
"""List(
| List(:db/retract, 17592186045886 , :Community/category, Super cool events)
|)""".stripMargin
// Mixing updates and deletes..........................
// Applying nothing (empty parenthesises) finds and retract all values of an attribute
// Note how the name is updated at the same time
testUpdateMolecule(
Community(belltownId).name("belltown 3").url().category()
) -->
Model(List(
Generic("Community", "e_", "datom", Eq(List(17592186045886L))),
Atom("Community", "name", "String", 1, Eq(List("belltown 3")), None),
Atom("Community", "url", "String", 1, Eq(List()), None),
Atom("Community", "category", "String", 2, Eq(List()), None))
) -->
"""List(
| List(:db/add , 17592186045886 , :Community/name , belltown 3 ),
| List(:db/retract, 17592186045886 , :Community/url , http://www.belltownpeople.com/),
| List(:db/retract, 17592186045886 , :Community/category, news ),
| List(:db/retract, 17592186045886 , :Community/category, events )
|)""".stripMargin
}
}
You can’t perform that action at this time.