Skip to content
This repository was archived by the owner on Jun 4, 2019. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions build.sbt
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
name := "prequel"

version := "0.3.9"
version := "1.0-SNAPSHOT"

organization := "net.noerd"
organization := "com.gu"

scalaVersion := "2.10.0"

crossScalaVersions := Seq("2.9.2", "2.10.0")

// Runtime Dependencies
libraryDependencies ++= Seq(
"commons-pool" % "commons-pool" % "1.5.5",
Expand Down
26 changes: 25 additions & 1 deletion src/main/scala/net/noerd/prequel/ColumnTypes.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@ package net.noerd.prequel

import java.util.Date

import java.sql.{ Date => SqlDate }
import java.sql.Timestamp

import org.joda.time.DateTime
import org.joda.time.Duration
import org.joda.time.format.DateTimeFormatter

//
// String
Expand Down Expand Up @@ -75,13 +77,35 @@ class DateTimeColumnType( row: ResultSetRow ) extends ColumnType[ DateTime ] {
object DateTimeColumnType extends ColumnTypeFactory[ DateTime ] {
def apply( row: ResultSetRow ) = new DateTimeColumnType( row )
}

class DateColumnType( row: ResultSetRow ) extends ColumnType[ Date ] {
override def nextValueOption: Option[ Date ] = row.nextDate
}
object DateColumnType extends ColumnTypeFactory[ Date ] {
def apply( row: ResultSetRow ) = new DateColumnType( row )
}

//
// Timestamp
//
class TimestampColumnType( row: ResultSetRow ) extends ColumnType[ Timestamp ] {
override def nextValueOption: Option[ Timestamp ] = row.nextTimestamp
}
object TimestampColumnType extends ColumnTypeFactory[ Timestamp ] {
def apply( row: ResultSetRow ) = new TimestampColumnType( row )
}

//
// java.sql.Date
//
class SqlDateColumnType( row: ResultSetRow ) extends ColumnType[ SqlDate ] {
override def nextValueOption: Option[ SqlDate ] = row.nextSqlDate
}
object SqlDateColumnType extends ColumnTypeFactory[ SqlDate ] {
def apply( row: ResultSetRow ) = new SqlDateColumnType( row )
}


//
// Duration
//
Expand Down
2 changes: 1 addition & 1 deletion src/main/scala/net/noerd/prequel/Database.scala
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package net.noerd.prequel

import java.sql.{ SQLException, Connection }
import java.sql.Connection
import java.util.Properties

import scala.collection.mutable.{ Map => MMap }
Expand Down
42 changes: 41 additions & 1 deletion src/main/scala/net/noerd/prequel/Formattables.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import java.util.{Locale, Date}

import org.joda.time.DateTime
import org.joda.time.Duration
import org.joda.time.format.DateTimeFormatter
import java.sql.{Timestamp, Date => SqlDate}

/**
* Wrap your optional value in NullComparable to compare with null if None.
Expand Down Expand Up @@ -154,6 +154,46 @@ object DateTimeFormattable{
}
}


//
// Timestamp
//
class TimestampFormattable( val value: Timestamp )
extends Formattable {
override def escaped( formatter: SQLFormatter ): String = {
formatter.toSQLString( formatter.timeStampFormatter.print( value.getTime ) )
}
override def addTo( statement: ReusableStatement ): Unit = {
statement.addTimestamp( value )
}
}

object TimestampFormattable {
def apply( value: Timestamp ) = {
new TimestampFormattable( value )
}
}



class SqlDateFormattable( val value: SqlDate )
extends Formattable {
override def escaped( formatter: SQLFormatter ): String = {
formatter.toSQLString( value.toString )
}
override def addTo( statement: ReusableStatement ): Unit = {
statement.addSqlDate( value )
}
}

object SqlDateFormattable {
def apply( value: SqlDate ) = {
new SqlDateFormattable( value )
}
}



//
// Duration
//
Expand Down
15 changes: 9 additions & 6 deletions src/main/scala/net/noerd/prequel/ResultSetRow.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,10 @@ package net.noerd.prequel

import java.util.Date

import java.sql.ResultSet
import java.sql.ResultSetMetaData
import java.sql.{Timestamp, ResultSet, Date => SqlDate}

import scala.collection.mutable.ArrayBuffer

import org.joda.time.DateTime
import org.joda.time.Duration

/**
* Wraps a ResultSet in a row context. The ResultSetRow gives access
Expand All @@ -27,9 +24,11 @@ class ResultSetRow( val rs: ResultSet ) {
def nextDouble: Option[ Double ] = nextValueOption( rs.getDouble )
def nextString: Option[ String ] = nextValueOption( rs.getString )
def nextDate: Option[ Date ] = nextValueOption( rs.getTimestamp )
def nextSqlDate: Option[ SqlDate ] = nextValueOption( rs.getDate )
def nextTimestamp: Option[ Timestamp ] = nextValueOption( rs.getTimestamp )
def nextObject: Option[ AnyRef ] = nextValueOption( rs.getObject )
def nextBinary: Option[ Array[Byte] ] = nextValueOption( rs.getBytes )

def columnNames: Seq[ String ]= {
val columnNames = ArrayBuffer.empty[ String ]
val metaData = rs.getMetaData
Expand Down Expand Up @@ -84,6 +83,8 @@ object ResultSetRowImplicits {
implicit def row2String( row: ResultSetRow ) = StringColumnType( row ).nextValue
implicit def row2Date( row: ResultSetRow ) = DateColumnType( row ).nextValue
implicit def row2DateTime( row: ResultSetRow ) = DateTimeColumnType( row ).nextValue
implicit def row2Timestamp( row: ResultSetRow ) = TimestampColumnType( row ).nextValue
implicit def row2SqlDate( row: ResultSetRow ) = SqlDateColumnType( row ).nextValue
implicit def row2Duration( row: ResultSetRow ) = DurationColumnType( row ).nextValue
implicit def row2Binary( row: ResultSetRow ) = BinaryColumnType( row ).nextValue

Expand All @@ -95,6 +96,8 @@ object ResultSetRowImplicits {
implicit def row2StringOption( row: ResultSetRow ) = StringColumnType( row ).nextValueOption
implicit def row2DateOption( row: ResultSetRow ) = DateColumnType( row ).nextValueOption
implicit def row2DateTimeOption( row: ResultSetRow ) = DateTimeColumnType( row ).nextValueOption
implicit def row2TimestampOption( row: ResultSetRow ) = TimestampColumnType( row ).nextValueOption
implicit def row2SqlDateOption( row: ResultSetRow ) = SqlDateColumnType( row ).nextValueOption
implicit def row2DurationOption( row: ResultSetRow ) = DurationColumnType( row ).nextValueOption
implicit def row2BinaryOption( row: ResultSetRow ) = BinaryColumnType( row ).nextValueOption
}
}
23 changes: 16 additions & 7 deletions src/main/scala/net/noerd/prequel/ReusableStatement.scala
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
package net.noerd.prequel

import java.sql.Connection
import java.sql.PreparedStatement
import java.sql.Timestamp
import java.sql.Types
import java.sql.{Timestamp, Types, Date => SqlDate}

import org.joda.time.DateTime

Expand Down Expand Up @@ -62,16 +60,27 @@ private class ReusableStatement( val wrapped: PreparedStatement, formatter: SQLF
def addString( value: String ) =
addValue(wrapped.setString( parameterIndex, formatter.escapeString( value ) )
)

/**
* Add a Date to the current parameter index. This is done by setTimestamp which
* looses the Timezone information of the DateTime
*/
def addDateTime( value: DateTime ): Unit =
addValue( wrapped.setTimestamp( parameterIndex, new Timestamp( value.getMillis ) )
)
addValue( wrapped.setTimestamp( parameterIndex, new Timestamp( value.getMillis ) ) )

/**
/**
* Add a Timestamp to the current parameter index.
*/
def addTimestamp( value: Timestamp ): Unit =
addValue( wrapped.setTimestamp( parameterIndex, value ) )

/**
* Add a java.sql.Date to the current parameter index.
*/
def addSqlDate( value: SqlDate ): Unit =
addValue( wrapped.setDate( parameterIndex, value) )

/**
* Add Binary (array of bytes) to the current parameter index
*/
def addBinary( value: Array[Byte] ): Unit = addValue( wrapped.setBytes( parameterIndex, value ) )
Expand Down
3 changes: 3 additions & 0 deletions src/main/scala/net/noerd/prequel/SQLFormatter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import org.joda.time.Duration
import org.joda.time.format.DateTimeFormat
import org.joda.time.format.DateTimeFormatter
import org.joda.time.format.ISODateTimeFormat
import java.sql.{Timestamp, Date => SqlDate}

/**
* Currently a private class responsible for formatting SQL used in
Expand Down Expand Up @@ -84,6 +85,8 @@ object SQLFormatterImplicits {
implicit def float2Formattable( wrapped: Float ) = FloatFormattable( wrapped )
implicit def double2Formattable( wrapped: Double ) = DoubleFormattable( wrapped )
implicit def dateTime2Formattable( wrapped: DateTime ) = DateTimeFormattable( wrapped )
implicit def sqlDate2Formattable( wrapped: SqlDate ) = SqlDateFormattable( wrapped )
implicit def timeStamp2Formattable( wrapped: Timestamp ) = TimestampFormattable( wrapped )
implicit def date2Formattable( wrapped: Date ) = DateTimeFormattable( wrapped )
implicit def duration2Formattable( wrapped: Duration ) = new DurationFormattable( wrapped )
implicit def binary2Formattable( wrapped: Array[Byte] ) = new BinaryFormattable( wrapped )
Expand Down
2 changes: 0 additions & 2 deletions src/main/scala/net/noerd/prequel/Transaction.scala
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
package net.noerd.prequel

import java.sql.Connection
import java.sql.Statement
import java.sql.ResultSet

import scala.collection.mutable.ArrayBuffer

Expand Down
2 changes: 0 additions & 2 deletions src/test/scala/net/noerd/prequel/ColumnTypesSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,7 @@ import org.joda.time.Duration

import org.scalatest.FunSpec
import org.scalatest.matchers.ShouldMatchers
import org.scalatest.BeforeAndAfterEach

import net.noerd.prequel.SQLFormatterImplicits._

trait ColumnTypeSpec[ T ] extends FunSpec with ShouldMatchers {

Expand Down
1 change: 0 additions & 1 deletion src/test/scala/net/noerd/prequel/ConnectionPoolsSpec.scala
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package net.noerd.prequel

import java.sql.SQLException

import org.scalatest.FunSpec
import org.scalatest.matchers.ShouldMatchers
Expand Down
12 changes: 10 additions & 2 deletions src/test/scala/net/noerd/prequel/FormattablesSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import org.joda.time.Duration

import org.scalatest.FunSpec
import org.scalatest.matchers.ShouldMatchers
import org.scalatest.BeforeAndAfterEach
import java.sql.{Timestamp, Date => SqlDate}
import java.util.Locale

class FormattablesSpec extends FunSpec with ShouldMatchers {
Expand Down Expand Up @@ -33,6 +33,14 @@ class FormattablesSpec extends FunSpec with ShouldMatchers {
DateTimeFormattable( formatter.timeStampFormatter.parseDateTime( "2010-03-13 13:00:00.0000" ) ),
"'2010-03-13 13:00:00.0000'"
),
( "TimeStampFormattable should escape 2010-03-13 13:00:00.0040",
TimestampFormattable( Timestamp.valueOf( "2010-03-13 13:00:00.0040" ) ),
"'2010-03-13 13:00:00.0040'"
),
( "TimeStampFormattable should escape 2010-03-13",
SqlDateFormattable( SqlDate.valueOf( "2010-03-13" ) ),
"'2010-03-13'"
),
( "DurationFormattable should escape an Duration object",
DurationFormattable( Duration.standardHours( 2 ) ), "7200000"
),
Expand Down Expand Up @@ -85,4 +93,4 @@ class FormattablesSpec extends FunSpec with ShouldMatchers {
Locale.setDefault(oldDefaultLocale)
}
}
}
}
1 change: 0 additions & 1 deletion src/test/scala/net/noerd/prequel/InTransactionSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import org.scalatest.matchers.ShouldMatchers
import org.scalatest.BeforeAndAfterEach

import net.noerd.prequel.SQLFormatterImplicits._
import net.noerd.prequel.ResultSetRowImplicits._

class InTransactionSpec extends FunSpec with ShouldMatchers with BeforeAndAfterEach {

Expand Down
32 changes: 25 additions & 7 deletions src/test/scala/net/noerd/prequel/ResultSetRowSpec.scala
Original file line number Diff line number Diff line change
@@ -1,18 +1,13 @@
package net.noerd.prequel

import java.util.Date
import java.sql.SQLException
import java.sql.{Timestamp, Date => SqlDate}

import org.scalatest.FunSpec
import org.scalatest.matchers.ShouldMatchers
import org.scalatest.BeforeAndAfterEach

import org.joda.time.DateTime
import org.joda.time.Duration
import org.joda.time.format.DateTimeFormat
import org.joda.time.format.DateTimeFormatter
import net.noerd.prequel.SQLFormatterImplicits._
import net.noerd.prequel.ResultSetRowImplicits._

class ResultSetRowSpec extends FunSpec with ShouldMatchers with BeforeAndAfterEach {

Expand Down Expand Up @@ -87,7 +82,30 @@ class ResultSetRowSpec extends FunSpec with ShouldMatchers with BeforeAndAfterEa
}
} }

it( "should return a Float" ) { database.transaction { tx =>
it( "should return a Timestamp" ) { database.transaction { tx =>
val value1 = Some( Timestamp.valueOf( "2014-03-26 00:00:00" ) )
tx.execute( "create table timestamp_table(c1 timestamp, c2 timestamp)" )
tx.execute( "insert into timestamp_table values(?, null)", value1.get )
tx.select( "select c1, c2 from timestamp_table" ) { row =>
row.nextTimestamp.get.getTime should equal (value1.get.getTime)
row.nextTimestamp should equal ( None )
}
} }

it( "should return a SqlDate" ) { database.transaction { tx =>
val now = ( new Date ).getTime
val value1 = Some( new SqlDate( now) )

tx.execute( "create table sqldate_table(c1 date, c2 date)" )
tx.execute( "insert into sqldate_table values(?, null)", value1.get )
tx.select( "select c1, c2 from sqldate_table" ) { row =>
val retrievedDate = row.nextSqlDate.get
retrievedDate.toString should equal (value1.get.toString)
row.nextSqlDate should equal ( None )
}
} }

it( "should return a Float" ) { database.transaction { tx =>
val value1 = Some(1.5f)
val value2 = None
tx.execute( "create table float_table(c1 real, c2 real)" )
Expand Down
1 change: 0 additions & 1 deletion src/test/scala/net/noerd/prequel/SQLFormatterSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import org.scalatest.matchers.ShouldMatchers

import net.noerd.prequel.SQLFormatter.DefaultSQLFormatter
import net.noerd.prequel.SQLFormatterImplicits._
import net.noerd.prequel.ResultSetRowImplicits._

class SQLFormatterSpec extends FunSpec with ShouldMatchers {

Expand Down