Skip to content
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")
})
}

}
}

0 comments on commit 210e6d1

Please sign in to comment.
You can’t perform that action at this time.