Reputation: 5045
Any idea how to do a conditional drop in Slick 3.0, to prevent An exception or error caused a run to abort: Unknown table 'MY_TABLE'
if for some reason it doesn't exist?
def clear = {
val operations = DBIO.seq(
myTable.schema.drop,
// other table definitions
...
)
db.run(operations)
}
Upvotes: 0
Views: 1982
Reputation: 143
I am currently using the Slick framework in its 3.2.0 version. The solution I am giving may apply to earlier version of the framework however but I did not verify this point.
If the only problem is to drop the table if it exists without throwing exception you can use the combinators of the Actions for this.
I have a series of test for which I run the create/populate/drop statement for each test on H2 in memory database.
I suppose you have two tables Canal
and SubCanal
(SubCanal has a foreign key on Canal so that you would like to drop it first if it exists) for wich you already have declared TableQuery
variables such as:
lazy val canals = TableQuery[CanalTable]
lazy val subcanals = TableQuery[SubCanalTable]
// we don't put SubCanals to check if no exeption is produced and then
// add it for further testing.
lazy val ddl = canals.schema // ++ subcanals.schema
...I provided helper methods as follows:
def create: DBIO[Unit] = ddl.create
def drop: DBIO[Unit] = ddl.drop
def popCanal = canals ++= Seq(
Canal("Chat"),
Canal("Web"),
Canal("Mail"))
The above is just creating the action but what is cool is that Slick will attempt to drop the SubCanal
table and the Canal
table but will encapsulate the exception in the Try[...]
. So this will run smoothly:
val db = Database.forConfig("yourBaseConfig")
val res = db.run(drop)
And this will run also:
val db = Database.forConfig("yourBaseConfig")
val res1 = db.run(
create >>
popCanal >>
canals.result
)
.... some interesting computation ...
val res2 = db.run(drop)
Note: The SubCanal scheme is still commented so has never been performed for the moment and the drop is however applied and fail to this table but does not raise the exeption.
More on combining actions (combinator):
Upvotes: 0
Reputation:
I did this:
val personQuery = TableQuery[PersonTable]
val addressQuery = TableQuery[AddressTable]
...
val setupAction = DBIO.seq(
sqlu"SET FOREIGN_KEY_CHECKS = 0",
sqlu"DROP TABLE IF EXISTS #${personQuery.baseTableRow.tableName}",
sqlu"DROP TABLE IF EXISTS #${addressQuery.baseTableRow.tableName}",
sqlu"SET FOREIGN_KEY_CHECKS = 1",
)
val setupFuture = db.run(setupAction)
Note how you need to use #${} not ${} otherwise slick will fire off something like:
DROP TABLE IF EXISTS 'PERSON'
Which won't work
Upvotes: 0
Reputation: 15690
I went down the MTable route, but at least in Postgres it's a big hassle.
Try
def qDropSchema = sqlu"""drop table if exists your-table-name;""";
Watch out for case-sensitivity issues with the table name. I ran into odd problems with the postgres there - don't know about mysql.
Upvotes: 2
Reputation: 7288
Let me try to answer your question, I think you can first check the availability of the table using MTable
then drop it if it exists. More or less like below:
import scala.slick.jdbc.meta._
if (MTable.getTables("table_name").list().isEmpty) {
//do something here..
}
Upvotes: 0