mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-22 15:42:02 +00:00
refactor parseTypeOfField & fix tests
This commit is contained in:
parent
96cfc7f07a
commit
1886d9c2ea
@ -1,14 +1,14 @@
|
|||||||
version: '2.3'
|
version: '2.3'
|
||||||
services:
|
services:
|
||||||
meili1:
|
meili1:
|
||||||
image: getmeili/meilisearch
|
image: getmeili/meilisearch:latest
|
||||||
restart: always
|
restart: always
|
||||||
command: ./meilisearch
|
command: ./meilisearch
|
||||||
ports:
|
ports:
|
||||||
- ${MEILI_EXTERNAL_PORT}:${MEILI_INTERNAL_PORT}
|
- ${MEILI_EXTERNAL_PORT}:${MEILI_INTERNAL_PORT}
|
||||||
|
|
||||||
meili_secure:
|
meili_secure:
|
||||||
image: getmeili/meilisearch
|
image: getmeili/meilisearch:latest
|
||||||
restart: always
|
restart: always
|
||||||
command: ./meilisearch --master-key="password"
|
command: ./meilisearch --master-key="password"
|
||||||
ports:
|
ports:
|
||||||
|
@ -1,11 +1,14 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
#include <Storages/MeiliSearch/MeiliSearchColumnDescriptionFetcher.h>
|
#include <Storages/MeiliSearch/MeiliSearchColumnDescriptionFetcher.h>
|
||||||
#include <base/JSON.h>
|
#include <base/JSON.h>
|
||||||
#include "DataTypes/DataTypeArray.h"
|
#include <DataTypes/DataTypeArray.h>
|
||||||
#include "DataTypes/DataTypeNullable.h"
|
#include <DataTypes/DataTypeNullable.h>
|
||||||
#include "DataTypes/DataTypeString.h"
|
#include <DataTypes/DataTypeString.h>
|
||||||
#include "DataTypes/DataTypesNumber.h"
|
#include <DataTypes/DataTypesNumber.h>
|
||||||
#include "DataTypes/Serializations/ISerialization.h"
|
#include <DataTypes/Serializations/ISerialization.h>
|
||||||
|
#include <IO/ReadHelpers.h>
|
||||||
|
#include <base/types.h>
|
||||||
|
|
||||||
namespace DB
|
namespace DB
|
||||||
{
|
{
|
||||||
@ -25,12 +28,9 @@ void MeiliSearchColumnDescriptionFetcher::addParam(const String & key, const Str
|
|||||||
query_params[key] = val;
|
query_params[key] = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isDouble(const std::string & val)
|
bool checkIfInteger(const String & s)
|
||||||
{
|
{
|
||||||
std::istringstream iss(val);
|
return s.find('.') == String::npos;
|
||||||
double f;
|
|
||||||
iss >> std::noskipws >> f;
|
|
||||||
return iss.eof() && !iss.fail() && static_cast<Int64>(f) != f;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DataTypePtr parseTypeOfField(JSON ptr)
|
DataTypePtr parseTypeOfField(JSON ptr)
|
||||||
@ -53,19 +53,15 @@ DataTypePtr parseTypeOfField(JSON ptr)
|
|||||||
DataTypePtr res = std::make_shared<DataTypeNullable>(res);
|
DataTypePtr res = std::make_shared<DataTypeNullable>(res);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
if (isDouble(ptr.toString()))
|
|
||||||
{
|
|
||||||
return std::make_shared<DataTypeFloat64>();
|
|
||||||
}
|
|
||||||
if (ptr.isNumber())
|
if (ptr.isNumber())
|
||||||
{
|
{
|
||||||
return std::make_shared<DataTypeInt64>();
|
if (checkIfInteger(ptr.toString()))
|
||||||
|
{
|
||||||
|
return std::make_shared<DataTypeInt64>();
|
||||||
|
}
|
||||||
|
return std::make_shared<DataTypeFloat64>();
|
||||||
}
|
}
|
||||||
if (ptr.isObject())
|
return std::make_shared<DataTypeString>();
|
||||||
{
|
|
||||||
return std::make_shared<DataTypeString>();
|
|
||||||
}
|
|
||||||
throw Exception(ErrorCodes::UNSUPPORTED_MEILISEARCH_TYPE, "Can't recognize type of some fields");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ColumnsDescription MeiliSearchColumnDescriptionFetcher::fetchColumnsDescription() const
|
ColumnsDescription MeiliSearchColumnDescriptionFetcher::fetchColumnsDescription() const
|
||||||
|
@ -28,7 +28,14 @@ CURLcode MeiliSearchConnection::execQuery(std::string_view url, std::string_view
|
|||||||
|
|
||||||
headers_list = nullptr;
|
headers_list = nullptr;
|
||||||
headers_list = curl_slist_append(headers_list, "Content-Type: application/json");
|
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();
|
handle = curl_easy_init();
|
||||||
curl_easy_setopt(handle, CURLOPT_URL, url.data());
|
curl_easy_setopt(handle, CURLOPT_URL, url.data());
|
||||||
|
@ -10,14 +10,15 @@ namespace DB
|
|||||||
{
|
{
|
||||||
struct MeiliSearchConfiguration
|
struct MeiliSearchConfiguration
|
||||||
{
|
{
|
||||||
|
inline const static String key_prefix = "Authorization: Bearer ";
|
||||||
|
|
||||||
String key;
|
String key;
|
||||||
String index;
|
String index;
|
||||||
String connection_string;
|
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_ + "/";
|
connection_string = url_ + "/indexes/" + index_ + "/";
|
||||||
key = "Authorization: Bearer " + key_;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -126,48 +126,33 @@ MeiliSearchConfiguration StorageMeiliSearch::getConfiguration(ASTs engine_args,
|
|||||||
if (auto named_collection = getExternalDataSourceConfiguration(engine_args, context))
|
if (auto named_collection = getExternalDataSourceConfiguration(engine_args, context))
|
||||||
{
|
{
|
||||||
auto [common_configuration, storage_specific_args] = named_collection.value();
|
auto [common_configuration, storage_specific_args] = named_collection.value();
|
||||||
|
|
||||||
String url = common_configuration.addresses_expr;
|
String url = common_configuration.addresses_expr;
|
||||||
String index = common_configuration.table;
|
String index = common_configuration.table;
|
||||||
String key = common_configuration.password;
|
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<ASTLiteral>()->value.safeGet<String>(),
|
|
||||||
ErrorCodes::BAD_ARGUMENTS);
|
|
||||||
url = arg_value->as<ASTLiteral>()->value.safeGet<String>();
|
|
||||||
}
|
|
||||||
else if (arg_name == "key" || arg_name == "password")
|
|
||||||
{
|
|
||||||
if (!key.empty())
|
|
||||||
throw Exception(
|
|
||||||
"2 times given 'key' value, old = " + key + " new = " + arg_value->as<ASTLiteral>()->value.safeGet<String>(),
|
|
||||||
ErrorCodes::BAD_ARGUMENTS);
|
|
||||||
key = arg_value->as<ASTLiteral>()->value.safeGet<String>();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
throw Exception("Unexpected key-value argument", ErrorCodes::BAD_ARGUMENTS);
|
|
||||||
}
|
|
||||||
if (url.empty() || index.empty())
|
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);
|
return MeiliSearchConfiguration(url, index, key);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (engine_args.size() != 3)
|
if (engine_args.size() < 2 || 3 < engine_args.size())
|
||||||
{
|
{
|
||||||
throw Exception(
|
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);
|
ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH);
|
||||||
}
|
}
|
||||||
|
|
||||||
String url = engine_args[0]->as<ASTLiteral &>().value.safeGet<String>();
|
String url = engine_args[0]->as<ASTLiteral &>().value.safeGet<String>();
|
||||||
String index = engine_args[1]->as<ASTLiteral &>().value.safeGet<String>();
|
String index = engine_args[1]->as<ASTLiteral &>().value.safeGet<String>();
|
||||||
String key = engine_args[2]->as<ASTLiteral &>().value.safeGet<String>();
|
String key;
|
||||||
|
if (engine_args.size() == 3)
|
||||||
|
key = engine_args[2]->as<ASTLiteral &>().value.safeGet<String>();
|
||||||
return MeiliSearchConfiguration(url, index, key);
|
return MeiliSearchConfiguration(url, index, key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,14 @@
|
|||||||
<database>MeiliSearch</database>
|
<database>MeiliSearch</database>
|
||||||
<addresses_expr>meili_secure:7700</addresses_expr>
|
<addresses_expr>meili_secure:7700</addresses_expr>
|
||||||
<table>new_table</table>
|
<table>new_table</table>
|
||||||
|
<password>password</password>
|
||||||
</named_collection_for_meili_secure>
|
</named_collection_for_meili_secure>
|
||||||
|
|
||||||
|
|
||||||
|
<named_collection_for_meili_secure_no_password>
|
||||||
|
<database>MeiliSearch</database>
|
||||||
|
<addresses_expr>meili_secure:7700</addresses_expr>
|
||||||
|
<table>new_table</table>
|
||||||
|
</named_collection_for_meili_secure_no_password>
|
||||||
</named_collections>
|
</named_collections>
|
||||||
</clickhouse>
|
</clickhouse>
|
||||||
|
@ -427,25 +427,37 @@ def test_named_collection(started_cluster):
|
|||||||
|
|
||||||
@pytest.mark.parametrize('started_cluster', [False], indirect=['started_cluster'])
|
@pytest.mark.parametrize('started_cluster', [False], indirect=['started_cluster'])
|
||||||
def test_named_collection_secure(started_cluster):
|
def test_named_collection_secure(started_cluster):
|
||||||
client = get_meili_secure_client(started_cluster)
|
client_secure = get_meili_secure_client(started_cluster)
|
||||||
table = client.index("new_table")
|
client_free = get_meili_client(started_cluster)
|
||||||
|
table_secure = client_secure.index("new_table")
|
||||||
|
table_free = client_free.index("new_table")
|
||||||
|
|
||||||
data = []
|
data = []
|
||||||
for i in range(0, 100):
|
for i in range(0, 100):
|
||||||
data.append({'id': i, 'data': hex(i * i)})
|
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 = started_cluster.instances['meili']
|
||||||
node.query(
|
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(
|
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 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 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 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")
|
error = node.query_and_get_error("SELECT COUNT() FROM wrong_meili_table")
|
||||||
assert("MEILISEARCH_EXCEPTION" in error)
|
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 simple_meili_table")
|
||||||
node.query("DROP TABLE wrong_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'])
|
@pytest.mark.parametrize('started_cluster', [False], indirect=['started_cluster'])
|
||||||
def test_table_function(started_cluster):
|
def test_table_function(started_cluster):
|
||||||
|
Loading…
Reference in New Issue
Block a user