Permalink
Browse files

[jdbc-driver] Array support in query result:

```java
import acolyte.RowLists;
import acolyte.ImmutableArray;

// List of row with 1 column,
// whose type is array of string
RowLists.rowList1(java.sql.Array.class).
  append(ImmutableArray.getInstance(String.class,
    new String[] { "Ab", "Cd", "Ef" }));
```
  • Loading branch information...
cchantep
cchantep committed Jun 22, 2014
1 parent 57c38c2 commit 210e6d17602af672fe4154b11d1009580cce01a3
@@ -1,11 +1,16 @@
package acolyte;
+import org.apache.commons.lang3.builder.HashCodeBuilder;
+import org.apache.commons.lang3.builder.EqualsBuilder;
+
/**
* Column meta data.
*
* @author Cedric Chantepie
*/
public final class Column<T> {
+ // --- Properties ---
+
/**
* Column class
*/
@@ -62,4 +67,42 @@
public Column withNullable(final boolean nullable) {
return new Column(this.columnClass, this.name, nullable);
} // end of withNullable
+
+ // --- Object support ---
+
+ /**
+ * {@inheritDoc}
+ */
+ public int hashCode() {
+ return new HashCodeBuilder(9, 3).
+ append(this.columnClass).append(this.name).append(this.nullable).
+ toHashCode();
+
+ } // end of hashCode
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean equals(final Object o) {
+ if (o == null || !(o instanceof Column)) {
+ return false;
+ } // end of if
+
+ final Column other = (Column) o;
+
+ return new EqualsBuilder().
+ append(this.columnClass, other.columnClass).
+ append(this.name, other.name).
+ append(this.nullable, other.nullable).isEquals();
+
+ } // end of equals
+
+ /**
+ * {@inheritDoc}
+ */
+ public String toString() {
+ return String.format("Column(%s, %s, %s)",
+ this.columnClass, this.name, this.nullable);
+
+ } // end of toString
} // end of class Column
@@ -663,12 +663,25 @@ public Properties getClientInfo() throws SQLException {
/**
* {@inheritDoc}
- * @throws java.sql.SQLFeatureNotSupportedException
*/
public Array createArrayOf(final String typeName,
final Object[] elements) throws SQLException {
- throw new SQLFeatureNotSupportedException();
+ final String jdbcClassName = Defaults.jdbcTypeNameClasses.get(typeName);
+
+ if (jdbcClassName == null) {
+ throw new SQLException("Unsupported type: " + typeName);
+ } // end of if
+
+ // ---
+
+ try {
+ final Class jdbcClass = Class.forName(jdbcClassName);
+
+ return ImmutableArray.getInstance(jdbcClass, elements);
+ } catch (ClassNotFoundException ce) {
+ throw new SQLException("Element type not found: " + jdbcClassName);
+ } // end of catch
} // end of createArrayOf
/**
@@ -48,6 +48,11 @@
*/
public static final Map<String,Integer> jdbcTypeClasses;
+ /**
+ * JDBC type name classes
+ */
+ public static final Map<String,String> jdbcTypeNameClasses;
+
static {
// JDBC type mappings
final HashMap<Integer,String> mappings = new HashMap<Integer,String>();
@@ -109,6 +114,15 @@
jdbcTypeNames = Collections.unmodifiableMap(names);
+ // Class for JDBC type name
+ final HashMap<String,String> nameClasses = new HashMap<String,String>();
+
+ for (final Map.Entry<Integer,String> e : jdbcTypeNames.entrySet()) {
+ nameClasses.put(e.getValue(), jdbcTypeMappings.get(e.getKey()));
+ } // end of for
+
+ jdbcTypeNameClasses = nameClasses;
+
// JDBC type signs
final HashMap<Integer,Boolean> signs = new HashMap<Integer,Boolean>();
@@ -11,12 +11,15 @@
import java.sql.ResultSet;
import java.sql.Array;
+import org.apache.commons.lang3.builder.HashCodeBuilder;
+import org.apache.commons.lang3.builder.EqualsBuilder;
+
/**
* Immu Array implementation.
*
* @author Cedric Chantepie
*/
-final class ImmutableArray<T> { //implements Array {
+public final class ImmutableArray<T> implements Array {
// --- Properties ---
/**
@@ -68,12 +71,12 @@ private ImmutableArray(final Class<T> baseClass,
/**
* Returns empty array for given base class.
*/
- protected static <A> ImmutableArray<A> getInstance(final Class<A> baseClass) { return new ImmutableArray<A>(baseClass, Collections.unmodifiableList(Collections.<A>emptyList())); }
+ public static <A> ImmutableArray<A> getInstance(final Class<A> baseClass) { return new ImmutableArray<A>(baseClass, Collections.unmodifiableList(Collections.<A>emptyList())); }
/**
* Returns array with copy of given |elements|.
*/
- protected static <A> ImmutableArray<A> getInstance(final Class<A> baseClass, final A[] elements) {
+ public static <A> ImmutableArray<A> getInstance(final Class<A> baseClass, final A[] elements) {
if (elements == null) {
throw new IllegalArgumentException("Invalid element array");
} // end of if
@@ -84,7 +87,7 @@ private ImmutableArray(final Class<T> baseClass,
/**
* Returns array with copy of given |elements|.
*/
- protected static <A> ImmutableArray<A> getInstance(final Class<A> baseClass, final List<A> elements) {
+ public static <A> ImmutableArray<A> getInstance(final Class<A> baseClass, final List<A> elements) {
if (elements == null) {
throw new IllegalArgumentException("Invalid element list");
} // end of if
@@ -113,7 +116,11 @@ public String getBaseTypeName() throws SQLException {
* {@inheritDoc}
*/
public Object getArray() throws SQLException {
- return this.elements.toArray();
+ @SuppressWarnings("Unchecked")
+ final T[] arr = (T[]) java.lang.reflect.Array.
+ newInstance(baseClass, this.elements.size());
+
+ return this.elements.toArray(arr);
} // end of getArray
/**
@@ -124,15 +131,32 @@ public Object getArray(Map<String, Class<?>> map) throws SQLException {
throw new SQLFeatureNotSupportedException();
} // end of getArray
+ /**
+ * {@inheritDoc}
+ */
+ public Object getArray(final long index, final int count)
+ throws SQLException {
+
+ final List<T> sub = subList(index, count);
- //public Object getArray(long, int) throws SQLException;
+ if (sub == null) {
+ throw new SQLException("Invalid range: " + index + " + " + count);
+ } // end of if
+
+ // ---
+
+ @SuppressWarnings("Unchecked")
+ final T[] arr = (T[]) java.lang.reflect.Array.
+ newInstance(baseClass, sub.size());
+
+ return sub.toArray(arr);
+ } // end of getArray
/**
* @throws SQLFeatureNotSupportedException as array convertion
* is not supported
*/
- public Object getArray(long index,
- int count,
+ public Object getArray(long index, int count,
Map<String, Class<?>> map) throws SQLException {
throw new SQLFeatureNotSupportedException();
@@ -149,6 +173,28 @@ public ResultSet getResultSet() throws SQLException {
return rows.resultSet();
} // end of getResultSet
+ /**
+ * {@inheritDoc}
+ */
+ public ResultSet getResultSet(final long index, final int count)
+ throws SQLException {
+
+ // TODO: Test
+ final List<T> sub = subList(index, count);
+
+ if (sub == null) {
+ throw new SQLException("Invalid range: " + index + " + " + count);
+ } // end of if
+
+ // ---
+
+ RowList1<T,?> rows = RowLists.rowList1(this.baseClass);
+
+ for (final T elmt : sub) rows = rows.append(elmt);
+
+ return rows.resultSet();
+ } // end of getResultSet
+
/**
* @throws SQLFeatureNotSupportedException as array convertion
* is not supported
@@ -158,8 +204,6 @@ public ResultSet getResultSet(Map<String, Class<?>> map)
throw new SQLFeatureNotSupportedException();
} // end of getResultSet
- // public ResultSet getResultSet(long, int) throws SQLException;
-
/**
* @throws SQLFeatureNotSupportedException as array convertion
* is not supported
@@ -177,12 +221,61 @@ public ResultSet getResultSet(long index,
*/
public void free() throws SQLException {}
+ // --- Object support ---
+
+ /**
+ * {@inheritDoc}
+ */
+ public int hashCode() {
+ return new HashCodeBuilder(11, 7).
+ append(this.baseClass).append(this.baseType).
+ append(this.baseTypeName).append(this.elements).
+ toHashCode();
+
+ } // end of hashCode
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean equals(final Object o) {
+ if (o == null || !(o instanceof ImmutableArray)) {
+ return false;
+ } // end of if
+
+ final ImmutableArray<?> other = (ImmutableArray<?>) o;
+
+ return new EqualsBuilder().
+ append(this.baseClass, other.baseClass).
+ append(this.baseType, other.baseType).
+ append(this.baseTypeName, other.baseTypeName).
+ append(this.elements, other.elements).
+ isEquals();
+
+ } // end of equals
+
+ /**
+ * {@inheritDoc}
+ */
+ public String toString() {
+ return String.format("ImmutableArray(%s)", this.elements);
+ } // end of toString
+
// ---
/**
* Returns sub-list, or null if |index| is not valid.
*/
private List<T> subList(final long index, int count) {
- return null;
+ final int len = this.elements.size();
+
+ if (index < 0 || index >= len || count < 0) {
+ return null;
+ } // end of if
+
+ // ---
+
+ final long end = (index+count > len) ? len+1 : index+count;
+
+ return this.elements.subList((int)index, (int)end);
} // end of subList
} // end of class ImmutableArray
@@ -500,7 +500,13 @@ public Array getArray(final int columnIndex) throws SQLException {
return null;
} // end of if
- throw new RuntimeException("Not implemented");
+ // ---
+
+ try {
+ return convert(val, Array.class);
+ } catch (SQLException e) {
+ throw new SQLException("Not an Array: " + columnIndex);
+ } // end of catch
} // end of getArray
/**
@@ -513,7 +519,13 @@ public Array getArray(final String columnLabel) throws SQLException {
return null;
} // end of if
- throw new RuntimeException("Not implemented");
+ // ---
+
+ try {
+ return convert(val, Array.class);
+ } catch (SQLException e) {
+ throw new SQLException("Not an Array: " + columnLabel);
+ } // end of catch
} // end of getArray
/**
@@ -1166,6 +1178,22 @@ public int findColumn(final String columnLabel) throws SQLException {
throw new SQLException("Fails to convert numeric type");
} // end of if
+ if (Array.class.isAssignableFrom(type)) {
+ if (val instanceof Array) {
+ return (T) val;
+ } // end of if
+
+ final Class c = val.getClass();
+
+ if (c.isArray()) {
+ return (T) ImmutableArray.
+ getInstance(c.getComponentType(), (Object[]) val);
+
+ } // end of if
+
+ throw new SQLException("Fails to convert array");
+ } // end of if
+
throw new SQLException("Incompatible type: " + type + ", " + clazz);
} // end of convert
@@ -7,7 +7,8 @@ import java.sql.{
ResultSet,
SQLClientInfoException,
SQLException,
- SQLFeatureNotSupportedException
+ SQLFeatureNotSupportedException,
+ Types
}
import java.sql.ResultSet.{
TYPE_FORWARD_ONLY,
@@ -540,9 +541,20 @@ object ConnectionSpec extends Specification with ConnectionFixtures {
}
- "not be supported for ARRAY" in {
- defaultCon.createArrayOf("CHAR", Array[Object]()).
- aka("create array") must throwA[SQLFeatureNotSupportedException]
+ "be supported for ARRAY" in {
+ defaultCon.createArrayOf("VARCHAR", Array("Ab", "cD", "EF")).
+ aka("array") must beLike {
+ case strArr
+ (strArr.getBaseType aka "base type" mustEqual Types.VARCHAR) and
+ (strArr.getBaseTypeName aka "base type name" mustEqual "VARCHAR").
+ and(strArr.getArray aka "element array" must beLike {
+ case elmts: Array[String]
+ (elmts.size aka "size" must_== 3) and
+ (elmts(0) aka "1st element" must_== "Ab") and
+ (elmts(1) aka "2nd element" must_== "cD") and
+ (elmts(2) aka "3rd element" must_== "EF")
+ })
+ }
}
}
Oops, something went wrong.

0 comments on commit 210e6d1

Please sign in to comment.