Skip to content

Commit eb77c8a

Browse files
committed
IGNITE-13908: ODBC nullability info for columns
This closes #8610
1 parent 5223e44 commit eb77c8a

File tree

15 files changed

+179
-59
lines changed

15 files changed

+179
-59
lines changed

modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcColumnMeta.java

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -35,19 +35,19 @@ public class OdbcColumnMeta {
3535
private final String tableName;
3636

3737
/** Column name. */
38-
public final String columnName;
38+
private final String columnName;
3939

4040
/** Data type. */
4141
private final Class<?> dataType;
4242

4343
/** Precision. */
44-
public final int precision;
44+
private final int precision;
4545

4646
/** Scale. */
47-
public final int scale;
47+
private final int scale;
4848

49-
/** Client version. */
50-
private final ClientListenerProtocolVersion ver;
49+
/** Nullability. See {@link java.sql.ResultSetMetaData#isNullable(int)} for more info. */
50+
private final int nullability;
5151

5252
/**
5353
* @param schemaName Cache name.
@@ -56,30 +56,30 @@ public class OdbcColumnMeta {
5656
* @param dataType Data type.
5757
* @param precision Precision.
5858
* @param scale Scale.
59-
* @param ver Client version.
59+
* @param nullability Nullability.
6060
*/
6161
public OdbcColumnMeta(String schemaName, String tableName, String columnName, Class<?> dataType,
62-
int precision, int scale, ClientListenerProtocolVersion ver) {
62+
int precision, int scale, int nullability) {
6363
this.schemaName = OdbcUtils.addQuotationMarksIfNeeded(schemaName);
6464
this.tableName = tableName;
6565
this.columnName = columnName;
6666
this.dataType = dataType;
6767
this.precision = precision;
6868
this.scale = scale;
69-
this.ver = ver;
69+
this.nullability = nullability;
7070
}
7171

7272
/**
73+
* Constructor for result set column.
7374
* @param info Field metadata.
74-
* @param ver Client version.
7575
*/
76-
public OdbcColumnMeta(GridQueryFieldMetadata info, ClientListenerProtocolVersion ver) {
77-
this.schemaName = OdbcUtils.addQuotationMarksIfNeeded(info.schemaName());
78-
this.tableName = info.typeName();
79-
this.columnName = info.fieldName();
80-
this.precision = info.precision();
81-
this.scale = info.scale();
82-
this.ver = ver;
76+
public OdbcColumnMeta(GridQueryFieldMetadata info) {
77+
schemaName = OdbcUtils.addQuotationMarksIfNeeded(info.schemaName());
78+
tableName = info.typeName();
79+
columnName = info.fieldName();
80+
precision = info.precision();
81+
scale = info.scale();
82+
nullability = info.nullability();
8383

8484
Class<?> type;
8585

@@ -123,8 +123,9 @@ public OdbcColumnMeta(GridQueryFieldMetadata info, ClientListenerProtocolVersion
123123
* Write in a binary format.
124124
*
125125
* @param writer Binary writer.
126+
* @param ver Client version.
126127
*/
127-
public void write(BinaryRawWriter writer) {
128+
public void write(BinaryRawWriter writer, ClientListenerProtocolVersion ver) {
128129
writer.writeString(schemaName);
129130
writer.writeString(tableName);
130131
writer.writeString(columnName);
@@ -137,6 +138,10 @@ public void write(BinaryRawWriter writer) {
137138
writer.writeInt(precision);
138139
writer.writeInt(scale);
139140
}
141+
142+
if (ver.compareTo(OdbcConnectionContext.VER_2_8_0) >= 0) {
143+
writer.writeByte((byte)nullability);
144+
}
140145
}
141146

142147
/**

modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcConnectionContext.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,11 @@ public class OdbcConnectionContext extends ClientListenerAbstractConnectionConte
5656
/** Version 2.7.0: added precision and scale. */
5757
public static final ClientListenerProtocolVersion VER_2_7_0 = ClientListenerProtocolVersion.create(2, 7, 0);
5858

59+
/** Version 2.8.0: added column nullability info. */
60+
public static final ClientListenerProtocolVersion VER_2_8_0 = ClientListenerProtocolVersion.create(2, 8, 0);
61+
5962
/** Current version. */
60-
private static final ClientListenerProtocolVersion CURRENT_VER = VER_2_7_0;
63+
private static final ClientListenerProtocolVersion CURRENT_VER = VER_2_8_0;
6164

6265
/** Supported versions. */
6366
private static final Set<ClientListenerProtocolVersion> SUPPORTED_VERS = new HashSet<>();
@@ -79,6 +82,7 @@ public class OdbcConnectionContext extends ClientListenerAbstractConnectionConte
7982

8083
static {
8184
SUPPORTED_VERS.add(CURRENT_VER);
85+
SUPPORTED_VERS.add(VER_2_7_0);
8286
SUPPORTED_VERS.add(VER_2_5_0);
8387
SUPPORTED_VERS.add(VER_2_3_0);
8488
SUPPORTED_VERS.add(VER_2_3_2);

modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcMessageParser.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -419,13 +419,13 @@ else if (res0 instanceof OdbcQueryGetResultsetMetaResult) {
419419
* @param writer Writer.
420420
* @param meta Metadata
421421
*/
422-
private static void writeResultsetMeta(BinaryWriterExImpl writer, Collection<OdbcColumnMeta> meta) {
422+
private void writeResultsetMeta(BinaryWriterExImpl writer, Collection<OdbcColumnMeta> meta) {
423423
assert meta != null;
424424

425425
writer.writeInt(meta.size());
426426

427427
for (OdbcColumnMeta columnMeta : meta)
428-
columnMeta.write(writer);
428+
columnMeta.write(writer, ver);
429429
}
430430

431431
/** {@inheritDoc} */

modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcRequestHandler.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,8 @@
6969
import org.apache.ignite.transactions.TransactionSerializationException;
7070
import org.apache.ignite.transactions.TransactionUnsupportedConcurrencyException;
7171

72+
import static java.sql.ResultSetMetaData.columnNoNulls;
73+
import static java.sql.ResultSetMetaData.columnNullable;
7274
import static org.apache.ignite.internal.processors.odbc.odbc.OdbcRequest.META_COLS;
7375
import static org.apache.ignite.internal.processors.odbc.odbc.OdbcRequest.META_PARAMS;
7476
import static org.apache.ignite.internal.processors.odbc.odbc.OdbcRequest.META_RESULTSET;
@@ -696,7 +698,8 @@ private ClientListenerResponse getColumnsMeta(OdbcQueryGetColumnsMetaRequest req
696698
GridQueryProperty prop = table.property(field.getKey());
697699

698700
OdbcColumnMeta columnMeta = new OdbcColumnMeta(table.schemaName(), table.tableName(),
699-
field.getKey(), field.getValue(), prop.precision(), prop.scale(), ver);
701+
field.getKey(), field.getValue(), prop.precision(), prop.scale(),
702+
prop.notNull() ? columnNoNulls : columnNullable);
700703

701704
if (!meta.contains(columnMeta))
702705
meta.add(columnMeta);
@@ -802,7 +805,7 @@ private ClientListenerResponse getResultMeta(OdbcQueryGetResultsetMetaRequest re
802805
SqlFieldsQueryEx qry = makeQuery(schema, sql);
803806

804807
List<GridQueryFieldMetadata> columns = ctx.query().getIndexing().resultMetaData(schema, qry);
805-
Collection<OdbcColumnMeta> meta = OdbcUtils.convertMetadata(columns, ver);
808+
Collection<OdbcColumnMeta> meta = OdbcUtils.convertMetadata(columns);
806809

807810
OdbcQueryGetResultsetMetaResult res = new OdbcQueryGetResultsetMetaResult(meta);
808811

modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcResultSet.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ public class OdbcResultSet {
5454

5555
if (this.cursor.isQuery()) {
5656
iter = this.cursor.iterator();
57-
meta = OdbcUtils.convertMetadata(this.cursor.fieldsMeta(), ver);
57+
meta = OdbcUtils.convertMetadata(this.cursor.fieldsMeta());
5858
}
5959
else {
6060
iter = null;

modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcUtils.java

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@
2525
import org.apache.ignite.cache.query.QueryCursor;
2626
import org.apache.ignite.internal.processors.cache.QueryCursorImpl;
2727
import org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode;
28-
import org.apache.ignite.internal.processors.odbc.ClientListenerProtocolVersion;
2928
import org.apache.ignite.internal.processors.odbc.SqlListenerDataTypes;
3029
import org.apache.ignite.internal.processors.odbc.SqlListenerUtils;
3130
import org.apache.ignite.internal.processors.query.GridQueryFieldMetadata;
@@ -252,16 +251,14 @@ public static long rowsAffected(QueryCursor<List<?>> qryCur) {
252251
* {@link OdbcColumnMeta}.
253252
*
254253
* @param meta Internal query field metadata.
255-
* @param ver Client version.
256254
* @return Odbc query field metadata.
257255
*/
258-
public static Collection<OdbcColumnMeta> convertMetadata(Collection<GridQueryFieldMetadata> meta,
259-
ClientListenerProtocolVersion ver) {
256+
public static Collection<OdbcColumnMeta> convertMetadata(Collection<GridQueryFieldMetadata> meta) {
260257
List<OdbcColumnMeta> res = new ArrayList<>();
261258

262259
if (meta != null) {
263260
for (GridQueryFieldMetadata info : meta)
264-
res.add(new OdbcColumnMeta(info, ver));
261+
res.add(new OdbcColumnMeta(info));
265262
}
266263

267264
return res;

modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryFieldMetadata.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,4 +65,13 @@ public interface GridQueryFieldMetadata extends Externalizable {
6565
* @return Field scale.
6666
*/
6767
public int scale();
68+
69+
/**
70+
* Gets field nullability.
71+
*
72+
* See {@link java.sql.ResultSetMetaData#isNullable(int)} for more info.
73+
*
74+
* @return Field nullability.
75+
*/
76+
public int nullability();
6877
}

modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/H2SqlFieldMetadata.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,9 @@ public class H2SqlFieldMetadata implements GridQueryFieldMetadata {
5151
/** Scale. */
5252
private int scale;
5353

54+
/** Nullability. See {@link java.sql.ResultSetMetaData#isNullable(int)} */
55+
private int nullability;
56+
5457
/**
5558
* Required by {@link Externalizable}.
5659
*/
@@ -67,7 +70,7 @@ public H2SqlFieldMetadata() {
6770
* @param scale Scale.
6871
*/
6972
H2SqlFieldMetadata(@Nullable String schemaName, @Nullable String typeName, String name, String type,
70-
int precision, int scale) {
73+
int precision, int scale, int nullability) {
7174
assert name != null && type != null : schemaName + " | " + typeName + " | " + name + " | " + type;
7275

7376
this.schemaName = schemaName;
@@ -76,6 +79,7 @@ public H2SqlFieldMetadata() {
7679
this.type = type;
7780
this.precision = precision;
7881
this.scale = scale;
82+
this.nullability = nullability;
7983
}
8084

8185
/** {@inheritDoc} */
@@ -108,6 +112,11 @@ public H2SqlFieldMetadata() {
108112
return scale;
109113
}
110114

115+
/** {@inheritDoc} */
116+
@Override public int nullability() {
117+
return nullability;
118+
}
119+
111120
/** {@inheritDoc} */
112121
@Override public void writeExternal(ObjectOutput out) throws IOException {
113122
U.writeString(out, schemaName);

modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/H2Utils.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@
105105
import org.jetbrains.annotations.NotNull;
106106
import org.jetbrains.annotations.Nullable;
107107

108+
import static java.sql.ResultSetMetaData.columnNullableUnknown;
108109
import static org.apache.ignite.internal.processors.query.QueryUtils.KEY_COL;
109110
import static org.apache.ignite.internal.processors.query.QueryUtils.KEY_FIELD_NAME;
110111
import static org.apache.ignite.internal.processors.query.QueryUtils.VAL_FIELD_NAME;
@@ -136,7 +137,8 @@ public class H2Utils {
136137

137138
/** Dummy metadata for update result. */
138139
public static final List<GridQueryFieldMetadata> UPDATE_RESULT_META =
139-
Collections.singletonList(new H2SqlFieldMetadata(null, null, "UPDATED", Long.class.getName(), -1, -1));
140+
Collections.singletonList(new H2SqlFieldMetadata(null, null, "UPDATED", Long.class.getName(), -1, -1,
141+
columnNullableUnknown));
140142

141143
/** Spatial index class name. */
142144
private static final String SPATIAL_IDX_CLS =
@@ -375,11 +377,12 @@ public static List<GridQueryFieldMetadata> meta(ResultSetMetaData rsMeta) throws
375377
String type = rsMeta.getColumnClassName(i);
376378
int precision = rsMeta.getPrecision(i);
377379
int scale = rsMeta.getScale(i);
380+
int nullability = rsMeta.isNullable(i);
378381

379382
if (type == null) // Expression always returns NULL.
380383
type = Void.class.getName();
381384

382-
meta.add(new H2SqlFieldMetadata(schemaName, typeName, name, type, precision, scale));
385+
meta.add(new H2SqlFieldMetadata(schemaName, typeName, name, type, precision, scale, nullability));
383386
}
384387

385388
return meta;

modules/platforms/cpp/odbc-test/src/attributes_test.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,30 @@ BOOST_AUTO_TEST_CASE(TestConnectionProtocolVersion_2_3_2)
116116
InsertTestBatch(11, 20, 9);
117117
}
118118

119+
BOOST_AUTO_TEST_CASE(TestConnectionProtocolVersion_2_5_0)
120+
{
121+
Connect("DRIVER={Apache Ignite};ADDRESS=127.0.0.1:11110;SCHEMA=cache;PROTOCOL_VERSION=2.5.0");
122+
123+
InsertTestStrings(10, false);
124+
InsertTestBatch(11, 20, 9);
125+
}
126+
127+
BOOST_AUTO_TEST_CASE(TestConnectionProtocolVersion_2_7_0)
128+
{
129+
Connect("DRIVER={Apache Ignite};ADDRESS=127.0.0.1:11110;SCHEMA=cache;PROTOCOL_VERSION=2.7.0");
130+
131+
InsertTestStrings(10, false);
132+
InsertTestBatch(11, 20, 9);
133+
}
134+
135+
BOOST_AUTO_TEST_CASE(TestConnectionProtocolVersion_2_8_0)
136+
{
137+
Connect("DRIVER={Apache Ignite};ADDRESS=127.0.0.1:11110;SCHEMA=cache;PROTOCOL_VERSION=2.8.0");
138+
139+
InsertTestStrings(10, false);
140+
InsertTestBatch(11, 20, 9);
141+
}
142+
119143
BOOST_AUTO_TEST_CASE(TestConnectionRangeBegin)
120144
{
121145
Connect("DRIVER={Apache Ignite};ADDRESS=127.0.0.1:11110..11115;SCHEMA=cache");

0 commit comments

Comments
 (0)