Skip to content

Commit 57b45b7

Browse files
committed
MariaDB determine json from Extended Metadata
In MariaDB the JSON of a result value is from the extended metadata of the protocol. This is returned when PROTOCOL_41 is in the connection flags. ref: https://mariadb.com/docs/server/reference/clientserver-protocol/4-server-response-packets/result-set-packets#extended-metadata
1 parent b009d7e commit 57b45b7

File tree

2 files changed

+27
-5
lines changed

2 files changed

+27
-5
lines changed

ext/mysql2/result.c

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,18 @@ static VALUE rb_mysql_result_fetch_field(VALUE self, unsigned int idx, int symbo
240240
return rb_field;
241241
}
242242

243+
static int rb_mariadb_json_type(const MYSQL_FIELD *field) {
244+
#if defined(MARIADB_PACKAGE_VERSION)
245+
MARIADB_CONST_STRING field_attr;
246+
247+
if (!mariadb_field_attr(&field_attr, field,
248+
MARIADB_FIELD_ATTR_FORMAT_NAME)) {
249+
return field_attr.length == 4 && strncmp(field_attr.str, "json", 4) == 0;
250+
}
251+
#endif
252+
return 0;
253+
}
254+
243255
static VALUE rb_mysql_result_fetch_field_type(VALUE self, unsigned int idx) {
244256
VALUE rb_field_type;
245257
GET_RESULT(self);
@@ -309,7 +321,9 @@ static VALUE rb_mysql_result_fetch_field_type(VALUE self, unsigned int idx) {
309321
rb_field_type = rb_sprintf("decimal(%d,%d)", precision, field->decimals);
310322
break;
311323
case MYSQL_TYPE_STRING: // char[]
312-
if (field->flags & ENUM_FLAG) {
324+
if (rb_mariadb_json_type(field)) {
325+
rb_field_type = rb_str_new_cstr("json");
326+
} else if (field->flags & ENUM_FLAG) {
313327
rb_field_type = rb_str_new_cstr("enum");
314328
} else if (field->flags & SET_FLAG) {
315329
rb_field_type = rb_str_new_cstr("set");
@@ -324,17 +338,27 @@ static VALUE rb_mysql_result_fetch_field_type(VALUE self, unsigned int idx) {
324338
case MYSQL_TYPE_VAR_STRING: // char[]
325339
if (field->charsetnr == MYSQL2_BINARY_CHARSET) {
326340
rb_field_type = rb_sprintf("varbinary(%ld)", field->length);
327-
} else {
341+
} else if (rb_mariadb_json_type(field)) {
342+
rb_field_type = rb_str_new_cstr("json");
343+
} else {
328344
rb_field_type = rb_sprintf("varchar(%ld)", field->length / MYSQL2_MAX_BYTES_PER_CHAR);
329345
}
330346
break;
331347
case MYSQL_TYPE_VARCHAR: // char[]
348+
if (rb_mariadb_json_type(field)) {
349+
rb_field_type = rb_str_new_cstr("json");
350+
break;
351+
}
332352
rb_field_type = rb_sprintf("varchar(%ld)", field->length / MYSQL2_MAX_BYTES_PER_CHAR);
333353
break;
334354
case MYSQL_TYPE_TINY_BLOB: // char[]
335355
rb_field_type = rb_str_new_cstr("tinyblob");
336356
break;
337357
case MYSQL_TYPE_BLOB: // char[]
358+
if (rb_mariadb_json_type(field)) {
359+
rb_field_type = rb_str_new_cstr("json");
360+
break;
361+
}
338362
if (field->charsetnr == MYSQL2_BINARY_CHARSET) {
339363
switch(field->length) {
340364
case 255:

spec/mysql2/result_spec.rb

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -199,9 +199,7 @@
199199
expect(result.field_types).to eql(expected_types)
200200
end
201201

202-
it "should return json type on mysql 8.0" do
203-
next unless /8.\d+.\d+/ =~ @client.server_info[:version]
204-
202+
it "should return json type" do
205203
result = @client.query("SELECT JSON_OBJECT('key', 'value')")
206204
expect(result.field_types).to eql(['json'])
207205
end

0 commit comments

Comments
 (0)