Exporting Database Schema
The DDLUnit class provides API for creating and dropping database schema. It features arranging database objects in correct order (preliminary auxiliary objects, tables, constraints, auxiliary database objects) and configurable logging.
|
class DDLUnit {
protected var _schemata: Seq[Schema] = Nil
def schemata = _schemata
protected var _tables: Seq[Table[_, _]] = Nil
def tables = _tables
protected var _views: Seq[View[_, _]] = Nil
def views = _views
protected var _constraints: Seq[Constraint] = Nil
def constraints = _constraints
protected var _preAux: Seq[SchemaObject] = Nil
def preAux = _preAux
protected var _postAux: Seq[SchemaObject] = Nil
def postAux = _postAux
protected var _msgs: Seq[Msg] = Nil
def messages = _msgs
def msgsArray: Array[Msg] = messages.toArray
def this(objects: SchemaObject*) = {
this()
add(objects: _*)
}
def resetMsgs(): this.type = {
_msgs = Nil
return this
}
def clear() = {
_schemata = Nil
_tables = Nil
_views = Nil
_constraints = Nil
_preAux = Nil
_postAux = Nil
resetMsgs()
}
def add(objects: SchemaObject*): this.type = {
objects.foreach(addObject(_))
return this
}
def addObject(obj: SchemaObject): this.type = {
def processRelation(r: Relation[_, _]) = {
addObject(r.schema)
r.preAux.foreach(o =>
if (!_preAux.contains(o)) _preAux ++= List(o))
r.postAux.foreach(o => addObject(o))
}
obj match {
case t: Table[_, _] => if (!_tables.contains(t)) {
_tables ++= List(t)
t.constraints.foreach(c => addObject(c))
t.indexes.foreach(i => addObject(i))
processRelation(t)
}
case v: View[_, _] => if (!_views.contains(v)) {
_views ++= List(v)
processRelation(v)
}
case c: Constraint => if (!_constraints.contains(c))
_constraints ++= List(c)
case s: Schema => if (!_schemata.contains(s))
_schemata ++= List(s)
case o => if (!_postAux.contains(o))
_postAux ++= List(o)
}
return this
}
protected def dropObjects(objects: Seq[SchemaObject]): Unit =
for (o <- objects.reverse) tx.execute (o.sqlDrop) { st =>
st.executeUpdate
_msgs ++= List(new Msg(
"orm.ddl.info",
"status" -> ("DROP " + o.objectName + ": OK"),
"sql" -> o.sqlDrop))
} { e =>
_msgs ++= List(new Msg(
"orm.ddl.info",
"status" -> ("DROP " + o.objectName + ": " + e.getMessage),
"sql" -> o.sqlDrop,
"error" -> e.getMessage))
}
protected def createObjects(objects: Seq[SchemaObject]): Unit =
for (o <- objects) tx.execute(o.sqlCreate) { st =>
st.executeUpdate
_msgs ++= List(new Msg(
"orm.ddl.info",
"status" -> ("CREATE " + o.objectName + ": OK"),
"sql" -> o.sqlCreate))
} { e =>
_msgs ++= List(new Msg(
"orm.ddl.error",
"status" -> ("CREATE " + o.objectName + ": " + e.getMessage),
"sql" -> o.sqlCreate,
"error" -> e.getMessage))
}
def DROP(): this.type = {
resetMsgs()
_drop()
return this
}
def _drop(): Unit = tx.execute { conn =>
// We will commit every successfull statement.
val autoCommit = conn.getAutoCommit
conn.setAutoCommit(true)
// Execute a script.
dropObjects(postAux)
dropObjects(views)
if (dialect.supportsDropConstraints_?)
dropObjects(constraints)
dropObjects(tables)
dropObjects(preAux)
if (dialect.supportsSchema_?)
dropObjects(schemata)
// Restore auto-commit.
conn.setAutoCommit(autoCommit)
} { throw _ }
def CREATE(): this.type = {
resetMsgs()
_create()
return this
}
def _create(): Unit = tx.execute { conn =>
// We will commit every successfull statement.
val autoCommit = conn.getAutoCommit
conn.setAutoCommit(true)
// Execute a script.
if (dialect.supportsSchema_?)
createObjects(schemata)
createObjects(preAux)
createObjects(tables)
createObjects(constraints)
createObjects(views)
createObjects(postAux)
// Restore auto-commit.
conn.setAutoCommit(autoCommit)
} { throw _ }
def DROP_CREATE(): this.type = {
resetMsgs()
_drop()
_create()
return this
}
def close(): Unit = {
tx.close()
connectionProvider.close()
}
override def toString: String = {
var result = "Circumflex DDL Unit: "
if (messages.size == 0) {
val objectsCount = (schemata.size +
tables.size +
constraints.size +
views.size +
preAux.size +
postAux.size)
result += objectsCount + " objects in queue."
} else {
val infoCount = messages.filter(_.key == "orm.ddl.info").size
val errorsCount = messages.filter(_.key == "orm.ddl.error").size
result += infoCount + " successful statements, " + errorsCount + " errors."
}
return result
}
}
|