Permalink
Browse files

[jdbc-driver] Support for SQL Array as statement parameter

  • Loading branch information...
cchantep
cchantep committed Sep 27, 2014
1 parent 97e0edf commit ca0470eb13f5dd9a6a083fa26f2665303f96ffdb
@@ -7,6 +7,7 @@
import java.math.BigDecimal;
import java.sql.Timestamp;
+import java.sql.Array;
import java.sql.Types;
import java.sql.Date;
import java.sql.Time;
@@ -57,6 +58,7 @@
// JDBC type mappings
final HashMap<Integer,String> mappings = new HashMap<Integer,String>();
+ mappings.put(Types.ARRAY, Array.class.getName());
mappings.put(Types.BIGINT, Long.class.getName());
mappings.put(Types.BIT, Boolean.class.getName());
mappings.put(Types.BOOLEAN, Boolean.class.getName());
@@ -98,6 +100,7 @@
// JDBC type names
final HashMap<Integer,String> names = new HashMap<Integer,String>();
+ names.put(Types.ARRAY, "ARRAY");
names.put(Types.BIGINT, "BIGINT");
names.put(Types.BIT, "BOOL");
names.put(Types.BOOLEAN, "BOOL");
@@ -134,6 +137,7 @@
// JDBC type signs
final HashMap<Integer,Boolean> signs = new HashMap<Integer,Boolean>();
+ signs.put(Types.ARRAY, Boolean.FALSE);
signs.put(Types.BIGINT, Boolean.TRUE);
signs.put(Types.BIT, Boolean.FALSE);
signs.put(Types.BOOLEAN, Boolean.FALSE);
@@ -162,6 +166,7 @@
final HashMap<Integer,Integer> precisions =
new HashMap<Integer,Integer>();
+ precisions.put(Types.ARRAY, 0);
precisions.put(Types.BIGINT, 64);
precisions.put(Types.BIT, 1);
precisions.put(Types.BOOLEAN, 1);
@@ -189,6 +194,7 @@
// JDBC type scales
final HashMap<Integer,Integer> scales = new HashMap<Integer,Integer>();
+ scales.put(Types.ARRAY, 0);
scales.put(Types.BIGINT, 0);
scales.put(Types.BIT, 0);
scales.put(Types.BOOLEAN, 0);
@@ -298,6 +298,11 @@ public static ParameterDef Decimal(final BigDecimal bd) {
return Scaled(Types.DECIMAL, bd.scale());
} // end of Decimal
+ /**
+ * Array definition
+ */
+ public static final ParameterDef Array = Default(Types.ARRAY);
+
/**
* String definition
*/
@@ -583,7 +583,7 @@ public void setClob(final int parameterIndex, final Clob clob)
public void setArray(final int parameterIndex, final Array x)
throws SQLException {
- throw new SQLFeatureNotSupportedException();
+ setParam(parameterIndex, acolyte.jdbc.ParameterMetaData.Array, x);
} // end of setArray
/**
@@ -974,6 +974,7 @@ private void setParam(final int index,
*/
private String normalizeClassName(final Class<?> c) {
if (Blob.class.isAssignableFrom(c)) return "java.sql.Blob";
+ else if (Array.class.isAssignableFrom(c)) return "java.sql.Array";
return c.getName();
} // end of normalizeClassName
@@ -14,6 +14,7 @@ import org.specs2.mutable.Specification
import acolyte.jdbc.ParameterMetaData.{
ParameterDef Param,
Binary,
+ Array => ArrayP,
Blob BlobP,
Bool BoolP,
Byte ByteP,
@@ -227,6 +228,12 @@ object ParameterMetaDataSpec
}
}
+ "Array parameter" should {
+ "be default one" in {
+ ArrayP aka "array parameter" mustEqual DefaultP(Types.ARRAY)
+ }
+ }
+
"Binary parameter" should {
"be default one" in {
Binary aka "binary parameter" mustEqual DefaultP(Types.BINARY)
@@ -16,6 +16,8 @@ import org.specs2.mutable.Specification
import org.apache.commons.io.IOUtils.contentEquals
+import scala.collection.JavaConversions
+
import acolyte.jdbc.StatementHandler.Parameter
import acolyte.jdbc.test.{ EmptyConnectionHandler, Params }
@@ -61,8 +63,6 @@ trait StatementSpecification[S <: PreparedStatement] extends Setters {
aka("setter") must throwA[SQLFeatureNotSupportedException]).
and(statement().setClob(0, null.asInstanceOf[java.sql.Clob]).
aka("setter") must throwA[SQLFeatureNotSupportedException]).
- and(statement().setArray(0, null).
- aka("setter") must throwA[SQLFeatureNotSupportedException]).
and(statement().setURL(0, null).
aka("setter") must throwA[SQLFeatureNotSupportedException]).
and(statement().setRowId(0, null).
@@ -321,6 +321,63 @@ trait StatementSpecification[S <: PreparedStatement] extends Setters {
}
}
+ "Array" should {
+ val stringArray = ImmutableArray.getInstance(classOf[String],
+ JavaConversions.seqAsJavaList(List("A", "B")))
+
+ "be set as first parameter" in {
+ lazy val s = statement()
+ s.setArray(1, stringArray)
+
+ lazy val m = s.getParameterMetaData
+
+ (m.getParameterCount aka "count" mustEqual 1).
+ and(m.getParameterType(1) aka "SQL type" mustEqual Types.ARRAY)
+
+ }
+
+ "be set as first object with SQL type" in {
+ lazy val s = statement()
+ s.setObject(1, stringArray, Types.ARRAY)
+
+ lazy val m = s.getParameterMetaData
+
+ (m.getParameterCount aka "count" mustEqual 1).
+ and(m.getParameterType(1) aka "SQL type" mustEqual Types.ARRAY)
+
+ }
+
+ "be set as first object with SQL type and scale" in {
+ lazy val s = statement()
+ s.setObject(1, stringArray, Types.ARRAY, 1)
+
+ lazy val m = s.getParameterMetaData
+
+ (m.getParameterCount aka "count" mustEqual 1).
+ and(m.getParameterType(1) aka "SQL type" mustEqual Types.ARRAY)
+
+ }
+
+ "be set as first object without SQL type" in {
+ lazy val s = statement()
+ s.setObject(1, stringArray)
+
+ lazy val m = s.getParameterMetaData
+
+ (m.getParameterCount aka "count" mustEqual 1).
+ and(m.getParameterType(1) aka "SQL type" mustEqual Types.ARRAY)
+
+ }
+
+ "be properly prepared" in {
+ (executeUpdate("TEST ?, y", Types.ARRAY, stringArray).
+ aka("SQL update") mustEqual ("TEST ?, y" -> stringArray)).
+ and(executeQuery("SELECT ? WHERE true", Types.ARRAY, stringArray).
+ aka("SQL query") mustEqual ("SELECT ? WHERE true" -> stringArray))
+
+ }
+ }
+
"Binary Large Object" should {
"be set as first parameter" in {
lazy val s = statement()
@@ -1679,9 +1736,19 @@ sealed trait StatementParam[A] {
sealed trait Setters {
import java.math.BigDecimal
import java.util.Calendar
- import java.sql.{ Date, Time, Timestamp }
+ import java.sql.{ Array => SqlArray, Date, Time, Timestamp }
import org.apache.commons.lang3.tuple.ImmutablePair
+ implicit def StmtArray[A <: SqlArray]: StatementParam[A] =
+ new StatementParam[A] {
+ def set(s: PreparedStatement, i: Int, p: A, t: Int) = {
+ s.setArray(i, p)
+ s
+ }
+
+ def get(p: Parameter): A = p.right.asInstanceOf[A]
+ }
+
implicit def StmtBytes: StatementParam[Array[Byte]] =
new StatementParam[Array[Byte]] {
def set(s: PreparedStatement, i: Int, p: Array[Byte], t: Int) = {
View
@@ -10,7 +10,7 @@ object Acolyte extends Build with Dependencies
aggregate(scalacPlugin, reactiveMongo, jdbcDriver, jdbcScala, studio).
settings(
organization in ThisBuild := "org.eu.acolyte",
- version in ThisBuild := "1.0.27",
+ version in ThisBuild := "1.0.28",
javaOptions in ThisBuild ++= Seq("-source", "1.6", "-target", "1.6"),
scalaVersion in ThisBuild := "2.10.4",
crossScalaVersions in ThisBuild := Seq("2.10.4", "2.11.2"),

0 comments on commit ca0470e

Please sign in to comment.