Permalink
Browse files

Create slick-testkit-example with PostgreSQL driver

  • Loading branch information...
0 parents commit fdeccc9bc586bb76bad4bec3674950f250dd55dc @szeiger szeiger committed Sep 10, 2012
@@ -0,0 +1,12 @@
+/.idea/
+target/
+/test-dbs/*-*
+/test-dbs/databases.properties
+*.log
+*.iml
+*.pyc
+/\.target/
+/\.cache
+/\.project
+/\.classpath
+/\.settings/
@@ -0,0 +1,25 @@
+Copyright 2011-2012 Typesafe, Inc.
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,6 @@
+Slick TestKit Example
+=====================
+
+This project contains the standard Slick driver for PostgreSQL in a separate
+project, in order to demonstrate how to build and verify a driver with the
+Slick TestKit.
@@ -0,0 +1,25 @@
+name := "Slick-TestKit-Example"
+
+organizationName := "Typesafe"
+
+organization := "com.typesafe"
+
+version := "1.0.0-SNAPSHOT"
+
+scalaVersion := "2.10.0-M7"
+
+scalaBinaryVersion in Global := "2.10.0-M7"
+
+libraryDependencies ++= Seq(
+ "com.typesafe" %% "slick" % "1.0.0-SNAPSHOT",
+ "com.typesafe" %% "slick-testkit" % "1.0.0-SNAPSHOT" % "test",
+ "com.novocode" % "junit-interface" % "0.10-M1" % "test",
+ "ch.qos.logback" % "logback-classic" % "0.9.28" % "test",
+ "postgresql" % "postgresql" % "9.1-901.jdbc4" % "test"
+)
+
+testOptions += Tests.Argument(TestFrameworks.JUnit, "-q", "-v", "-s", "-a")
+
+parallelExecution in Test := false
+
+logBuffered := false
@@ -0,0 +1 @@
+sbt.version=0.12.0
@@ -0,0 +1,84 @@
+package scala.slick.driver
+
+import java.util.UUID
+import scala.slick.lifted._
+import scala.slick.session.{PositionedResult, PositionedParameters}
+import scala.slick.ast.{SequenceNode, Library, FieldSymbol, Node}
+
+/**
+ * Slick driver for PostgreSQL.
+ *
+ * This driver implements the [[scala.slick.driver.ExtendedProfile]]
+ * ''without'' the following capabilities:
+ *
+ * <ul>
+ * <li>[[scala.slick.driver.BasicProfile.capabilities.typeBlob]]:
+ * Blobs are not supported (but binary data in the form of
+ * <code>Array[Byte]</code> is).</li>
+ * </ul>
+ *
+ * @author szeiger
+ */
+trait MyPostgresDriver extends ExtendedDriver { driver =>
+
+ override val typeMapperDelegates = new TypeMapperDelegates
+ override def createQueryBuilder(input: QueryBuilderInput): QueryBuilder = new QueryBuilder(input)
+ override def createColumnDDLBuilder(column: FieldSymbol, table: Table[_]): ColumnDDLBuilder = new ColumnDDLBuilder(column)
+
+ override val capabilities: Set[Capability] = (BasicProfile.capabilities.all
+ - BasicProfile.capabilities.typeBlob
+ )
+
+ override def mapTypeName(tmd: TypeMapperDelegate[_]): String = tmd.sqlType match {
+ case java.sql.Types.DOUBLE => "DOUBLE PRECISION"
+ case _ => super.mapTypeName(tmd)
+ }
+
+ class QueryBuilder(input: QueryBuilderInput) extends super.QueryBuilder(input) {
+ override protected val concatOperator = Some("||")
+
+ override protected def buildFetchOffsetClause(fetch: Option[Long], offset: Option[Long]) = (fetch, offset) match {
+ case (Some(t), Some(d)) => b += " LIMIT " += t += " OFFSET " += d
+ case (Some(t), None) => b += " LIMIT " += t
+ case (None, Some(d)) => b += " OFFSET " += d
+ case _ =>
+ }
+
+ override def expr(n: Node, skipParens: Boolean = false) = n match {
+ case Library.NextValue(SequenceNode(name)) => b += "nextval('" += name += "')"
+ case Library.CurrentValue(SequenceNode(name)) => b += "currval('" += name += "')"
+ case _ => super.expr(n, skipParens)
+ }
+ }
+
+ class ColumnDDLBuilder(column: FieldSymbol) extends super.ColumnDDLBuilder(column) {
+ override def appendColumn(sb: StringBuilder) {
+ sb append quoteIdentifier(column.name) append ' '
+ if(autoIncrement) {
+ sb append "SERIAL"
+ autoIncrement = false
+ }
+ else sb append sqlType
+ appendOptions(sb)
+ }
+ }
+
+ class TypeMapperDelegates extends super.TypeMapperDelegates {
+ /* PostgreSQL does not have a TINYINT type, so we use SMALLINT instead. */
+ override val byteTypeMapperDelegate = new ByteTypeMapperDelegate {
+ override def sqlTypeName = "SMALLINT"
+ }
+ override val byteArrayTypeMapperDelegate = new ByteArrayTypeMapperDelegate {
+ override val sqlTypeName = "BYTEA"
+ }
+ override val uuidTypeMapperDelegate = new UUIDTypeMapperDelegate {
+ override def setValue(v: UUID, p: PositionedParameters) = p.setObject(v, sqlType)
+ override def setOption(v: Option[UUID], p: PositionedParameters) = p.setObjectOption(v, sqlType)
+ override def nextValue(r: PositionedResult) = r.nextObject().asInstanceOf[UUID]
+ override def updateValue(v: UUID, r: PositionedResult) = r.updateObject(v)
+ override def valueToSQLLiteral(value: UUID) = "'" + value + "'"
+ }
+ }
+}
+
+object MyPostgresDriver extends MyPostgresDriver
@@ -0,0 +1,30 @@
+<configuration>
+ <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+ <encoder>
+ <pattern>*** \(%logger{30}\) %msg%n</pattern>
+ </encoder>
+ </appender>
+ <root level="${log.root:-info}">
+ <appender-ref ref="STDOUT" />
+ </root>
+ <logger name="scala.slick.compiler" level="${log.qcomp:-info}" />
+ <logger name="scala.slick.compiler.QueryCompiler" level="${log.qcomp.phases:-inherited}" />
+ <logger name="scala.slick.compiler.LocalizeRefs" level="${log.qcomp.localizeRefs:-inherited}" />
+ <logger name="scala.slick.compiler.ReconstructProducts" level="${log.qcomp.reconstructProducts:-inherited}" />
+ <logger name="scala.slick.compiler.Inline" level="${log.qcomp.inline:-inherited}" />
+ <logger name="scala.slick.compiler.RewriteOrderBy" level="${log.qcomp.rewriteOrderBy:-inherited}" />
+ <logger name="scala.slick.compiler.LetDynamicEliminated" level="${log.qcomp.letDynamicEliminated:-inherited}" />
+ <logger name="scala.slick.compiler.AssignUniqueSymbols" level="${log.qcomp.assignUniqueSymbols:-inherited}" />
+ <logger name="scala.slick.compiler.ForceOuterBinds" level="${log.qcomp.forceOuterBinds:-inherited}" />
+ <logger name="scala.slick.compiler.ExpandTables" level="${log.qcomp.expandTables:-inherited}" />
+ <logger name="scala.slick.compiler.ExpandRefs" level="${log.qcomp.expandRefs:-inherited}" />
+ <logger name="scala.slick.compiler.ReplaceFieldSymbols" level="${log.qcomp.replaceFieldSymbols:-inherited}" />
+ <logger name="scala.slick.compiler.RewritePaths" level="${log.qcomp.rewritePaths:-inherited}" />
+ <logger name="scala.slick.compiler.RelabelUnions" level="${log.qcomp.relabelUnions:-inherited}" />
+ <logger name="scala.slick.compiler.PruneFields" level="${log.qcomp.pruneFields:-inherited}" />
+ <logger name="scala.slick.compiler.ResolveZipJoins" level="${log.qcomp.resolveZipJoins:-inherited}" />
+ <logger name="scala.slick.compiler.ConvertToComprehensions" level="${log.qcomp.convertToComprehensions:-inherited}" />
+ <logger name="scala.slick.compiler.FuseComprehensions" level="${log.qcomp.fuseComprehensions:-inherited}" />
+ <logger name="scala.slick.compiler.FixRowNumberOrdering" level="${log.qcomp.fixRowNumberOrdering:-inherited}" />
+ <logger name="scala.slick.session" level="${log.session:-info}" />
+</configuration>
@@ -0,0 +1,25 @@
+package scala.slick.driver.test
+
+import org.junit.runner.RunWith
+import com.typesafe.slick.testkit.util.{TestDB, ExternalTestDB, DriverTest, Testkit}
+import scala.slick.session.Session
+import scala.slick.jdbc.ResultSetInvoker
+import scala.slick.jdbc.GetResult._
+import scala.slick.driver.MyPostgresDriver
+
+@RunWith(classOf[Testkit])
+class MyPostgresTest extends DriverTest(MyPostgresTest.tdb)
+
+object MyPostgresTest {
+ def tdb(cname: String) = new ExternalTestDB("mypostgres", MyPostgresDriver) {
+ override def getLocalTables(implicit session: Session) = {
+ val tables = ResultSetInvoker[(String,String,String, String)](_.conn.getMetaData().getTables("", "public", null, null))
+ tables.list.filter(_._4.toUpperCase == "TABLE").map(_._3).sorted
+ }
+ override def getLocalSequences(implicit session: Session) = {
+ val tables = ResultSetInvoker[(String,String,String, String)](_.conn.getMetaData().getTables("", "public", null, null))
+ tables.list.filter(_._4.toUpperCase == "SEQUENCE").map(_._3).sorted
+ }
+ override lazy val capabilities = driver.capabilities + TestDB.plainSql
+ }
+}
@@ -0,0 +1,26 @@
+##############################################################################
+# Configurations for external test databases
+##############################################################################
+# Copy this file to databases.properties and follow the instructions below to
+# enable the external database systems for unit tests.
+##############################################################################
+
+# Use only the following DBs (or use all if not set)
+#testDBs = mypostgres
+
+# Store database files in this path instead of the test-dbs dir
+testDir = r:/test-dbs
+
+# PostgreSQL quick setup:
+# - Install PostgreSQL server with default options
+# - Change password in mypostgres.password
+# - Set mypostgres.enabled = true
+mypostgres.enabled = false
+mypostgres.url = jdbc:postgresql:[DB]
+mypostgres.user = postgres
+mypostgres.password = secret
+mypostgres.adminDB = postgres
+mypostgres.testDB = slick-test
+mypostgres.create = CREATE TABLESPACE slick_test LOCATION '[DBPATH]'; CREATE DATABASE "[DB]" TEMPLATE = template0 TABLESPACE slick_test
+mypostgres.drop = DROP DATABASE IF EXISTS "[DB]"; DROP TABLESPACE IF EXISTS slick_test
+mypostgres.driver = org.postgresql.Driver

0 comments on commit fdeccc9

Please sign in to comment.