Skip to content

Commit

Permalink
[CONJ-1205] permit use of Array parameter
Browse files Browse the repository at this point in the history
  • Loading branch information
rusher committed Oct 20, 2024
1 parent a54a87e commit 3e94848
Show file tree
Hide file tree
Showing 17 changed files with 430 additions and 31 deletions.
15 changes: 14 additions & 1 deletion src/main/java/org/mariadb/jdbc/BasePreparedStatement.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import org.mariadb.jdbc.message.server.OkPacket;
import org.mariadb.jdbc.message.server.PrepareResultPacket;
import org.mariadb.jdbc.plugin.Codec;
import org.mariadb.jdbc.plugin.array.FloatArray;
import org.mariadb.jdbc.plugin.codec.*;
import org.mariadb.jdbc.util.ParameterList;
import org.mariadb.jdbc.util.constants.ColumnFlags;
Expand Down Expand Up @@ -756,7 +757,19 @@ public void setClob(int parameterIndex, Clob x) throws SQLException {
*/
@Override
public void setArray(int parameterIndex, Array x) throws SQLException {
throw exceptionFactory().notSupported("Array parameter are not supported");
checkIndex(parameterIndex);
if (x == null) {
parameters.set(parameterIndex - 1, Parameter.NULL_PARAMETER);
return;
}
if (x instanceof FloatArray) {
parameters.set(
parameterIndex - 1, new Parameter<>(FloatArrayCodec.INSTANCE, (float[]) x.getArray()));
return;
}
throw exceptionFactory()
.notSupported(
String.format("this type of Array parameter %s is not supported", x.getClass()));
}

/**
Expand Down
34 changes: 33 additions & 1 deletion src/main/java/org/mariadb/jdbc/Connection.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
// Copyright (c) 2015-2024 MariaDB Corporation Ab
package org.mariadb.jdbc;

import java.nio.FloatBuffer;
import java.sql.*;
import java.util.*;
import java.util.concurrent.Executor;
Expand All @@ -19,6 +20,7 @@
import org.mariadb.jdbc.message.client.PingPacket;
import org.mariadb.jdbc.message.client.QueryPacket;
import org.mariadb.jdbc.message.client.ResetPacket;
import org.mariadb.jdbc.plugin.array.FloatArray;
import org.mariadb.jdbc.util.NativeSql;
import org.mariadb.jdbc.util.constants.Capabilities;
import org.mariadb.jdbc.util.constants.CatalogTerm;
Expand Down Expand Up @@ -742,7 +744,37 @@ public void setClientInfo(Properties properties) {

@Override
public Array createArrayOf(String typeName, Object[] elements) throws SQLException {
throw exceptionFactory.notSupported("Array type is not supported");
return createArrayOf(typeName, (Object) elements);
}

public Array createArrayOf(String typeName, Object elements) throws SQLException {
if (typeName == null) throw exceptionFactory.notSupported("typeName is not mandatory");
if (elements == null) return null;

switch (typeName) {
case "float":
case "Float":
if (float[].class.equals(elements.getClass())) {
return new FloatArray((float[]) elements, client.getContext());
}
if (Float[].class.equals(elements.getClass())) {
float[] result =
Arrays.stream(((Float[]) elements))
.collect(
() -> FloatBuffer.allocate(((Float[]) elements).length),
FloatBuffer::put,
(left, right) -> {
throw new UnsupportedOperationException();
})
.array();
return new FloatArray(result, client.getContext());
}
throw exceptionFactory.notSupported(
"elements class is expect to be float[]/Float[] for 'float/Float' typeName");
default:
throw exceptionFactory.notSupported(
String.format("typeName %s is not supported", typeName));
}
}

@Override
Expand Down
17 changes: 14 additions & 3 deletions src/main/java/org/mariadb/jdbc/client/result/Result.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import org.mariadb.jdbc.export.ExceptionFactory;
import org.mariadb.jdbc.message.server.ErrorPacket;
import org.mariadb.jdbc.plugin.Codec;
import org.mariadb.jdbc.plugin.array.FloatArray;
import org.mariadb.jdbc.plugin.codec.*;
import org.mariadb.jdbc.util.constants.ServerStatus;

Expand Down Expand Up @@ -1236,7 +1237,17 @@ public Clob getClob(int columnIndex) throws SQLException {

@Override
public Array getArray(int columnIndex) throws SQLException {
throw exceptionFactory.notSupported("Method ResultSet.getArray not supported");
checkIndex(columnIndex);
fieldLength.set(
rowDecoder.setPosition(
columnIndex - 1, fieldIndex, maxIndex, rowBuf, nullBitmap, metadataList));
if (fieldLength.get() == NULL_LENGTH) {
return null;
}
float[] val =
rowDecoder.decode(
FloatArrayCodec.INSTANCE, null, rowBuf, fieldLength, metadataList, fieldIndex, context);
return new FloatArray(val, context);
}

@Override
Expand Down Expand Up @@ -1265,7 +1276,7 @@ public Clob getClob(String columnLabel) throws SQLException {

@Override
public Array getArray(String columnLabel) throws SQLException {
throw exceptionFactory.notSupported("Method ResultSet.getArray not supported");
return getArray(findColumn(columnLabel));
}

@Override
Expand Down Expand Up @@ -1382,7 +1393,7 @@ public void updateArray(int columnIndex, Array x) throws SQLException {

@Override
public void updateArray(String columnLabel, Array x) throws SQLException {
throw exceptionFactory.notSupported("Array are not supported");
updateArray(findColumn(columnLabel), x);
}

@Override
Expand Down
13 changes: 13 additions & 0 deletions src/main/java/org/mariadb/jdbc/client/result/UpdatableResult.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import org.mariadb.jdbc.client.result.rowdecoder.BinaryRowDecoder;
import org.mariadb.jdbc.codec.*;
import org.mariadb.jdbc.plugin.Codec;
import org.mariadb.jdbc.plugin.array.FloatArray;
import org.mariadb.jdbc.plugin.codec.*;
import org.mariadb.jdbc.util.ParameterList;

Expand Down Expand Up @@ -291,6 +292,18 @@ public void updateTime(int columnIndex, Time x) throws SQLException {
parameters.set(columnIndex - 1, new Parameter<>(TimeCodec.INSTANCE, x));
}

@Override
public void updateArray(int columnIndex, Array x) throws SQLException {
checkUpdatable(columnIndex);
if (x instanceof FloatArray) {
parameters.set(
columnIndex - 1, new Parameter<>(FloatArrayCodec.INSTANCE, (float[]) x.getArray()));
return;
}
throw exceptionFactory.notSupported(
String.format("this type of Array parameter %s is not supported", x.getClass()));
}

@Override
public void updateTimestamp(int columnIndex, Timestamp x) throws SQLException {
checkUpdatable(columnIndex);
Expand Down
119 changes: 119 additions & 0 deletions src/main/java/org/mariadb/jdbc/plugin/array/FloatArray.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
// SPDX-License-Identifier: LGPL-2.1-or-later
// Copyright (c) 2012-2014 Monty Program Ab
// Copyright (c) 2015-2024 MariaDB Corporation Ab
package org.mariadb.jdbc.plugin.array;

import java.nio.charset.StandardCharsets;
import java.sql.*;
import java.util.Arrays;
import java.util.Map;
import org.mariadb.jdbc.client.ColumnDecoder;
import org.mariadb.jdbc.client.Context;
import org.mariadb.jdbc.client.DataType;
import org.mariadb.jdbc.client.result.CompleteResult;
import org.mariadb.jdbc.util.constants.ColumnFlags;

public class FloatArray implements Array {

private final float[] val;
private Context context;

public FloatArray(float[] val, Context context) {
this.val = val;
this.context = context;
}

@Override
public String getBaseTypeName() throws SQLException {
return "float[]";
}

@Override
public int getBaseType() throws SQLException {
return Types.FLOAT;
}

@Override
public Object getArray() throws SQLException {
return this.val;
}

@Override
public Object getArray(Map<String, Class<?>> map) throws SQLException {
throw new SQLFeatureNotSupportedException(
"getArray(Map<String, Class<?>> map) is not supported");
}

@Override
public Object getArray(long index, int count) throws SQLException {
if (index < 1 || index > val.length) {
throw new SQLException(
String.format(
"Wrong index position. Is %s but must be in 1-%s range", index, val.length));
}
if (count < 0 || (index - 1 + count) > val.length) {
throw new SQLException(
String.format(
"Count value is too big. Count is %s but cannot be > to %s",
count, val.length - (index - 1)));
}

return Arrays.copyOfRange(val, (int) index - 1, (int) (index - 1) + count);
}

@Override
public Object getArray(long index, int count, Map<String, Class<?>> map) throws SQLException {
throw new SQLFeatureNotSupportedException(
"getArray(long index, int count, Map<String, Class<?>> map) is not supported");
}

@Override
public ResultSet getResultSet() throws SQLException {
return getResultSet(1, this.val.length);
}

@Override
public ResultSet getResultSet(Map<String, Class<?>> map) throws SQLException {
throw new SQLFeatureNotSupportedException(
"getResultSet(Map<String, Class<?>> map) is not supported");
}

@Override
public ResultSet getResultSet(long index, int count) throws SQLException {
byte[][] rows = new byte[count][];
for (int i = 0; i < count; i++) {
rows[i] = Float.toString(this.val[(int) index - 1 + i]).getBytes(StandardCharsets.US_ASCII);
}

return new CompleteResult(
new ColumnDecoder[] {ColumnDecoder.create("Array", DataType.FLOAT, ColumnFlags.NOT_NULL)},
rows,
context,
ResultSet.TYPE_SCROLL_INSENSITIVE);
}

@Override
public ResultSet getResultSet(long index, int count, Map<String, Class<?>> map)
throws SQLException {
throw new SQLFeatureNotSupportedException(
"getResultSet(long index, int count, Map<String, Class<?>> map) is not supported");
}

@Override
public void free() {}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;

FloatArray that = (FloatArray) o;

return Arrays.equals(val, that.val);
}

@Override
public int hashCode() {
return Arrays.hashCode(val);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ private byte[] getBytes(ReadableByteBuf buf, MutableInt length, ColumnDecoder co
default:
buf.skip(length.get());
throw new SQLDataException(
String.format("Data type %s cannot be decoded as byte[]", column.getType()));
String.format("Data type %s cannot be decoded as float[]", column.getType()));
}
}

Expand All @@ -131,7 +131,9 @@ public void encodeBinary(
final Calendar cal,
final Long maxLength)
throws IOException {
encoder.writeBytes(toByteArray((float[]) value));
byte[] arr = toByteArray((float[]) value);
encoder.writeLength(arr.length);
encoder.writeBytes(arr);
}

public int getBinaryEncodeType() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ private byte[] getBytes(ReadableByteBuf buf, MutableInt length, ColumnDecoder co
default:
buf.skip(length.get());
throw new SQLDataException(
String.format("Data type %s cannot be decoded as byte[]", column.getType()));
String.format("Data type %s cannot be decoded as float[]", column.getType()));
}
}

Expand All @@ -151,7 +151,9 @@ public void encodeBinary(
final Calendar cal,
final Long maxLength)
throws IOException {
encoder.writeBytes(toByteArray((Float[]) value));
byte[] arr = toByteArray((Float[]) value);
encoder.writeLength(arr.length);
encoder.writeBytes(arr);
}

public int getBinaryEncodeType() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -398,7 +398,8 @@ public void checkFixedData() throws SQLException {
assertTrue(sharedConn.createClob() instanceof Clob);
assertTrue(sharedConn.createNClob() instanceof NClob);
assertThrows(SQLException.class, () -> sharedConn.createSQLXML());
assertThrows(SQLException.class, () -> sharedConn.createArrayOf("", null));
assertNull(sharedConn.createArrayOf("", null));
assertThrows(SQLException.class, () -> sharedConn.createArrayOf("string", "ddd"));
assertThrows(SQLException.class, () -> sharedConn.createStruct("", null));
assertNull(sharedConn.getSchema());
sharedConn.setSchema("fff");
Expand Down
Loading

0 comments on commit 3e94848

Please sign in to comment.