Permalink
Browse files

Add Slick Extensions drivers

These are the drivers for DB2, Oracle and SQL Server from Slick
Extensions 3.1.0, integrated into the main project and updated to
work on master for 3.2.

See http://slick.typesafe.com/news/2016/02/01/slick-extensions-licensing-change.html for details.
  • Loading branch information...
1 parent 25ca1db commit 81b6919bb719c20933779e9cb2cdadf1bbc6ea8a @szeiger szeiger committed Feb 2, 2016
View
@@ -19,18 +19,13 @@ The following database systems are directly supported for type-safe queries:
- MySQL
- PostgreSQL
- SQLite
-
-Support for Oracle, IBM DB2 and Microsoft SQL Server is available for
-production use by
-[Typesafe subscribers](http://www.typesafe.com/products/typesafe-subscription)
-(free for evaluation and development) in the Slick Extensions package.
-See the Slick [manual](http://slick.typesafe.com/docs/) for details.
+- Oracle 11g
+- IBM DB2 LUW 10
+- Microsoft SQL Server 2008
Accessing other database systems is possible, with a reduced feature set.
The [manual and scaladocs](http://slick.typesafe.com/docs/) for Slick can be
found on the [Slick web site](http://slick.typesafe.com/).
-There is some older documentation (which may still apply to some extent to
-Slick) in the [ScalaQuery Wiki](https://github.com/szeiger/scala-query/wiki).
Licensing conditions (BSD-style) can be found in LICENSE.txt.
View
@@ -13,7 +13,6 @@ import com.typesafe.sbt.sdlc.Plugin._
object SlickBuild extends Build {
val slickVersion = "3.2.0-SNAPSHOT"
- val slickExtensionsVersion = slickVersion // Slick extensions version for links in the manual
val binaryCompatSlickVersion = "3.2.0" // Slick base version for binary compatibility checks
val scalaVersions = Seq("2.11.7", "2.12.0-M2")
@@ -42,7 +41,8 @@ object SlickBuild extends Build {
"org.apache.derby" % "derby" % "10.9.1.0",
"org.hsqldb" % "hsqldb" % "2.2.8",
"postgresql" % "postgresql" % "9.1-901.jdbc4",
- "mysql" % "mysql-connector-java" % "5.1.23"
+ "mysql" % "mysql-connector-java" % "5.1.23",
+ "net.sourceforge.jtds" % "jtds" % "1.3.1"
)
val paxExamVersion = "4.6.0"
val paxExam = Seq(
@@ -195,8 +195,7 @@ object SlickBuild extends Build {
)),
(sphinxEnv in Sphinx) := (sphinxEnv in Sphinx).value +
("version" -> version.value.replaceFirst("""(\d*.\d*).*""", """$1""")) +
- ("release" -> version.value) +
- ("slick_extensions_version" -> slickExtensionsVersion),
+ ("release" -> version.value),
(sphinxProperties in Sphinx) := Map.empty,
makeSite <<= makeSite dependsOn (buildCapabilitiesTable in slickTestkitProject),
site.addMappingsToSiteDir(mappings in packageDoc in Compile in slickProject, "api"),
@@ -0,0 +1,5 @@
+CREATE TABLE "PERSON"(
+ "ID" NUMBER(11,0) NOT NULL ENABLE,
+ "PERSON_TYPE" CHAR(1 BYTE) DEFAULT 'Y' NOT NULL ENABLE,
+ CONSTRAINT "PERSON_PK" PRIMARY KEY ("ID")
+);
@@ -104,7 +104,11 @@ val SimpleA = CustomTyping.SimpleA
""".stripMargin
},
new UUIDConfig("Postgres2", StandardTestDBs.Postgres, "Postgres", Seq("/dbs/uuid.sql")),
- new Config("EmptyDB", StandardTestDBs.H2Mem, "H2Mem", Nil)
+ new Config("EmptyDB", StandardTestDBs.H2Mem, "H2Mem", Nil),
+ new Config("Oracle1", StandardTestDBs.Oracle, "Oracle", Seq("/dbs/oracle1.sql")) {
+ override def useSingleLineStatements = true
+ override def testCode = "DBIO.successful(())"
+ }
)
//Unified UUID config
@@ -4,7 +4,7 @@
testkit {
# Use only the following DBs (or use all if not set)
- #testDBs = [h2mem, h2rownum, h2disk, hsqldbmem, hsqldbdisk, sqlitemem, sqlitedisk, derbymem, derbydisk, postgres, mysql, access, heap]
+ #testDBs = [h2mem, h2rownum, h2disk, hsqldbmem, hsqldbdisk, sqlitemem, sqlitedisk, derbymem, derbydisk, postgres, mysql, oracle, db2, sqlserver-jtds, sqlserver-jdbc, access, heap]
testDBs = null
# Store database files in this path (ignored by MySQL and in-memory databases)
@@ -80,7 +80,7 @@ defaults {
}
###################################################################################################
-# Test rest of this file consists of defaults for the standard database systems which
+# The rest of this file consists of defaults for the standard database systems which
# are supported by TestKit.
###################################################################################################
@@ -109,3 +109,66 @@ mysql {
drop = DROP DATABASE IF EXISTS ${testDB}
driver = com.mysql.jdbc.Driver
}
+
+oracle {
+ baseURL = "jdbc:oracle:thin:@//localhost:1521/xe"
+ testConn {
+ url = ${baseURL}
+ user = SLICK_TEST
+ }
+ adminConn {
+ url = ${baseURL}
+ user = SYSTEM
+ }
+ driver = "oracle.jdbc.OracleDriver"
+ create = [
+ create tablespace ${testConn.user}"_TS datafile '"${testkit.absTestDir}"/"${testConn.user}_${testDB}"_TS' size 2M autoextend on"
+ create user ${testConn.user}" identified by \""${testConn.password}"\" default tablespace "${testConn.user}_TS
+ "grant connect, resource, select any dictionary, select_catalog_role, analyze any, analyze any dictionary to "${testConn.user}
+ ]
+ drop = [
+ "begin execute immediate 'drop user "${testConn.user}" cascade'; exception when others then if sqlcode != -1918 then raise; end if; end;"
+ "begin execute immediate 'drop tablespace "${testConn.user}"_TS including contents and datafiles cascade constraints'; exception when others then if sqlcode != -959 then raise; end if; end;"
+ ]
+ testClasses = ${testkit.testClasses} [
+ ${testkit.testPackage}.OracleExtraTests
+ ]
+}
+
+db2 {
+ testDB = SLICKTST
+ schema = SLICK_TEST
+ baseURL = "jdbc:db2://localhost:50000/"${testDB}":currentSchema="${schema}";"
+ testConn.url = ${baseURL}
+ adminConn.url = ${baseURL}
+ user = db2admin
+ driver = "com.ibm.db2.jcc.DB2Driver"
+ driverJar = "file:///C:/Program%20Files/IBM/SQLLIB/java/db2jcc4.jar"
+}
+
+sqlserver-jtds {
+ baseURL = "jdbc:jtds:sqlserver://localhost/"
+ domain = local
+ urlSuffix = ";progName=Slick_TestKit;namedPipe=true;domain="${domain}
+ testConn.url = ${baseURL}${testDB}${urlSuffix}
+ adminConn.url = ${baseURL}${adminDB}${urlSuffix}
+ user = dbo
+ adminDB = master
+ defaultSchema = dbo
+ create = "CREATE DATABASE \""${testDB}"\" ON (NAME = '[DB]_dat', FILENAME = '"${testkit.absTestDir}"\\\\"${testDB}".mdf') LOG ON (NAME = '"${testDB}"_log', FILENAME = \""${testkit.absTestDir}"\\\\"${testDB}".ldf\")"
+ drop = "IF EXISTS(SELECT name FROM sys.databases WHERE name = '"${testDB}"') DROP DATABASE \""${testDB}"\""
+ driver = net.sourceforge.jtds.jdbc.Driver
+}
+
+sqlserver-sqljdbc {
+ baseURL = "jdbc:sqlserver://localhost;database="
+ urlSuffix = ";applicationName=Slick_TestKit"
+ testConn.url = ${baseURL}${testDB}${urlSuffix}
+ adminConn.url = ${baseURL}${adminDB}${urlSuffix}
+ user = sa
+ adminDB = master
+ defaultSchema = dbo
+ create = "CREATE DATABASE \""${testDB}"\" ON (NAME = '[DB]_dat', FILENAME = '"${testkit.absTestDir}"\\\\"${testDB}".mdf') LOG ON (NAME = '"${testDB}"_log', FILENAME = \""${testkit.absTestDir}"\\\\"${testDB}".ldf\")"
+ drop = "IF EXISTS(SELECT name FROM sys.databases WHERE name = '"${testDB}"') DROP DATABASE \""${testDB}"\""
+ driver = com.microsoft.sqlserver.jdbc.SQLServerDriver
+}
@@ -0,0 +1,51 @@
+package com.typesafe.slick.testkit.tests
+
+import com.typesafe.slick.testkit.util.{AsyncTest, JdbcTestDB}
+import slick.jdbc.OracleProfile
+
+class OracleExtraTests extends AsyncTest[JdbcTestDB] {
+ lazy val oracleProfile = tdb.profile.asInstanceOf[OracleProfile]
+ import oracleProfile.api._
+
+ def testBlobCompare = {
+ class A(tag: Tag) extends Table[(Int, Option[Array[Byte]])](tag, "a") {
+ def id = column[Int]("id")
+ def a = column[Option[Array[Byte]]]("a")
+ def * = (id, a)
+ }
+ val as = TableQuery[A]
+
+ DBIO.seq(
+ as.schema.create,
+ as += (1, Some(Array[Byte](1, 2, 3))),
+ as.filter(_ => LiteralColumn[Option[Int]](None).isDefined).map(_.id).result.map(_ shouldBe Nil),
+ as.filter(_ => LiteralColumn[Option[Int]](None).bind.isDefined).map(_.id).result.map(_ shouldBe Nil),
+ as.filter(_.a.isEmpty).map(_.id).result.map(_ shouldBe Nil),
+ as.filter(_.a === (Some(Array[Byte](1, 2, 3)): Option[Array[Byte]])).map(_.id).result.map(_ shouldBe Seq(1)),
+ as.filter(_.a === (None: Option[Array[Byte]])).map(_.id).result.map(_ shouldBe Nil),
+ as.filter(_.a === (Some(Array[Byte](1, 2, 3)): Option[Array[Byte]]).bind).map(_.id).result.map(_ shouldBe Seq(1)),
+ as.filter(_.a === (None: Option[Array[Byte]]).bind).map(_.id).result.map(_ shouldBe Nil),
+ as.filter(_ => LiteralColumn[Option[Int]](None) === (None: Option[Int])).map(_.id).result.map(_ shouldBe Nil)
+ )
+ }
+
+ def testSequenceAndTriggerName = {
+ class A(tag: Tag) extends Table[(Int, Int)](tag, "A_SEQTRG") {
+ def id = column[Int]("ID", O.PrimaryKey, O.AutoInc, O.AutoIncSequenceName("SEQ_SEQTRG"), O.AutoIncTriggerName("TRG_SEQTRG"))
+ def a = column[Int]("A")
+ def * = (id, a)
+ }
+ val as = TableQuery[A]
+
+ //as.schema.createStatements.foreach(println)
+ as.schema.createStatements.should(_.find(_.contains("sequence \"SEQ_SEQTRG\"")).isDefined)
+ as.schema.createStatements.should(_.find(_.contains("trigger \"TRG_SEQTRG\"")).isDefined)
+
+ DBIO.seq(
+ as.schema.create,
+ as.map(_.a) ++= Seq(1, 2, 3),
+ as.to[Set].result.map(_ shouldBe Set((1,1), (2,2), (3,3))),
+ as.schema.drop
+ )
+ }
+}
@@ -17,12 +17,15 @@ object BuildCapabilitiesTable extends App {
}
val profileNames = if(args.length > 1) args(1).split(",") else Array(
+ "slick.jdbc.DB2Profile",
"slick.jdbc.DerbyProfile",
"slick.jdbc.H2Profile",
"slick.jdbc.HsqldbProfile",
"slick.jdbc.MySQLProfile",
+ "slick.jdbc.OracleProfile",
"slick.jdbc.PostgresProfile",
- "slick.jdbc.SQLiteProfile"
+ "slick.jdbc.SQLiteProfile",
+ "slick.jdbc.SQLServerProfile"
)
val profiles = profileNames.map { n =>
@@ -5,8 +5,9 @@ import java.util.logging.{Level, Logger}
import java.sql.SQLException
import slick.compiler.Phase
import slick.dbio._
+import slick.driver.JdbcProfile
import slick.memory.MemoryProfile
-import slick.jdbc.{SimpleJdbcAction, ResultSetAction, H2Profile, HsqldbProfile, MySQLProfile, DerbyProfile, PostgresProfile, SQLiteProfile}
+import slick.jdbc._
import slick.jdbc.GetResult._
import slick.jdbc.meta.MTable
import org.junit.Assert
@@ -139,6 +140,92 @@ object StandardTestDBs {
}
}
}
+
+ lazy val DB2 = new ExternalJdbcTestDB("db2") {
+ val profile = DB2Profile
+ import profile.api.actionBasedSQLInterpolation
+
+ override def canGetLocalTables = false
+
+ lazy val schema = config.getString("schema")
+
+ def dropSchema: DBIO[Unit] = {
+ import ExecutionContext.Implicits.global
+ for {
+ schema <- sql"select schemaname from syscat.schemata where schemaname = '#$schema'".as[String].headOption
+ _ <- if(schema.isDefined) {
+ println(s"[Dropping DB2 schema '$schema']")
+ sqlu"call sysproc.admin_drop_schema($schema, null, ${"ERRORSCHEMA"}, ${"ERRORTABLE"})"
+ } else DBIO.successful(())
+ } yield ()
+ }
+
+ override def cleanUpBefore(): Unit = {
+ import ExecutionContext.Implicits.global
+ await(databaseFor("testConn").run(for {
+ _ <- dropSchema
+ _ = println(s"[Creating DB2 schema '$schema']")
+ _ <- sqlu"create schema #$schema"
+ } yield ()))
+ }
+
+ override def cleanUpAfter(): Unit =
+ await(databaseFor("adminConn").run(dropSchema))
+
+ override def dropUserArtifacts(implicit session: profile.Backend#Session) = {
+ session.close()
+ cleanUpBefore()
+ }
+ }
+
+ class SQLServerDB(confName: String) extends ExternalJdbcTestDB(confName) {
+ val profile = SQLServerProfile
+ import profile.api.actionBasedSQLInterpolation
+
+ val defaultSchema = config.getString("defaultSchema")
+
+ override def localTables(implicit ec: ExecutionContext): DBIO[Vector[String]] =
+ ResultSetAction[(String,String,String, String)](_.conn.getMetaData().getTables(testDB, defaultSchema, null, null)).map { ts =>
+ ts.map(_._3).sorted
+ }
+
+ override def dropUserArtifacts(implicit session: profile.Backend#Session) = blockingRunOnSession { implicit ec =>
+ for {
+ constraints <- sql"""select constraint_name, table_name from information_schema.table_constraints where constraint_type = 'FOREIGN KEY'""".as[(String, String)]
+ constraintStatements = constraints.collect { case (c, t) if !c.startsWith("SQL") =>
+ sqlu"alter table #${profile.quoteIdentifier(t)} drop constraint #${profile.quoteIdentifier(c)}"
+ }
+ _ <- DBIO.sequence(constraintStatements)
+ tables <- localTables
+ tableStatements = tables.map(t => sqlu"drop table #${profile.quoteIdentifier(t)}")
+ _ <- DBIO.sequence(tableStatements)
+ } yield ()
+ }
+ }
+
+ lazy val SQLServerJTDS = new SQLServerDB("sqlserver-jtds") {
+ override def capabilities = super.capabilities - TestDB.capabilities.plainSql
+ }
+ lazy val SQLServerSQLJDBC = new SQLServerDB("sqlserver-sqljdbc") {
+ override def capabilities = profile.capabilities - JdbcCapabilities.createModel
+ }
+
+ lazy val Oracle = new ExternalJdbcTestDB("oracle") {
+ val profile = OracleProfile
+ import profile.api.actionBasedSQLInterpolation
+
+ override def canGetLocalTables = false
+ override def capabilities =
+ super.capabilities - TestDB.capabilities.jdbcMetaGetIndexInfo - TestDB.capabilities.transactionIsolation
+
+ /* Only drop and recreate the user. This is much faster than dropping
+ * the tablespace. */
+ override def dropUserArtifacts(implicit session: profile.Backend#Session) = {
+ session.close()
+ val a = DBIO.sequence(Seq(drop(0), create(1), create(2)).map(s => sqlu"#$s"))
+ await(databaseFor("adminConn").run(a))
+ }
+ }
}
abstract class H2TestDB(confName: String, keepAlive: Boolean) extends InternalJdbcTestDB(confName) {
@@ -38,3 +38,15 @@ class MySQLTest extends ProfileTest(StandardTestDBs.MySQL)
@RunWith(classOf[Testkit])
class HeapTest extends ProfileTest(StandardTestDBs.Heap)
+
+@RunWith(classOf[Testkit])
+class DB2Test extends ProfileTest(StandardTestDBs.DB2)
+
+@RunWith(classOf[Testkit])
+class OracleTest extends ProfileTest(StandardTestDBs.Oracle)
+
+@RunWith(classOf[Testkit])
+class SQLServerJTDSTest extends ProfileTest(StandardTestDBs.SQLServerJTDS)
+
+@RunWith(classOf[Testkit])
+class SQLServerSQLJDBCTest extends ProfileTest(StandardTestDBs.SQLServerSQLJDBC)
@@ -37,3 +37,10 @@ slick.jdbc.MySQLProfile {
# to "VARCHAR(254)"
defaultStringType = null
}
+
+# Profile-specific settings for SQLServerProfile
+slick.jdbc.SQLServerProfile {
+ # The default SQL type for strings without an explicit size limit.
+ # When set to null / undefined, pick "TEXT" where possible, otherwise fall back to "VARCHAR(254)"
+ defaultStringType = null
+}
Oops, something went wrong.

0 comments on commit 81b6919

Please sign in to comment.