Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions ydb/core/tx/schemeshard/schemeshard_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,18 @@ bool CommonCheck(const TTableDesc& tableDesc, const NKikimrSchemeOp::TIndexCreat
error = TStringBuilder() << "fulltext index can only have a single key text column";
return false;
}
if (indexDesc.GetFulltextIndexDescription().GetSettings().Getcolumns().size() != 1) {
status = NKikimrScheme::EStatus::StatusInvalidParameter;
error = TStringBuilder() << "fulltext index should have single '" << indexKeys.KeyColumns.at(0) << "' column settings"
<< " but have " << indexDesc.GetFulltextIndexDescription().GetSettings().Getcolumns().size() << " of them";
return false;
}
if (indexDesc.GetFulltextIndexDescription().GetSettings().Getcolumns().at(0).Getcolumn() != indexKeys.KeyColumns.at(0)) {
status = NKikimrScheme::EStatus::StatusInvalidParameter;
error = TStringBuilder() << "fulltext index should have '" << indexKeys.KeyColumns.at(0) << "' column settings"
<< " but have '" << indexDesc.GetFulltextIndexDescription().GetSettings().Getcolumns().at(0).Getcolumn() << "' column settings";
return false;
}

const TString& indexColumnName = indexKeys.KeyColumns.back();
Y_ABORT_UNLESS(baseColumnTypes.contains(indexColumnName));
Expand Down
42 changes: 30 additions & 12 deletions ydb/core/tx/schemeshard/ut_helpers/ls_checks.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "ls_checks.h"

#include <google/protobuf/text_format.h>
#include <ydb/public/api/protos/ydb_cms.pb.h>
#include <ydb/public/api/protos/ydb_coordination.pb.h>
#include <ydb/public/lib/scheme_types/scheme_type_id.h>
Expand Down Expand Up @@ -914,20 +915,37 @@ TCheckFunc KMeansTreeDescription(Ydb::Table::VectorIndexSettings_Metric metric,

TCheckFunc SpecializedIndexDescription(const TString& proto) {
return [=] (const NKikimrScheme::TEvDescribeSchemeResult& record) {
TString actual;
switch (record.GetPathDescription().GetTableIndex().GetSpecializedIndexDescriptionCase()) {
case NKikimrSchemeOp::TIndexDescription::kVectorIndexKmeansTreeDescription:
actual = record.GetPathDescription().GetTableIndex().GetVectorIndexKmeansTreeDescription().GetSettings().ShortDebugString();
break;
case NKikimrSchemeOp::TIndexDescription::kFulltextIndexDescription:
actual = record.GetPathDescription().GetTableIndex().GetFulltextIndexDescription().GetSettings().ShortDebugString();
break;
case NKikimrSchemeOp::TIndexDescription::SPECIALIZEDINDEXDESCRIPTION_NOT_SET:
actual = "SPECIALIZEDINDEXDESCRIPTION_NOT_SET";
break;
case NKikimrSchemeOp::TIndexDescription::kVectorIndexKmeansTreeDescription: {
auto actual = record.GetPathDescription().GetTableIndex().GetVectorIndexKmeansTreeDescription().GetSettings();
Ydb::Table::KMeansTreeSettings expected;
UNIT_ASSERT(google::protobuf::TextFormat::ParseFromString(proto, &expected));
UNIT_ASSERT_C(google::protobuf::util::MessageDifferencer::Equals(actual, expected),
TStringBuilder() << "Expected"
<< expected.ShortDebugString()
<< " but got "
<< actual.ShortDebugString());
break;
}
case NKikimrSchemeOp::TIndexDescription::kFulltextIndexDescription: {
auto actual = record.GetPathDescription().GetTableIndex().GetFulltextIndexDescription().GetSettings();
Ydb::Table::FulltextIndexSettings expected;
UNIT_ASSERT(google::protobuf::TextFormat::ParseFromString(proto, &expected));
UNIT_ASSERT_C(google::protobuf::util::MessageDifferencer::Equals(actual, expected),
TStringBuilder() << "Expected"
<< expected.ShortDebugString()
<< " but got "
<< actual.ShortDebugString());
break;
}
case NKikimrSchemeOp::TIndexDescription::SPECIALIZEDINDEXDESCRIPTION_NOT_SET: {
UNIT_ASSERT_C(proto == "SPECIALIZEDINDEXDESCRIPTION_NOT_SET",
TStringBuilder() << "Expected"
<< proto
<< " but got SPECIALIZEDINDEXDESCRIPTION_NOT_SET");
break;
}
}

UNIT_ASSERT_VALUES_EQUAL(actual, proto);
};
}

Expand Down
258 changes: 218 additions & 40 deletions ydb/core/tx/schemeshard/ut_index/ut_fulltext_index.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,23 +18,38 @@ Y_UNIT_TEST_SUITE(TFulltextIndexTests) {
TTestEnv env(runtime);
ui64 txId = 100;

TestCreateIndexedTable(runtime, ++txId, "/MyRoot", R"(
TString fulltextSettings = R"(
layout: FLAT
columns: {
column: "text"
analyzers: {
tokenizer: STANDARD
use_filter_ngram: true
filter_ngram_max_length: 42
}
}
)";
TestCreateIndexedTable(runtime, ++txId, "/MyRoot", Sprintf(R"(
TableDescription {
Name: "texts"
Columns { Name: "id" Type: "Uint64" }
Columns { Name: "text" Type: "String" }
Columns { Name: "covered" Type: "String" }
Columns { Name: "another" Type: "Uint64" }
KeyColumnNames: ["id"]
Name: "texts"
Columns { Name: "id" Type: "Uint64" }
Columns { Name: "text" Type: "String" }
Columns { Name: "covered" Type: "String" }
Columns { Name: "another" Type: "Uint64" }
KeyColumnNames: ["id"]
}
IndexDescription {
Name: "idx_fulltext"
KeyColumnNames: ["text"]
DataColumnNames: ["covered"]
Type: EIndexTypeGlobalFulltext
FulltextIndexDescription: { Settings: { layout: FLAT, tokenizer: STANDARD, use_filter_ngram: true, filter_ngram_max_length: 42 } }
Name: "idx_fulltext"
KeyColumnNames: ["text"]
DataColumnNames: ["covered"]
Type: EIndexTypeGlobalFulltext
FulltextIndexDescription: {
Settings: {
%s
}
}
}
)");
)", fulltextSettings.c_str()));
env.TestWaitNotification(runtime, txId);

NKikimrSchemeOp::TDescribeOptions opts;
Expand All @@ -49,7 +64,7 @@ Y_UNIT_TEST_SUITE(TFulltextIndexTests) {
NLs::IndexState(NKikimrSchemeOp::EIndexStateReady),
NLs::IndexKeys({"text"}),
NLs::IndexDataColumns({"covered"}),
NLs::SpecializedIndexDescription("layout: FLAT tokenizer: STANDARD use_filter_ngram: true filter_ngram_max_length: 42"),
NLs::SpecializedIndexDescription(fulltextSettings),
NLs::ChildrenCount(1),
});

Expand All @@ -70,23 +85,91 @@ Y_UNIT_TEST_SUITE(TFulltextIndexTests) {
TTestEnv env(runtime);
ui64 txId = 100;

TestCreateIndexedTable(runtime, ++txId, "/MyRoot", R"(
TString fulltextSettings = R"(
layout: FLAT
columns: {
column: "text"
analyzers: {
tokenizer: STANDARD
use_filter_ngram: true
filter_ngram_max_length: 42
}
}
)";
TestCreateIndexedTable(runtime, ++txId, "/MyRoot", Sprintf(R"(
TableDescription {
Name: "texts"
Columns { Name: "id" Type: "Uint64" }
Columns { Name: "text" Type: "String" }
Columns { Name: "covered" Type: "String" }
Columns { Name: "another" Type: "Uint64" }
KeyColumnNames: ["id"]
}
IndexDescription {
Name: "idx_fulltext"
KeyColumnNames: [ "another", "text"]
DataColumnNames: ["covered"]
Type: EIndexTypeGlobalFulltext
FulltextIndexDescription: {
Settings: {
%s
}
}
}
)", fulltextSettings.c_str()), {NKikimrScheme::StatusInvalidParameter});
env.TestWaitNotification(runtime, txId);

TestDescribeResult(DescribePrivatePath(runtime, "/MyRoot/texts/idx_fulltext"),{
NLs::PathNotExist,
});
}

Y_UNIT_TEST(CreateTableMultipleColumns) { // not supported for now, maybe later
TTestBasicRuntime runtime;
TTestEnv env(runtime);
ui64 txId = 100;

TString fulltextSettings = R"(
layout: FLAT
columns: {
column: "text1"
analyzers: {
tokenizer: STANDARD
use_filter_ngram: true
filter_ngram_max_length: 42
}
}
columns: {
column: "text2"
analyzers: {
tokenizer: STANDARD
use_filter_ngram: true
filter_ngram_max_length: 42
}
}
)";
TestCreateIndexedTable(runtime, ++txId, "/MyRoot", Sprintf(R"(
TableDescription {
Name: "texts"
Columns { Name: "id" Type: "Uint64" }
Columns { Name: "text" Type: "String" }
Columns { Name: "covered" Type: "String" }
Columns { Name: "another" Type: "Uint64" }
KeyColumnNames: [ "id"]
Name: "texts"
Columns { Name: "id" Type: "Uint64" }
Columns { Name: "text1" Type: "String" }
Columns { Name: "text2" Type: "String" }
Columns { Name: "covered" Type: "String" }
Columns { Name: "another" Type: "Uint64" }
KeyColumnNames: ["id"]
}
IndexDescription {
Name: "idx_fulltext"
KeyColumnNames: [ "another", "text"]
DataColumnNames: ["covered"]
Type: EIndexTypeGlobalFulltext
FulltextIndexDescription: { Settings: { layout: FLAT, tokenizer: STANDARD, use_filter_ngram: true, filter_ngram_max_length: 42 } }
Name: "idx_fulltext"
KeyColumnNames: ["text1", "text2"]
DataColumnNames: ["covered"]
Type: EIndexTypeGlobalFulltext
FulltextIndexDescription: {
Settings: {
%s
}
}
}
)", {NKikimrScheme::StatusInvalidParameter});
)", fulltextSettings.c_str()), {NKikimrScheme::StatusInvalidParameter});
env.TestWaitNotification(runtime, txId);

TestDescribeResult(DescribePrivatePath(runtime, "/MyRoot/texts/idx_fulltext"),{
Expand All @@ -99,23 +182,118 @@ Y_UNIT_TEST_SUITE(TFulltextIndexTests) {
TTestEnv env(runtime);
ui64 txId = 100;

TestCreateIndexedTable(runtime, ++txId, "/MyRoot", R"(
TString fulltextSettings = R"(
layout: FLAT
columns: {
column: "text"
analyzers: {
tokenizer: STANDARD
use_filter_ngram: true
filter_ngram_max_length: 42
}
}
)";
TestCreateIndexedTable(runtime, ++txId, "/MyRoot", Sprintf(R"(
TableDescription {
Name: "texts"
Columns { Name: "id" Type: "Uint64" }
Columns { Name: "text" Type: "Uint64" }
Columns { Name: "covered" Type: "String" }
Columns { Name: "another" Type: "Uint64" }
KeyColumnNames: ["id"]
}
IndexDescription {
Name: "idx_fulltext"
KeyColumnNames: ["text"]
DataColumnNames: ["covered"]
Type: EIndexTypeGlobalFulltext
FulltextIndexDescription: {
Settings: {
%s
}
}
}
)", fulltextSettings.c_str()), {NKikimrScheme::StatusInvalidParameter});
env.TestWaitNotification(runtime, txId);

TestDescribeResult(DescribePrivatePath(runtime, "/MyRoot/texts/idx_fulltext"),{
NLs::PathNotExist,
});
}

Y_UNIT_TEST(CreateTableColumnsMismatch) {
TTestBasicRuntime runtime;
TTestEnv env(runtime);
ui64 txId = 100;

TString fulltextSettings = R"(
layout: FLAT
columns: {
column: "text_wrong"
analyzers: {
tokenizer: STANDARD
use_filter_ngram: true
filter_ngram_max_length: 42
}
}
)";
TestCreateIndexedTable(runtime, ++txId, "/MyRoot", Sprintf(R"(
TableDescription {
Name: "texts"
Columns { Name: "id" Type: "Uint64" }
Columns { Name: "text" Type: "String" }
Columns { Name: "covered" Type: "String" }
Columns { Name: "another" Type: "Uint64" }
KeyColumnNames: ["id"]
}
IndexDescription {
Name: "idx_fulltext"
KeyColumnNames: ["text"]
DataColumnNames: ["covered"]
Type: EIndexTypeGlobalFulltext
FulltextIndexDescription: {
Settings: {
%s
}
}
}
)", fulltextSettings.c_str()), {NKikimrScheme::StatusInvalidParameter});
env.TestWaitNotification(runtime, txId);

TestDescribeResult(DescribePrivatePath(runtime, "/MyRoot/texts/idx_fulltext"),{
NLs::PathNotExist,
});
}

Y_UNIT_TEST(CreateTableNoColumnsSettings) {
TTestBasicRuntime runtime;
TTestEnv env(runtime);
ui64 txId = 100;

TString fulltextSettings = R"(
layout: FLAT
)";
TestCreateIndexedTable(runtime, ++txId, "/MyRoot", Sprintf(R"(
TableDescription {
Name: "texts"
Columns { Name: "id" Type: "Uint64" }
Columns { Name: "text" Type: "Uint64" }
Columns { Name: "covered" Type: "String" }
Columns { Name: "another" Type: "Uint64" }
KeyColumnNames: ["id"]
Name: "texts"
Columns { Name: "id" Type: "Uint64" }
Columns { Name: "text" Type: "String" }
Columns { Name: "covered" Type: "String" }
Columns { Name: "another" Type: "Uint64" }
KeyColumnNames: ["id"]
}
IndexDescription {
Name: "idx_fulltext"
KeyColumnNames: ["text"]
DataColumnNames: ["covered"]
Type: EIndexTypeGlobalFulltext
FulltextIndexDescription: { Settings: { layout: FLAT, tokenizer: STANDARD, use_filter_ngram: true, filter_ngram_max_length: 42 } }
Name: "idx_fulltext"
KeyColumnNames: ["text"]
DataColumnNames: ["covered"]
Type: EIndexTypeGlobalFulltext
FulltextIndexDescription: {
Settings: {
%s
}
}
}
)", {NKikimrScheme::StatusInvalidParameter});
)", fulltextSettings.c_str()), {NKikimrScheme::StatusInvalidParameter});
env.TestWaitNotification(runtime, txId);

TestDescribeResult(DescribePrivatePath(runtime, "/MyRoot/texts/idx_fulltext"),{
Expand Down
Loading
Loading