diff --git a/docker/test/integration/runner/compose/docker_compose_meili.yml b/docker/test/integration/runner/compose/docker_compose_meili.yml index 16d295d4988..196324bfcfb 100644 --- a/docker/test/integration/runner/compose/docker_compose_meili.yml +++ b/docker/test/integration/runner/compose/docker_compose_meili.yml @@ -1,14 +1,14 @@ version: '2.3' services: meili1: - image: getmeili/meilisearch + image: getmeili/meilisearch:latest restart: always command: ./meilisearch ports: - ${MEILI_EXTERNAL_PORT}:${MEILI_INTERNAL_PORT} meili_secure: - image: getmeili/meilisearch + image: getmeili/meilisearch:latest restart: always command: ./meilisearch --master-key="password" ports: diff --git a/src/Storages/MeiliSearch/MeiliSearchColumnDescriptionFetcher.cpp b/src/Storages/MeiliSearch/MeiliSearchColumnDescriptionFetcher.cpp index f035834b994..d9dff81b34c 100644 --- a/src/Storages/MeiliSearch/MeiliSearchColumnDescriptionFetcher.cpp +++ b/src/Storages/MeiliSearch/MeiliSearchColumnDescriptionFetcher.cpp @@ -1,11 +1,14 @@ #include +#include #include #include -#include "DataTypes/DataTypeArray.h" -#include "DataTypes/DataTypeNullable.h" -#include "DataTypes/DataTypeString.h" -#include "DataTypes/DataTypesNumber.h" -#include "DataTypes/Serializations/ISerialization.h" +#include +#include +#include +#include +#include +#include +#include namespace DB { @@ -25,12 +28,9 @@ void MeiliSearchColumnDescriptionFetcher::addParam(const String & key, const Str query_params[key] = val; } -bool isDouble(const std::string & val) +bool checkIfInteger(const String & s) { - std::istringstream iss(val); - double f; - iss >> std::noskipws >> f; - return iss.eof() && !iss.fail() && static_cast(f) != f; + return s.find('.') == String::npos; } DataTypePtr parseTypeOfField(JSON ptr) @@ -53,19 +53,15 @@ DataTypePtr parseTypeOfField(JSON ptr) DataTypePtr res = std::make_shared(res); return res; } - if (isDouble(ptr.toString())) - { - return std::make_shared(); - } if (ptr.isNumber()) { - return std::make_shared(); + if (checkIfInteger(ptr.toString())) + { + return std::make_shared(); + } + return std::make_shared(); } - if (ptr.isObject()) - { - return std::make_shared(); - } - throw Exception(ErrorCodes::UNSUPPORTED_MEILISEARCH_TYPE, "Can't recognize type of some fields"); + return std::make_shared(); } ColumnsDescription MeiliSearchColumnDescriptionFetcher::fetchColumnsDescription() const diff --git a/src/Storages/MeiliSearch/MeiliSearchConnection.cpp b/src/Storages/MeiliSearch/MeiliSearchConnection.cpp index 586a1165891..a83522a30a2 100644 --- a/src/Storages/MeiliSearch/MeiliSearchConnection.cpp +++ b/src/Storages/MeiliSearch/MeiliSearchConnection.cpp @@ -28,7 +28,14 @@ CURLcode MeiliSearchConnection::execQuery(std::string_view url, std::string_view headers_list = nullptr; headers_list = curl_slist_append(headers_list, "Content-Type: application/json"); - headers_list = curl_slist_append(headers_list, config.key.c_str()); + + String full_key; + + if (!config.key.empty()) + { + full_key = config.key_prefix + config.key; + headers_list = curl_slist_append(headers_list, full_key.c_str()); + } handle = curl_easy_init(); curl_easy_setopt(handle, CURLOPT_URL, url.data()); diff --git a/src/Storages/MeiliSearch/MeiliSearchConnection.h b/src/Storages/MeiliSearch/MeiliSearchConnection.h index 5040cc56453..430be7b7cf3 100644 --- a/src/Storages/MeiliSearch/MeiliSearchConnection.h +++ b/src/Storages/MeiliSearch/MeiliSearchConnection.h @@ -10,14 +10,15 @@ namespace DB { struct MeiliSearchConfiguration { + inline const static String key_prefix = "Authorization: Bearer "; + String key; String index; String connection_string; - MeiliSearchConfiguration(const String & url_, const String & index_, const String & key_) : index{index_} + MeiliSearchConfiguration(const String & url_, const String & index_, const String & key_) : key{key_}, index{index_} { connection_string = url_ + "/indexes/" + index_ + "/"; - key = "Authorization: Bearer " + key_; } }; diff --git a/src/Storages/MeiliSearch/StorageMeiliSearch.cpp b/src/Storages/MeiliSearch/StorageMeiliSearch.cpp index b9612ff5cae..6c31a593300 100644 --- a/src/Storages/MeiliSearch/StorageMeiliSearch.cpp +++ b/src/Storages/MeiliSearch/StorageMeiliSearch.cpp @@ -126,48 +126,33 @@ MeiliSearchConfiguration StorageMeiliSearch::getConfiguration(ASTs engine_args, if (auto named_collection = getExternalDataSourceConfiguration(engine_args, context)) { auto [common_configuration, storage_specific_args] = named_collection.value(); + String url = common_configuration.addresses_expr; String index = common_configuration.table; String key = common_configuration.password; - for (const auto & [arg_name, arg_value] : storage_specific_args) - { - if (arg_name == "url") - { - if (!url.empty()) - throw Exception( - "2 times given 'url' value, old = " + url + " new = " + arg_value->as()->value.safeGet(), - ErrorCodes::BAD_ARGUMENTS); - url = arg_value->as()->value.safeGet(); - } - else if (arg_name == "key" || arg_name == "password") - { - if (!key.empty()) - throw Exception( - "2 times given 'key' value, old = " + key + " new = " + arg_value->as()->value.safeGet(), - ErrorCodes::BAD_ARGUMENTS); - key = arg_value->as()->value.safeGet(); - } - else - throw Exception("Unexpected key-value argument", ErrorCodes::BAD_ARGUMENTS); - } + if (url.empty() || index.empty()) { - throw Exception("Storage MeiliSearch requires 3 parameters: {url, index, [key]}", ErrorCodes::BAD_ARGUMENTS); + throw Exception( + "Storage MeiliSearch requires 3 parameters: MeiliSearch('url', 'index', 'key'= \"\")", ErrorCodes::BAD_ARGUMENTS); } + return MeiliSearchConfiguration(url, index, key); } else { - if (engine_args.size() != 3) + if (engine_args.size() < 2 || 3 < engine_args.size()) { throw Exception( - "Storage MeiliSearch requires 3 parameters: MeiliSearch('url', 'index', 'key')", + "Storage MeiliSearch requires 3 parameters: MeiliSearch('url', 'index', 'key'= \"\")", ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH); } String url = engine_args[0]->as().value.safeGet(); String index = engine_args[1]->as().value.safeGet(); - String key = engine_args[2]->as().value.safeGet(); + String key; + if (engine_args.size() == 3) + key = engine_args[2]->as().value.safeGet(); return MeiliSearchConfiguration(url, index, key); } } diff --git a/tests/integration/test_storage_meilisearch/configs/named_collection.xml b/tests/integration/test_storage_meilisearch/configs/named_collection.xml index 8ff69f4930d..276e885ce45 100644 --- a/tests/integration/test_storage_meilisearch/configs/named_collection.xml +++ b/tests/integration/test_storage_meilisearch/configs/named_collection.xml @@ -11,6 +11,14 @@ MeiliSearch meili_secure:7700 new_table
+ password + + + + MeiliSearch + meili_secure:7700 + new_table
+
diff --git a/tests/integration/test_storage_meilisearch/test.py b/tests/integration/test_storage_meilisearch/test.py index 6d6abcd3912..8f91ed582af 100644 --- a/tests/integration/test_storage_meilisearch/test.py +++ b/tests/integration/test_storage_meilisearch/test.py @@ -427,25 +427,37 @@ def test_named_collection(started_cluster): @pytest.mark.parametrize('started_cluster', [False], indirect=['started_cluster']) def test_named_collection_secure(started_cluster): - client = get_meili_secure_client(started_cluster) - table = client.index("new_table") + client_secure = get_meili_secure_client(started_cluster) + client_free = get_meili_client(started_cluster) + table_secure = client_secure.index("new_table") + table_free = client_free.index("new_table") + data = [] for i in range(0, 100): data.append({'id': i, 'data': hex(i * i)}) - push_data(client, table, data) + push_data(client_secure, table_secure, data) + push_data(client_free, table_free, data) node = started_cluster.instances['meili'] node.query( - "CREATE TABLE simple_meili_table(id UInt64, data String) ENGINE = MeiliSearch( named_collection_for_meili_secure, key='password')") + "CREATE TABLE simple_meili_table(id UInt64, data String) ENGINE = MeiliSearch( named_collection_for_meili_secure )") node.query( - "CREATE TABLE wrong_meili_table(id UInt64, data String) ENGINE = MeiliSearch( named_collection_for_meili_secure )") + "CREATE TABLE wrong_meili_table(id UInt64, data String) ENGINE = MeiliSearch( named_collection_for_meili_secure_no_password )") + + node.query( + "CREATE TABLE combine_meili_table(id UInt64, data String) ENGINE = MeiliSearch( named_collection_for_meili_secure_no_password, password=\"password\" )") assert node.query("SELECT COUNT() FROM simple_meili_table") == '100\n' assert node.query("SELECT sum(id) FROM simple_meili_table") == str(sum(range(0, 100))) + '\n' assert node.query("SELECT data FROM simple_meili_table WHERE id = 42") == hex(42 * 42) + '\n' + assert node.query("SELECT COUNT() FROM combine_meili_table") == '100\n' + assert node.query("SELECT sum(id) FROM combine_meili_table") == str(sum(range(0, 100))) + '\n' + assert node.query("SELECT data FROM combine_meili_table WHERE id = 42") == hex(42 * 42) + '\n' + + error = node.query_and_get_error("SELECT COUNT() FROM wrong_meili_table") assert("MEILISEARCH_EXCEPTION" in error) @@ -457,7 +469,10 @@ def test_named_collection_secure(started_cluster): node.query("DROP TABLE simple_meili_table") node.query("DROP TABLE wrong_meili_table") - table.delete() + node.query("DROP TABLE combine_meili_table") + table_secure.delete() + table_free.delete() + @pytest.mark.parametrize('started_cluster', [False], indirect=['started_cluster']) def test_table_function(started_cluster):