Skip to content

Commit 3e94848

Browse files
committed
[CONJ-1205] permit use of Array parameter
1 parent a54a87e commit 3e94848

17 files changed

+430
-31
lines changed

src/main/java/org/mariadb/jdbc/BasePreparedStatement.java

+14-1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import org.mariadb.jdbc.message.server.OkPacket;
3030
import org.mariadb.jdbc.message.server.PrepareResultPacket;
3131
import org.mariadb.jdbc.plugin.Codec;
32+
import org.mariadb.jdbc.plugin.array.FloatArray;
3233
import org.mariadb.jdbc.plugin.codec.*;
3334
import org.mariadb.jdbc.util.ParameterList;
3435
import org.mariadb.jdbc.util.constants.ColumnFlags;
@@ -756,7 +757,19 @@ public void setClob(int parameterIndex, Clob x) throws SQLException {
756757
*/
757758
@Override
758759
public void setArray(int parameterIndex, Array x) throws SQLException {
759-
throw exceptionFactory().notSupported("Array parameter are not supported");
760+
checkIndex(parameterIndex);
761+
if (x == null) {
762+
parameters.set(parameterIndex - 1, Parameter.NULL_PARAMETER);
763+
return;
764+
}
765+
if (x instanceof FloatArray) {
766+
parameters.set(
767+
parameterIndex - 1, new Parameter<>(FloatArrayCodec.INSTANCE, (float[]) x.getArray()));
768+
return;
769+
}
770+
throw exceptionFactory()
771+
.notSupported(
772+
String.format("this type of Array parameter %s is not supported", x.getClass()));
760773
}
761774

762775
/**

src/main/java/org/mariadb/jdbc/Connection.java

+33-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
// Copyright (c) 2015-2024 MariaDB Corporation Ab
44
package org.mariadb.jdbc;
55

6+
import java.nio.FloatBuffer;
67
import java.sql.*;
78
import java.util.*;
89
import java.util.concurrent.Executor;
@@ -19,6 +20,7 @@
1920
import org.mariadb.jdbc.message.client.PingPacket;
2021
import org.mariadb.jdbc.message.client.QueryPacket;
2122
import org.mariadb.jdbc.message.client.ResetPacket;
23+
import org.mariadb.jdbc.plugin.array.FloatArray;
2224
import org.mariadb.jdbc.util.NativeSql;
2325
import org.mariadb.jdbc.util.constants.Capabilities;
2426
import org.mariadb.jdbc.util.constants.CatalogTerm;
@@ -742,7 +744,37 @@ public void setClientInfo(Properties properties) {
742744

743745
@Override
744746
public Array createArrayOf(String typeName, Object[] elements) throws SQLException {
745-
throw exceptionFactory.notSupported("Array type is not supported");
747+
return createArrayOf(typeName, (Object) elements);
748+
}
749+
750+
public Array createArrayOf(String typeName, Object elements) throws SQLException {
751+
if (typeName == null) throw exceptionFactory.notSupported("typeName is not mandatory");
752+
if (elements == null) return null;
753+
754+
switch (typeName) {
755+
case "float":
756+
case "Float":
757+
if (float[].class.equals(elements.getClass())) {
758+
return new FloatArray((float[]) elements, client.getContext());
759+
}
760+
if (Float[].class.equals(elements.getClass())) {
761+
float[] result =
762+
Arrays.stream(((Float[]) elements))
763+
.collect(
764+
() -> FloatBuffer.allocate(((Float[]) elements).length),
765+
FloatBuffer::put,
766+
(left, right) -> {
767+
throw new UnsupportedOperationException();
768+
})
769+
.array();
770+
return new FloatArray(result, client.getContext());
771+
}
772+
throw exceptionFactory.notSupported(
773+
"elements class is expect to be float[]/Float[] for 'float/Float' typeName");
774+
default:
775+
throw exceptionFactory.notSupported(
776+
String.format("typeName %s is not supported", typeName));
777+
}
746778
}
747779

748780
@Override

src/main/java/org/mariadb/jdbc/client/result/Result.java

+14-3
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import org.mariadb.jdbc.export.ExceptionFactory;
2626
import org.mariadb.jdbc.message.server.ErrorPacket;
2727
import org.mariadb.jdbc.plugin.Codec;
28+
import org.mariadb.jdbc.plugin.array.FloatArray;
2829
import org.mariadb.jdbc.plugin.codec.*;
2930
import org.mariadb.jdbc.util.constants.ServerStatus;
3031

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

12371238
@Override
12381239
public Array getArray(int columnIndex) throws SQLException {
1239-
throw exceptionFactory.notSupported("Method ResultSet.getArray not supported");
1240+
checkIndex(columnIndex);
1241+
fieldLength.set(
1242+
rowDecoder.setPosition(
1243+
columnIndex - 1, fieldIndex, maxIndex, rowBuf, nullBitmap, metadataList));
1244+
if (fieldLength.get() == NULL_LENGTH) {
1245+
return null;
1246+
}
1247+
float[] val =
1248+
rowDecoder.decode(
1249+
FloatArrayCodec.INSTANCE, null, rowBuf, fieldLength, metadataList, fieldIndex, context);
1250+
return new FloatArray(val, context);
12401251
}
12411252

12421253
@Override
@@ -1265,7 +1276,7 @@ public Clob getClob(String columnLabel) throws SQLException {
12651276

12661277
@Override
12671278
public Array getArray(String columnLabel) throws SQLException {
1268-
throw exceptionFactory.notSupported("Method ResultSet.getArray not supported");
1279+
return getArray(findColumn(columnLabel));
12691280
}
12701281

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

13831394
@Override
13841395
public void updateArray(String columnLabel, Array x) throws SQLException {
1385-
throw exceptionFactory.notSupported("Array are not supported");
1396+
updateArray(findColumn(columnLabel), x);
13861397
}
13871398

13881399
@Override

src/main/java/org/mariadb/jdbc/client/result/UpdatableResult.java

+13
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import org.mariadb.jdbc.client.result.rowdecoder.BinaryRowDecoder;
2121
import org.mariadb.jdbc.codec.*;
2222
import org.mariadb.jdbc.plugin.Codec;
23+
import org.mariadb.jdbc.plugin.array.FloatArray;
2324
import org.mariadb.jdbc.plugin.codec.*;
2425
import org.mariadb.jdbc.util.ParameterList;
2526

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

295+
@Override
296+
public void updateArray(int columnIndex, Array x) throws SQLException {
297+
checkUpdatable(columnIndex);
298+
if (x instanceof FloatArray) {
299+
parameters.set(
300+
columnIndex - 1, new Parameter<>(FloatArrayCodec.INSTANCE, (float[]) x.getArray()));
301+
return;
302+
}
303+
throw exceptionFactory.notSupported(
304+
String.format("this type of Array parameter %s is not supported", x.getClass()));
305+
}
306+
294307
@Override
295308
public void updateTimestamp(int columnIndex, Timestamp x) throws SQLException {
296309
checkUpdatable(columnIndex);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
// SPDX-License-Identifier: LGPL-2.1-or-later
2+
// Copyright (c) 2012-2014 Monty Program Ab
3+
// Copyright (c) 2015-2024 MariaDB Corporation Ab
4+
package org.mariadb.jdbc.plugin.array;
5+
6+
import java.nio.charset.StandardCharsets;
7+
import java.sql.*;
8+
import java.util.Arrays;
9+
import java.util.Map;
10+
import org.mariadb.jdbc.client.ColumnDecoder;
11+
import org.mariadb.jdbc.client.Context;
12+
import org.mariadb.jdbc.client.DataType;
13+
import org.mariadb.jdbc.client.result.CompleteResult;
14+
import org.mariadb.jdbc.util.constants.ColumnFlags;
15+
16+
public class FloatArray implements Array {
17+
18+
private final float[] val;
19+
private Context context;
20+
21+
public FloatArray(float[] val, Context context) {
22+
this.val = val;
23+
this.context = context;
24+
}
25+
26+
@Override
27+
public String getBaseTypeName() throws SQLException {
28+
return "float[]";
29+
}
30+
31+
@Override
32+
public int getBaseType() throws SQLException {
33+
return Types.FLOAT;
34+
}
35+
36+
@Override
37+
public Object getArray() throws SQLException {
38+
return this.val;
39+
}
40+
41+
@Override
42+
public Object getArray(Map<String, Class<?>> map) throws SQLException {
43+
throw new SQLFeatureNotSupportedException(
44+
"getArray(Map<String, Class<?>> map) is not supported");
45+
}
46+
47+
@Override
48+
public Object getArray(long index, int count) throws SQLException {
49+
if (index < 1 || index > val.length) {
50+
throw new SQLException(
51+
String.format(
52+
"Wrong index position. Is %s but must be in 1-%s range", index, val.length));
53+
}
54+
if (count < 0 || (index - 1 + count) > val.length) {
55+
throw new SQLException(
56+
String.format(
57+
"Count value is too big. Count is %s but cannot be > to %s",
58+
count, val.length - (index - 1)));
59+
}
60+
61+
return Arrays.copyOfRange(val, (int) index - 1, (int) (index - 1) + count);
62+
}
63+
64+
@Override
65+
public Object getArray(long index, int count, Map<String, Class<?>> map) throws SQLException {
66+
throw new SQLFeatureNotSupportedException(
67+
"getArray(long index, int count, Map<String, Class<?>> map) is not supported");
68+
}
69+
70+
@Override
71+
public ResultSet getResultSet() throws SQLException {
72+
return getResultSet(1, this.val.length);
73+
}
74+
75+
@Override
76+
public ResultSet getResultSet(Map<String, Class<?>> map) throws SQLException {
77+
throw new SQLFeatureNotSupportedException(
78+
"getResultSet(Map<String, Class<?>> map) is not supported");
79+
}
80+
81+
@Override
82+
public ResultSet getResultSet(long index, int count) throws SQLException {
83+
byte[][] rows = new byte[count][];
84+
for (int i = 0; i < count; i++) {
85+
rows[i] = Float.toString(this.val[(int) index - 1 + i]).getBytes(StandardCharsets.US_ASCII);
86+
}
87+
88+
return new CompleteResult(
89+
new ColumnDecoder[] {ColumnDecoder.create("Array", DataType.FLOAT, ColumnFlags.NOT_NULL)},
90+
rows,
91+
context,
92+
ResultSet.TYPE_SCROLL_INSENSITIVE);
93+
}
94+
95+
@Override
96+
public ResultSet getResultSet(long index, int count, Map<String, Class<?>> map)
97+
throws SQLException {
98+
throw new SQLFeatureNotSupportedException(
99+
"getResultSet(long index, int count, Map<String, Class<?>> map) is not supported");
100+
}
101+
102+
@Override
103+
public void free() {}
104+
105+
@Override
106+
public boolean equals(Object o) {
107+
if (this == o) return true;
108+
if (o == null || getClass() != o.getClass()) return false;
109+
110+
FloatArray that = (FloatArray) o;
111+
112+
return Arrays.equals(val, that.val);
113+
}
114+
115+
@Override
116+
public int hashCode() {
117+
return Arrays.hashCode(val);
118+
}
119+
}

src/main/java/org/mariadb/jdbc/plugin/codec/FloatArrayCodec.java

+4-2
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ private byte[] getBytes(ReadableByteBuf buf, MutableInt length, ColumnDecoder co
107107
default:
108108
buf.skip(length.get());
109109
throw new SQLDataException(
110-
String.format("Data type %s cannot be decoded as byte[]", column.getType()));
110+
String.format("Data type %s cannot be decoded as float[]", column.getType()));
111111
}
112112
}
113113

@@ -131,7 +131,9 @@ public void encodeBinary(
131131
final Calendar cal,
132132
final Long maxLength)
133133
throws IOException {
134-
encoder.writeBytes(toByteArray((float[]) value));
134+
byte[] arr = toByteArray((float[]) value);
135+
encoder.writeLength(arr.length);
136+
encoder.writeBytes(arr);
135137
}
136138

137139
public int getBinaryEncodeType() {

src/main/java/org/mariadb/jdbc/plugin/codec/FloatObjectArrayCodec.java

+4-2
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ private byte[] getBytes(ReadableByteBuf buf, MutableInt length, ColumnDecoder co
127127
default:
128128
buf.skip(length.get());
129129
throw new SQLDataException(
130-
String.format("Data type %s cannot be decoded as byte[]", column.getType()));
130+
String.format("Data type %s cannot be decoded as float[]", column.getType()));
131131
}
132132
}
133133

@@ -151,7 +151,9 @@ public void encodeBinary(
151151
final Calendar cal,
152152
final Long maxLength)
153153
throws IOException {
154-
encoder.writeBytes(toByteArray((Float[]) value));
154+
byte[] arr = toByteArray((Float[]) value);
155+
encoder.writeLength(arr.length);
156+
encoder.writeBytes(arr);
155157
}
156158

157159
public int getBinaryEncodeType() {

src/test/java/org/mariadb/jdbc/integration/ConnectionTest.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -398,7 +398,8 @@ public void checkFixedData() throws SQLException {
398398
assertTrue(sharedConn.createClob() instanceof Clob);
399399
assertTrue(sharedConn.createNClob() instanceof NClob);
400400
assertThrows(SQLException.class, () -> sharedConn.createSQLXML());
401-
assertThrows(SQLException.class, () -> sharedConn.createArrayOf("", null));
401+
assertNull(sharedConn.createArrayOf("", null));
402+
assertThrows(SQLException.class, () -> sharedConn.createArrayOf("string", "ddd"));
402403
assertThrows(SQLException.class, () -> sharedConn.createStruct("", null));
403404
assertNull(sharedConn.getSchema());
404405
sharedConn.setSchema("fff");

0 commit comments

Comments
 (0)