Skip to content

Commit b9f0e83

Browse files
svats0001jchrys
authored andcommitted
Added support for MariaDb extend type info
1 parent 9d9e763 commit b9f0e83

File tree

8 files changed

+91
-22
lines changed

8 files changed

+91
-22
lines changed

r2dbc-mysql/src/main/java/io/asyncer/r2dbc/mysql/Capability.java

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,11 @@ public final class Capability {
169169
// private static final long MARIADB_CLIENT_PROGRESS = 1L << 32;
170170
// private static final long MARIADB_CLIENT_COM_MULTI = 1L << 33;
171171
// private static final long MARIADB_CLIENT_STMT_BULK_OPERATIONS = 1L << 34;
172-
// private static final long MARIADB_CLIENT_EXTENDED_TYPE_INFO = 1L << 35;
172+
173+
/**
174+
* Receive extended column type information from MariaDB to find out more specific details about column type.
175+
*/
176+
private static final long MARIADB_CLIENT_EXTENDED_TYPE_INFO = 1L << 35;
173177
// private static final long MARIADB_CLIENT_CACHE_METADATA = 1L << 36;
174178

175179
private static final long ALL_SUPPORTED = CLIENT_MYSQL | FOUND_ROWS | LONG_FLAG | CONNECT_WITH_DB |
@@ -309,6 +313,15 @@ public boolean isZlibCompression() {
309313
public boolean isZstdCompression() {
310314
return (bitmap & ZSTD_COMPRESS) != 0;
311315
}
316+
317+
/**
318+
* Checks if MariaDB extended type info enabled.
319+
*
320+
* @return if MariaDB extended type info enabled.
321+
*/
322+
public boolean isExtendedTypeInfo() {
323+
return (bitmap & MARIADB_CLIENT_EXTENDED_TYPE_INFO) != 0;
324+
}
312325

313326
/**
314327
* Extends MariaDB capabilities.

r2dbc-mysql/src/main/java/io/asyncer/r2dbc/mysql/MySqlColumnDescriptor.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
import io.asyncer.r2dbc.mysql.constant.MySqlType;
2424
import io.asyncer.r2dbc.mysql.message.server.DefinitionMetadataMessage;
2525
import io.r2dbc.spi.Nullability;
26+
27+
import org.jetbrains.annotations.Nullable;
2628
import org.jetbrains.annotations.VisibleForTesting;
2729

2830
import static io.asyncer.r2dbc.mysql.internal.util.AssertUtils.require;
@@ -53,13 +55,13 @@ final class MySqlColumnDescriptor implements MySqlColumnMetadata {
5355

5456
@VisibleForTesting
5557
MySqlColumnDescriptor(int index, short typeId, String name, int definitions,
56-
long size, int decimals, int collationId) {
58+
long size, int decimals, int collationId, @Nullable String extendedTypeInfo) {
5759
require(index >= 0, "index must not be a negative integer");
5860
require(size >= 0, "size must not be a negative integer");
5961
require(decimals >= 0, "decimals must not be a negative integer");
6062
requireNonNull(name, "name must not be null");
6163

62-
MySqlTypeMetadata typeMetadata = new MySqlTypeMetadata(typeId, definitions, collationId);
64+
MySqlTypeMetadata typeMetadata = new MySqlTypeMetadata(typeId, definitions, collationId, extendedTypeInfo);
6365

6466
this.index = index;
6567
this.typeMetadata = typeMetadata;
@@ -74,7 +76,7 @@ final class MySqlColumnDescriptor implements MySqlColumnMetadata {
7476
static MySqlColumnDescriptor create(int index, DefinitionMetadataMessage message) {
7577
int definitions = message.getDefinitions();
7678
return new MySqlColumnDescriptor(index, message.getTypeId(), message.getColumn(), definitions,
77-
message.getSize(), message.getDecimals(), message.getCollationId());
79+
message.getSize(), message.getDecimals(), message.getCollationId(), message.getExtendedTypeInfo());
7880
}
7981

8082
int getIndex() {

r2dbc-mysql/src/main/java/io/asyncer/r2dbc/mysql/MySqlTypeMetadata.java

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@
1616

1717
package io.asyncer.r2dbc.mysql;
1818

19+
import java.util.Objects;
20+
21+
import org.jetbrains.annotations.Nullable;
22+
1923
import io.asyncer.r2dbc.mysql.api.MySqlNativeTypeMetadata;
2024
import io.asyncer.r2dbc.mysql.collation.CharCollation;
2125

@@ -64,11 +68,18 @@ final class MySqlTypeMetadata implements MySqlNativeTypeMetadata {
6468
* collationId > 0 when protocol version == 4.1, 0 otherwise.
6569
*/
6670
private final int collationId;
71+
72+
/**
73+
* The MariaDB extended type info field that provides more specific details about column type.
74+
*/
75+
@Nullable
76+
private final String extendedTypeInfo;
6777

68-
MySqlTypeMetadata(int typeId, int definitions, int collationId) {
78+
MySqlTypeMetadata(int typeId, int definitions, int collationId, @Nullable String extendedTypeInfo) {
6979
this.typeId = typeId;
7080
this.definitions = (short) (definitions & ALL_USED);
7181
this.collationId = collationId;
82+
this.extendedTypeInfo = extendedTypeInfo;
7283
}
7384

7485
@Override
@@ -105,6 +116,11 @@ public boolean isEnum() {
105116
public boolean isSet() {
106117
return (definitions & SET) != 0;
107118
}
119+
120+
@Override
121+
public boolean isMariaDbJson() {
122+
return extendedTypeInfo.equals("json");
123+
}
108124

109125
@Override
110126
public boolean equals(Object o) {
@@ -117,20 +133,22 @@ public boolean equals(Object o) {
117133

118134
MySqlTypeMetadata that = (MySqlTypeMetadata) o;
119135

120-
return typeId == that.typeId && definitions == that.definitions && collationId == that.collationId;
136+
return typeId == that.typeId && definitions == that.definitions && collationId == that.collationId &&
137+
Objects.equals(extendedTypeInfo, that.extendedTypeInfo);
121138
}
122139

123140
@Override
124141
public int hashCode() {
125142
int result = 31 * typeId + (int) definitions;
126-
return 31 * result + collationId;
143+
return 31 * result + collationId + extendedTypeInfo.hashCode();
127144
}
128145

129146
@Override
130147
public String toString() {
131148
return "MySqlTypeMetadata{typeId=" + typeId +
132149
", definitions=0x" + Integer.toHexString(definitions) +
133-
", collationId=" + collationId +
150+
", collationId=" + collationId +
151+
", extendedTypeInfo=" + extendedTypeInfo +
134152
'}';
135153
}
136154
}

r2dbc-mysql/src/main/java/io/asyncer/r2dbc/mysql/api/MySqlNativeTypeMetadata.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,4 +71,11 @@ public interface MySqlNativeTypeMetadata {
7171
* @return if value is a set
7272
*/
7373
boolean isSet();
74+
75+
/**
76+
* Checks if value is JSON for MariaDb.
77+
*
78+
* @return if value is a JSON for MariaDb
79+
*/
80+
boolean isMariaDbJson();
7481
}

r2dbc-mysql/src/main/java/io/asyncer/r2dbc/mysql/constant/MySqlType.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -712,7 +712,7 @@ public static MySqlType of(MySqlNativeTypeMetadata metadata) {
712712
case ID_VARCHAR:
713713
case ID_VAR_STRING:
714714
case ID_STRING:
715-
return metadata.isBinary() ? VARBINARY : VARCHAR;
715+
return metadata.isBinary() ? VARBINARY : (metadata.isMariaDbJson() ? JSON : VARCHAR);
716716
case ID_BIT:
717717
return BIT;
718718
case ID_JSON:

r2dbc-mysql/src/main/java/io/asyncer/r2dbc/mysql/message/server/DefinitionMetadataMessage.java

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,9 @@ public final class DefinitionMetadataMessage implements ServerMessage {
4545

4646
@Nullable
4747
private final String originColumn;
48+
49+
@Nullable
50+
private final String extendedTypeInfo;
4851

4952
private final int collationId;
5053

@@ -57,7 +60,7 @@ public final class DefinitionMetadataMessage implements ServerMessage {
5760
private final short decimals;
5861

5962
private DefinitionMetadataMessage(@Nullable String database, String table, @Nullable String originTable,
60-
String column, @Nullable String originColumn, int collationId, long size, short typeId,
63+
String column, @Nullable String originColumn, @Nullable String extendedTypeInfo, int collationId, long size, short typeId,
6164
int definitions, short decimals) {
6265
require(size >= 0, "size must not be a negative integer");
6366

@@ -66,6 +69,7 @@ private DefinitionMetadataMessage(@Nullable String database, String table, @Null
6669
this.originTable = originTable;
6770
this.column = requireNonNull(column, "column must not be null");
6871
this.originColumn = originColumn;
72+
this.extendedTypeInfo = extendedTypeInfo;
6973
this.collationId = collationId;
7074
this.size = size;
7175
this.typeId = typeId;
@@ -96,6 +100,10 @@ public int getDefinitions() {
96100
public short getDecimals() {
97101
return decimals;
98102
}
103+
104+
public String getExtendedTypeInfo() {
105+
return extendedTypeInfo;
106+
}
99107

100108
@Override
101109
public boolean equals(Object o) {
@@ -115,21 +123,22 @@ public boolean equals(Object o) {
115123
table.equals(that.table) &&
116124
Objects.equals(originTable, that.originTable) &&
117125
column.equals(that.column) &&
118-
Objects.equals(originColumn, that.originColumn);
126+
Objects.equals(originColumn, that.originColumn) &&
127+
Objects.equals(extendedTypeInfo, that.extendedTypeInfo);
119128
}
120129

121130
@Override
122131
public int hashCode() {
123132
return Objects.hash(database, table, originTable, column, originColumn, collationId, size, typeId,
124-
definitions, decimals);
133+
definitions, decimals, extendedTypeInfo);
125134
}
126135

127136
@Override
128137
public String toString() {
129138
return "DefinitionMetadataMessage{database='" + database + "', table='" + table + "' (origin:'" +
130-
originTable + "'), column='" + column + "' (origin:'" + originColumn + "'), collationId=" +
131-
collationId + ", size=" + size + ", type=" + typeId + ", definitions=" + definitions +
132-
", decimals=" + decimals + '}';
139+
originTable + "'), column='" + column + "' (origin:'" + originColumn + "'), extendedTypeInfo=" +
140+
extendedTypeInfo + ", collationId=" +collationId + ", size=" + size + ", type=" + typeId +
141+
", definitions=" + definitions + ", decimals=" + decimals + '}';
133142
}
134143

135144
static DefinitionMetadataMessage decode(ByteBuf buf, ConnectionContext context) {
@@ -156,7 +165,7 @@ private static DefinitionMetadataMessage decode320(ByteBuf buf, ConnectionContex
156165
int definitions = buf.readUnsignedShortLE();
157166
short decimals = buf.readUnsignedByte();
158167

159-
return new DefinitionMetadataMessage(null, table, null, column, null, 0, size, typeId,
168+
return new DefinitionMetadataMessage(null, table, null, column, null, null, 0, size, typeId,
160169
definitions, decimals);
161170
}
162171

@@ -170,6 +179,11 @@ private static DefinitionMetadataMessage decode41(ByteBuf buf, ConnectionContext
170179
String originTable = readVarIntSizedString(buf, charset);
171180
String column = readVarIntSizedString(buf, charset);
172181
String originColumn = readVarIntSizedString(buf, charset);
182+
183+
String extendTypeInfo = null;
184+
if (context.getCapability().isMariaDb() && context.getCapability().isExtendedTypeInfo()) {
185+
extendTypeInfo = readVarIntSizedString(buf, charset);
186+
}
173187

174188
// Skip constant 0x0c encoded by var integer
175189
VarIntUtils.readVarInt(buf);
@@ -179,7 +193,7 @@ private static DefinitionMetadataMessage decode41(ByteBuf buf, ConnectionContext
179193
short typeId = buf.readUnsignedByte();
180194
int definitions = buf.readUnsignedShortLE();
181195

182-
return new DefinitionMetadataMessage(database, table, originTable, column, originColumn, collationId,
196+
return new DefinitionMetadataMessage(database, table, originTable, column, originColumn, extendTypeInfo, collationId,
183197
size, typeId, definitions, buf.readUnsignedByte());
184198
}
185199

r2dbc-mysql/src/test/java/io/asyncer/r2dbc/mysql/MySqlRowDescriptorTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ private static MySqlRowDescriptor create(final String... names) {
5656
MySqlColumnDescriptor[] metadata = new MySqlColumnDescriptor[names.length];
5757
for (int i = 0; i < names.length; ++i) {
5858
metadata[i] =
59-
new MySqlColumnDescriptor(i, (short) 0, names[i], 0, 0, 0, 1);
59+
new MySqlColumnDescriptor(i, (short) 0, names[i], 0, 0, 0, 1, null);
6060
}
6161
return new MySqlRowDescriptor(metadata);
6262
}

r2dbc-mysql/src/test/java/io/asyncer/r2dbc/mysql/MySqlTypeMetadataTest.java

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
package io.asyncer.r2dbc.mysql;
1818

1919
import io.asyncer.r2dbc.mysql.collation.CharCollation;
20+
import io.asyncer.r2dbc.mysql.constant.MySqlType;
21+
2022
import org.junit.jupiter.api.Test;
2123

2224
import static org.assertj.core.api.Assertions.assertThat;
@@ -28,7 +30,7 @@ class MySqlTypeMetadataTest {
2830

2931
@Test
3032
void allSet() {
31-
MySqlTypeMetadata metadata = new MySqlTypeMetadata(0, -1, 0);
33+
MySqlTypeMetadata metadata = new MySqlTypeMetadata(0, -1, 0, null);
3234

3335
assertThat(metadata.isBinary()).isTrue();
3436
assertThat(metadata.isSet()).isTrue();
@@ -39,7 +41,7 @@ void allSet() {
3941

4042
@Test
4143
void noSet() {
42-
MySqlTypeMetadata metadata = new MySqlTypeMetadata(0, 0, 0);
44+
MySqlTypeMetadata metadata = new MySqlTypeMetadata(0, 0, 0, null);
4345

4446
assertThat(metadata.isBinary()).isFalse();
4547
assertThat(metadata.isSet()).isFalse();
@@ -50,11 +52,24 @@ void noSet() {
5052

5153
@Test
5254
void isBinaryUsesCollationId() {
53-
MySqlTypeMetadata metadata = new MySqlTypeMetadata(0, -1, CharCollation.BINARY_ID);
55+
MySqlTypeMetadata metadata = new MySqlTypeMetadata(0, -1, CharCollation.BINARY_ID, null);
5456

5557
assertThat(metadata.isBinary()).isTrue();
5658

57-
metadata = new MySqlTypeMetadata(0, -1, 33);
59+
metadata = new MySqlTypeMetadata(0, -1, 33, null);
5860
assertThat(metadata.isBinary()).isFalse();
5961
}
62+
63+
@Test
64+
void mariaDbJsonReturnsCorrectMySqlType() {
65+
MySqlTypeMetadata metadata = new MySqlTypeMetadata(254, 0, 0, "json");
66+
67+
assertThat(metadata.isMariaDbJson()).isTrue();
68+
assertThat(MySqlType.of(metadata)).isEqualTo(MySqlType.JSON);
69+
70+
metadata = new MySqlTypeMetadata(254, 0 ,0 , null);
71+
72+
assertThat(metadata.isMariaDbJson()).isFalse();
73+
assertThat(MySqlType.of(metadata)).isEqualTo(MySqlType.VARCHAR);
74+
}
6075
}

0 commit comments

Comments
 (0)