Skip to content

Commit

Permalink
Update for Slick 2.0.0-M3
Browse files Browse the repository at this point in the history
  • Loading branch information
szeiger committed Nov 27, 2013
1 parent 8a4eb45 commit 647168e
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 41 deletions.
12 changes: 5 additions & 7 deletions build.sbt
Expand Up @@ -4,16 +4,14 @@ organizationName := "Typesafe"

organization := "com.typesafe.slick"

version := "1.0.1-RC1"
version := "2.0.0-M3"

scalaVersion := "2.10.1"

//scalaBinaryVersion in Global := "2.10.0"
scalaVersion := "2.10.3"

libraryDependencies ++= Seq(
"com.typesafe.slick" %% "slick" % "1.0.1-RC1",
"com.typesafe.slick" %% "slick-testkit" % "1.0.1-RC1" % "test",
"com.novocode" % "junit-interface" % "0.10-M4" % "test",
"com.typesafe.slick" %% "slick" % "2.0.0-M3",
"com.typesafe.slick" %% "slick-testkit" % "2.0.0-M3" % "test",
"com.novocode" % "junit-interface" % "0.10" % "test",
"ch.qos.logback" % "logback-classic" % "0.9.28" % "test",
"postgresql" % "postgresql" % "9.1-901.jdbc4" % "test"
)
Expand Down
2 changes: 1 addition & 1 deletion project/build.properties
@@ -1 +1 @@
sbt.version=0.12.2
sbt.version=0.13.0
80 changes: 53 additions & 27 deletions src/main/scala/scala/slick/driver/MyPostgresDriver.scala
Expand Up @@ -2,43 +2,43 @@ package scala.slick.driver

import java.util.UUID
import scala.slick.lifted._
import scala.slick.session.{PositionedResult, PositionedParameters}
import scala.slick.jdbc.{PositionedParameters, PositionedResult, JdbcType}
import scala.slick.ast.{SequenceNode, Library, FieldSymbol, Node}
import scala.slick.util.MacroSupport.macroSupportInterpolation
import scala.slick.compiler.CompilerState

/**
* Slick driver for PostgreSQL.
*
* This driver implements the [[scala.slick.driver.ExtendedProfile]]
* ''without'' the following capabilities:
* This driver implements all capabilities of the
* [[scala.slick.driver.JdbcProfile]].
*
* Notes:
*
* <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>
* <li>[[scala.slick.profile.RelationalProfile.capabilities.typeBlob]]:
* The default implementation of the <code>Blob</code> type uses the
* database type <code>lo</code> and the stored procedure
* <code>lo_manage</code>, both of which are provided by the "lo"
* extension in PostgreSQL.</li>
* </ul>
*
* @author szeiger
*/
trait MyPostgresDriver extends ExtendedDriver { driver =>
trait MyPostgresDriver extends JdbcDriver { driver =>

override val typeMapperDelegates = new TypeMapperDelegates
override def createQueryBuilder(input: QueryBuilderInput): QueryBuilder = new QueryBuilder(input)
override val columnTypes = new JdbcTypes
override def createQueryBuilder(n: Node, state: CompilerState): QueryBuilder = new QueryBuilder(n, state)
override def createTableDDLBuilder(table: Table[_]): TableDDLBuilder = new TableDDLBuilder(table)
override def createColumnDDLBuilder(column: FieldSymbol, table: Table[_]): ColumnDDLBuilder = new ColumnDDLBuilder(column)

override val capabilities: Set[Capability] = (BasicProfile.capabilities.all
- BasicProfile.capabilities.typeBlob
)

override def defaultSqlTypeName(tmd: TypeMapperDelegate[_]): String = tmd.sqlType match {
override def defaultSqlTypeName(tmd: JdbcType[_]): String = tmd.sqlType match {
case java.sql.Types.BLOB => "lo"
case java.sql.Types.DOUBLE => "DOUBLE PRECISION"
/* PostgreSQL does not have a TINYINT type, so we use SMALLINT instead. */
case java.sql.Types.TINYINT => "SMALLINT"
case java.sql.Types.BLOB => "BYTEA"
case _ => super.defaultSqlTypeName(tmd)
}

class QueryBuilder(input: QueryBuilderInput) extends super.QueryBuilder(input) {
class QueryBuilder(tree: Node, state: CompilerState) extends super.QueryBuilder(tree, state) {
override protected val concatOperator = Some("||")

override protected def buildFetchOffsetClause(fetch: Option[Long], offset: Option[Long]) = (fetch, offset) match {
Expand All @@ -55,23 +55,48 @@ trait MyPostgresDriver extends ExtendedDriver { driver =>
}
}

class TableDDLBuilder(table: Table[_]) extends super.TableDDLBuilder(table) {
override def createPhase1 = super.createPhase1 ++ columns.flatMap {
case cb: ColumnDDLBuilder => cb.createLobTrigger(table.tableName)
}
override def dropPhase1 = {
val dropLobs = columns.flatMap {
case cb: ColumnDDLBuilder => cb.dropLobTrigger(table.tableName)
}
if(dropLobs.isEmpty) super.dropPhase1
else Seq("delete from "+quoteIdentifier(table.tableName)) ++ dropLobs ++ super.dropPhase1
}
}

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
}
if(autoIncrement && !customSqlType) sb append "SERIAL"
else sb append sqlType
autoIncrement = false
appendOptions(sb)
}

def lobTrigger(tname: String) =
quoteIdentifier(tname+"__"+quoteIdentifier(column.name)+"_lob")

def createLobTrigger(tname: String): Option[String] =
if(sqlType == "lo") Some(
"create trigger "+lobTrigger(tname)+" before update or delete on "+
quoteIdentifier(tname)+" for each row execute procedure lo_manage("+quoteIdentifier(column.name)+")"
) else None

def dropLobTrigger(tname: String): Option[String] =
if(sqlType == "lo") Some(
"drop trigger "+lobTrigger(tname)
) else None
}

class TypeMapperDelegates extends super.TypeMapperDelegates {
override val byteArrayTypeMapperDelegate = new ByteArrayTypeMapperDelegate
override val uuidTypeMapperDelegate = new UUIDTypeMapperDelegate
class JdbcTypes extends super.JdbcTypes {
override val byteArrayJdbcType = new ByteArrayJdbcType
override val uuidJdbcType = new UUIDJdbcType

class ByteArrayTypeMapperDelegate extends super.ByteArrayTypeMapperDelegate {
class ByteArrayJdbcType extends super.ByteArrayJdbcType {
override val sqlType = java.sql.Types.BINARY
override val sqlTypeName = "BYTEA"
override def setOption(v: Option[Array[Byte]], p: PositionedParameters) = v match {
Expand All @@ -80,13 +105,14 @@ trait MyPostgresDriver extends ExtendedDriver { driver =>
}
}

class UUIDTypeMapperDelegate extends super.UUIDTypeMapperDelegate {
class UUIDJdbcType extends super.UUIDJdbcType {
override def sqlTypeName = "UUID"
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 + "'"
override def hasLiteralForm = true
}
}
}
Expand Down
14 changes: 8 additions & 6 deletions src/test/scala/scala/slick/driver/test/MyPostgresTest.scala
@@ -1,8 +1,7 @@
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 com.typesafe.slick.testkit.util.{ExternalJdbcTestDB, TestDB, DriverTest, Testkit}
import scala.slick.jdbc.ResultSetInvoker
import scala.slick.jdbc.GetResult._
import scala.slick.driver.MyPostgresDriver
Expand All @@ -11,15 +10,18 @@ import scala.slick.driver.MyPostgresDriver
class MyPostgresTest extends DriverTest(MyPostgresTest.tdb)

object MyPostgresTest {
def tdb(cname: String) = new ExternalTestDB("mypostgres", MyPostgresDriver) {
override def getLocalTables(implicit session: Session) = {

def tdb = new ExternalJdbcTestDB("mypostgres") {
type Driver = MyPostgresDriver.type
val driver = MyPostgresDriver
override def getLocalTables(implicit session: profile.Backend#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) = {
override def getLocalSequences(implicit session: profile.Backend#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
override lazy val capabilities = driver.capabilities + TestDB.plainSql + TestDB.plainSqlWide
}
}
1 change: 1 addition & 0 deletions test-dbs/databases.properties.example
Expand Up @@ -22,5 +22,6 @@ 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.postCreate = create extension lo
mypostgres.drop = DROP DATABASE IF EXISTS "[DB]"; DROP TABLESPACE IF EXISTS slick_test
mypostgres.driver = org.postgresql.Driver

0 comments on commit 647168e

Please sign in to comment.