forked from squeryl/squeryl
/
Issue69.scala
146 lines (130 loc) · 4.17 KB
/
Issue69.scala
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
package org.squeryl.tests.issues
import org.specs._
import java.sql.{Connection, DriverManager}
import org.squeryl.{Session, SessionFactory}
import org.squeryl.adapters.H2Adapter
import org.squeryl.PrimitiveTypeMode
class Issue69 extends Specification with TestConnection {
def createSchema() {
PrimitiveTypeMode.using(session) {
try {
Graph.create
} catch {
case ex: Throwable =>
System.err.println(ex.getClass().getSimpleName() + ": " + ex.getMessage())
}
}
}
"Squeryl" should {
doBefore {
import PrimitiveTypeMode._
createSchema()
using(session) {
val root = new Node("Root")
transaction {
Graph.nodes.insert(root)
}
val adam = new Node("Adam")
transaction {
Graph.nodes.insert(adam)
root.children.associate(adam)
}
}
}
doAfter {
PrimitiveTypeMode.using(session) {
Graph.drop
}
}
"support (optional) foreign keys." in {
import PrimitiveTypeMode._
using(session) {
val getRoot = from(Graph.nodes)(n => where(n.name === "Root") select(n))
val root = getRoot.headOption.getOrElse(fail("Root not found"))
root.parent must beEmpty
val getAdam = from(Graph.nodes)(n => where(n.name === "Adam") select(n))
val adam = getAdam.headOption.getOrElse(fail("Adam not found"))
adam.parent must beEmpty.not
adam.parent.head mustEqual root
root.children must contain(adam)
}
}
"allow foreign keys to be set to None." in {
import PrimitiveTypeMode._
using(session) {
val (adam, parent) = getAdamAndHisParent
adam.parent must beEmpty.not // in one moment it still has a parent
transaction {
adam.parentId = None
Graph.nodes.update(adam)
}
adam.parent must beEmpty // and in the next ... no more!
}
}
"allow deletion of no longer referenced rows." in {
import PrimitiveTypeMode._
using(session) {
val (adam, parent) = getAdamAndHisParent
def illegalAction = {
transaction {
adam.parent.delete
}
}
illegalAction must throwAn[Exception] // still referenced, do not allow deletion
transaction {
adam.parentId = None
Graph.nodes.update(adam)
}
val getNodes = from(Graph.nodes)(select(_))
getNodes must haveSize(2)
transaction {
Graph.nodes.deleteWhere(n => n.name === "Root")
}
getNodes must haveSize(1) // since no longer referenced, deletion should be allowed
}
}
def getAdamAndHisParent: (Node, Node) = {
import PrimitiveTypeMode._
val getAdam = from(Graph.nodes)(n => where(n.name === "Adam") select(n))
val adam = getAdam.headOption.getOrElse(fail("Could not find Adam!"))
val parent = adam.parent.headOption.getOrElse(fail("Adam has no parent!"))
(adam, parent)
}
"let me see ..." in {
import PrimitiveTypeMode._
using(session) {
val nodes = from(Graph.nodes)(select(_)).toList
println("\tID\tNAME\tPARENT_ID")
nodes.foreach { node =>
print("\t" + node.id + "\t" + node.name + "\t")
val parent = node.parent.headOption
if (parent.isDefined) println(parent.get.id)
else println("-")
}
nodes must haveSize(2)
println("\nSchema:\n")
Graph.printDdl
}
}
}
}
import org.squeryl.{Schema, Table, KeyedEntity}
import org.squeryl.dsl.{OneToMany, ManyToOne}
import org.squeryl.PrimitiveTypeMode._
class Node(
val name: String,
val id: Long = 0,
var parentId: Option[Long] = None
) extends KeyedEntity[Long] {
def this() = this("", 0, Some(0L))
def parent: ManyToOne[Node] = Graph.parentChildRelation.right(this)
def children: OneToMany[Node] = Graph.parentChildRelation.left(this)
}
object Graph extends Schema {
val nodes = table[Node]
val parentChildRelation = {
val rel = oneToManyRelation(nodes, nodes)
rel.via((parent, child) => parent.id === child.parentId)
}
override def drop = super.drop
}