diff --git a/mysql-test/suite/router/r/table_type_long_blob.result b/mysql-test/suite/router/r/table_type_long_blob.result new file mode 100644 index 000000000000..592b1a3679dc --- /dev/null +++ b/mysql-test/suite/router/r/table_type_long_blob.result @@ -0,0 +1,40 @@ +# MySQL Rest Service schema created. +# MySQL Rest Service, server accounts configured. + +# Registred SERVICE at path: /svc +# Registred DB_SCHEMA at path: /svc/test +# Registred DB_OBJECT at path: /svc/test/long_blob_types + +GET /svc/test/long_blob_types +{ + "resultSets": [ + { + "type": "items0", + "items": [ + { + "long_text": "long text", + "long_blob": "AQI=" + } + ], + "_metadata": { + "columns": [ + { + "name": "long_text", + "type": "LONGTEXT" + }, + { + "name": "long_blob", + "type": "LONGBLOB" + } + ] + } + } + ] +} +OK +DROP SCHEMA mysql_rest_service_metadata; +DROP ROLE mysql_rest_service_admin; +DROP ROLE mysql_rest_service_schema_admin; +DROP ROLE mysql_rest_service_meta_provider; +DROP ROLE mysql_rest_service_data_provider; +DROP ROLE mysql_rest_service_dev; diff --git a/mysql-test/suite/router/t/table_type_long_blob.test b/mysql-test/suite/router/t/table_type_long_blob.test new file mode 100644 index 000000000000..8e616dfa7036 --- /dev/null +++ b/mysql-test/suite/router/t/table_type_long_blob.test @@ -0,0 +1,52 @@ +--source include/have_router.inc + +--let $extra_mrs_router_id=1 +--source ../include/predefined_setup/configure_router_mrs_root.inc + +--disable_query_log +--disable_result_log +CREATE TABLE test.long_blob_types( + id INTEGER PRIMARY KEY, + long_text LONGTEXT CHARACTER SET utf8mb4, + long_blob LONGBLOB); + +INSERT INTO test.long_blob_types VALUES (1, 'long text', 0x0102); + +DROP PROCEDURE IF EXISTS test.proc_long_blob_types; +DELIMITER //; +CREATE PROCEDURE test.proc_long_blob_types() +BEGIN + SELECT long_text, long_blob FROM test.long_blob_types; +END;// +DELIMITER ;// +--enable_query_log +--enable_result_log + +--source ../include/mrs/start_object_definition.inc + +--let $mrs_add_service_path="/svc" +--let $mrs_add_host_name="" +--source ../include/mrs/service/add.inc + +--let $mrs_add_schema=test +--let $mrs_add_schema_path=/test +--source ../include/mrs/db_schema/add.inc + +--let $mrs_add_db_object_type=PROCEDURE +--let $mrs_add_db_object=proc_long_blob_types +--let $mrs_add_db_object_path=/long_blob_types +--source ../include/mrs/db_object/add.inc + +--source ../include/mrs/end_object_definition.inc + +--let $mrs_host_and_port=127.0.0.1:$HTTP_SERVER_PORT +--let MRS_CLIENT_ARGS=$MRS_CLIENT --url https://$mrs_host_and_port +--exec $MRS_CLIENT_ARGS --path /svc/test/long_blob_types --wait-until-status 60 + +--disable_query_log +--disable_result_log +DROP PROCEDURE test.proc_long_blob_types; +DROP TABLE test.long_blob_types; +--enable_query_log +--enable_result_log +--source ../include/mrs/cleanup.inc diff --git a/router/src/mysql_rest_service/src/helper/mysql_column_types.cc b/router/src/mysql_rest_service/src/helper/mysql_column_types.cc index d606ac233605..ff9655657e81 100644 --- a/router/src/mysql_rest_service/src/helper/mysql_column_types.cc +++ b/router/src/mysql_rest_service/src/helper/mysql_column_types.cc @@ -173,7 +173,8 @@ std::string txt_from_mysql_column_type(const MYSQL_FIELD *field) { if (field->charsetnr == 63) return "MEDIUMBLOB"; return "MEDIUMTEXT"; case MYSQL_TYPE_LONG_BLOB: - return "BLOB"; + if (field->charsetnr == 63) return "LONGBLOB"; + return "LONGTEXT"; case MYSQL_TYPE_BLOB: if (field->charsetnr == 63) return "BLOB"; return "TEXT"; diff --git a/router/src/mysql_rest_service/tests/CMakeLists.txt b/router/src/mysql_rest_service/tests/CMakeLists.txt index 2de0884d2ccf..5a083bf0e262 100644 --- a/router/src/mysql_rest_service/tests/CMakeLists.txt +++ b/router/src/mysql_rest_service/tests/CMakeLists.txt @@ -44,6 +44,7 @@ ADD_TEST_FILE(test_plugin.cc ./test_mrs_authentication_rate_control.cc ./test_mrs_entities_manager.cc ./test_mrs_database_converters.cc + ./test_helper_mysql_column_types.cc ./test_mrs_database_rest_table.cc ./test_mrs_database_rest_table_get.cc ./test_mrs_database_rest_table_get_one.cc diff --git a/router/src/mysql_rest_service/tests/test_helper_mysql_column_types.cc b/router/src/mysql_rest_service/tests/test_helper_mysql_column_types.cc new file mode 100644 index 000000000000..7acb4bea7f87 --- /dev/null +++ b/router/src/mysql_rest_service/tests/test_helper_mysql_column_types.cc @@ -0,0 +1,66 @@ +/* + Copyright (c) 2026, Oracle and/or its affiliates. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License, version 2.0, + as published by the Free Software Foundation. + + This program is designed to work with certain software (including + but not limited to OpenSSL) that is licensed under separate terms, + as designated in a particular file or component or in included license + documentation. The authors of MySQL hereby grant you an additional + permission to link the program and your derivative works with the + separately licensed software that they have either included with + the program or referenced in the documentation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include + +#include + +#include "helper/mysql_column_types.h" + +namespace { + +constexpr unsigned int kBinaryCharset = 63; +constexpr unsigned int kUtf8mb4Charset = 255; + +struct BlobTypeData { + enum_field_types mysql_type; + unsigned int charsetnr; + const char *expected; +}; + +class BlobTypeTests : public testing::TestWithParam {}; + +TEST_P(BlobTypeTests, preserves_blob_family_type_name) { + MYSQL_FIELD field{}; + const auto ¶m = GetParam(); + field.type = param.mysql_type; + field.charsetnr = param.charsetnr; + + EXPECT_EQ(param.expected, helper::txt_from_mysql_column_type(&field)); +} + +INSTANTIATE_TEST_SUITE_P( + BlobTypes, BlobTypeTests, + testing::Values( + BlobTypeData{MYSQL_TYPE_TINY_BLOB, kBinaryCharset, "TINYBLOB"}, + BlobTypeData{MYSQL_TYPE_TINY_BLOB, kUtf8mb4Charset, "TINYTEXT"}, + BlobTypeData{MYSQL_TYPE_MEDIUM_BLOB, kBinaryCharset, "MEDIUMBLOB"}, + BlobTypeData{MYSQL_TYPE_MEDIUM_BLOB, kUtf8mb4Charset, "MEDIUMTEXT"}, + BlobTypeData{MYSQL_TYPE_LONG_BLOB, kBinaryCharset, "LONGBLOB"}, + BlobTypeData{MYSQL_TYPE_LONG_BLOB, kUtf8mb4Charset, "LONGTEXT"}, + BlobTypeData{MYSQL_TYPE_BLOB, kBinaryCharset, "BLOB"}, + BlobTypeData{MYSQL_TYPE_BLOB, kUtf8mb4Charset, "TEXT"})); + +} // namespace