aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorivanmorozov <ivanmorozov@yandex-team.com>2022-11-17 15:27:11 +0300
committerivanmorozov <ivanmorozov@yandex-team.com>2022-11-17 15:27:11 +0300
commit2ea084bfc239ef31c3483557bcccd2871b59dc42 (patch)
tree81c2ff02c423159557f32a5d805583ddc6513621
parentde958bc48ec6f97a3ea97a990bfa5ddae7ada4a7 (diff)
downloadydb-2ea084bfc239ef31c3483557bcccd2871b59dc42.tar.gz
object workflow in yql
-rw-r--r--ydb/library/yql/sql/v1/CMakeLists.txt1
-rw-r--r--ydb/library/yql/sql/v1/SQLv1.g.in42
-rw-r--r--ydb/library/yql/sql/v1/format/sql_format.cpp23
-rw-r--r--ydb/library/yql/sql/v1/format/sql_format_ut.cpp14
-rw-r--r--ydb/library/yql/sql/v1/node.h7
-rw-r--r--ydb/library/yql/sql/v1/object_processing.cpp62
-rw-r--r--ydb/library/yql/sql/v1/object_processing.h76
-rw-r--r--ydb/library/yql/sql/v1/query.cpp16
-rw-r--r--ydb/library/yql/sql/v1/sql.cpp213
-rw-r--r--ydb/library/yql/sql/v1/sql_ut.cpp121
10 files changed, 533 insertions, 42 deletions
diff --git a/ydb/library/yql/sql/v1/CMakeLists.txt b/ydb/library/yql/sql/v1/CMakeLists.txt
index 03584bb68e2..9d15e3cb086 100644
--- a/ydb/library/yql/sql/v1/CMakeLists.txt
+++ b/ydb/library/yql/sql/v1/CMakeLists.txt
@@ -51,6 +51,7 @@ target_sources(yql-sql-v1 PRIVATE
${CMAKE_SOURCE_DIR}/ydb/library/yql/sql/v1/select.cpp
${CMAKE_SOURCE_DIR}/ydb/library/yql/sql/v1/sql.cpp
${CMAKE_SOURCE_DIR}/ydb/library/yql/sql/v1/query.cpp
+ ${CMAKE_SOURCE_DIR}/ydb/library/yql/sql/v1/object_processing.cpp
)
generate_enum_serilization(yql-sql-v1
${CMAKE_SOURCE_DIR}/ydb/library/yql/sql/v1/node.h
diff --git a/ydb/library/yql/sql/v1/SQLv1.g.in b/ydb/library/yql/sql/v1/SQLv1.g.in
index d89c57ce850..5a5a0272bdb 100644
--- a/ydb/library/yql/sql/v1/SQLv1.g.in
+++ b/ydb/library/yql/sql/v1/SQLv1.g.in
@@ -44,6 +44,9 @@ sql_stmt_core:
| create_group_stmt
| alter_group_stmt
| drop_role_stmt
+ | create_object_stmt
+ | alter_object_stmt
+ | drop_object_stmt
;
expr:
@@ -450,6 +453,38 @@ values_source_row: LPAREN expr_list RPAREN;
simple_values_source: expr_list | select_stmt;
+create_object_stmt: CREATE OBJECT object_ref
+ LPAREN
+ TYPE object_type_ref
+ create_object_features?
+ RPAREN
+;
+create_object_features: WITH object_features;
+
+alter_object_stmt: ALTER OBJECT object_ref
+ LPAREN
+ TYPE object_type_ref
+ alter_object_features
+ RPAREN
+;
+alter_object_features: SET object_features;
+
+drop_object_stmt: DROP OBJECT object_ref
+ LPAREN
+ TYPE object_type_ref
+ drop_object_options?
+ RPAREN
+;
+drop_object_options: WITH object_features;
+
+object_feature_value: an_id_or_type | bind_parameter;
+object_feature_kv: an_id_or_type EQUALS object_feature_value;
+object_feature_flag: an_id_or_type;
+object_feature: object_feature_kv | object_feature_flag;
+object_features: object_feature (COMMA object_feature)*;
+
+object_type_ref: an_id_or_type;
+
create_table_stmt: CREATE (TABLE | TABLESTORE) simple_table_ref LPAREN create_table_entry (COMMA create_table_entry)* RPAREN
table_inherits?
table_partition_by?
@@ -534,7 +569,7 @@ changefeed_setting_value:
STRING_VALUE
| bool_value
;
-changefeed_alter_settings:
+changefeed_alter_settings:
DISABLE
| SET LPAREN changefeed_settings RPAREN
;
@@ -593,7 +628,8 @@ table_hint:
| SCHEMA EQUALS? LPAREN (struct_arg_positional (COMMA struct_arg_positional)*)? COMMA? RPAREN
;
-simple_table_ref_core: ((cluster_expr DOT)? id_or_at) | AT? bind_parameter;
+object_ref: (cluster_expr DOT)? id_or_at;
+simple_table_ref_core: object_ref | AT? bind_parameter;
simple_table_ref: simple_table_ref_core table_hints?;
into_simple_table_ref: simple_table_ref (ERASE BY pure_column_list)?;
@@ -1002,6 +1038,7 @@ keyword_compat: (
| TEMPORARY
| THEN
| TIES
+ | TYPE
| TO
| TRANSACTION
| TRIGGER
@@ -1318,6 +1355,7 @@ TEMP: T E M P;
TEMPORARY: T E M P O R A R Y;
THEN: T H E N;
TIES: T I E S;
+TYPE: T Y P E;
TO: T O;
TRANSACTION: T R A N S A C T I O N;
TRIGGER: T R I G G E R;
diff --git a/ydb/library/yql/sql/v1/format/sql_format.cpp b/ydb/library/yql/sql/v1/format/sql_format.cpp
index 53a1381dbcc..4cddca2138d 100644
--- a/ydb/library/yql/sql/v1/format/sql_format.cpp
+++ b/ydb/library/yql/sql/v1/format/sql_format.cpp
@@ -901,6 +901,24 @@ private:
VisitAllFields(TRule_drop_role_stmt::GetDescriptor(), msg);
}
+ void VisitCreateObject(const TRule_create_object_stmt& msg) {
+ PosFromToken(msg.GetToken1());
+ NewLine();
+ VisitAllFields(TRule_create_object_stmt::GetDescriptor(), msg);
+ }
+
+ void VisitAlterObject(const TRule_alter_object_stmt& msg) {
+ PosFromToken(msg.GetToken1());
+ NewLine();
+ VisitAllFields(TRule_alter_object_stmt::GetDescriptor(), msg);
+ }
+
+ void VisitDropObject(const TRule_drop_object_stmt& msg) {
+ PosFromToken(msg.GetToken1());
+ NewLine();
+ VisitAllFields(TRule_drop_object_stmt::GetDescriptor(), msg);
+ }
+
void VisitAllFields(const NProtoBuf::Descriptor* descr, const NProtoBuf::Message& msg) {
for (int i = 0; i < descr->field_count(); ++i) {
const NProtoBuf::FieldDescriptor* fd = descr->field(i);
@@ -1762,7 +1780,10 @@ TStaticData::TStaticData()
{TRule_create_group_stmt::GetDescriptor(), MakeFunctor(&TVisitor::VisitCreateGroup)},
{TRule_alter_group_stmt::GetDescriptor(), MakeFunctor(&TVisitor::VisitAlterGroup)},
{TRule_drop_role_stmt::GetDescriptor(), MakeFunctor(&TVisitor::VisitDropRole)},
- })
+ {TRule_create_object_stmt::GetDescriptor(), MakeFunctor(&TVisitor::VisitCreateObject)},
+ {TRule_alter_object_stmt::GetDescriptor(), MakeFunctor(&TVisitor::VisitAlterObject)},
+ {TRule_drop_object_stmt::GetDescriptor(), MakeFunctor(&TVisitor::VisitDropObject)},
+ })
{
// ensure that all statements has a visitor
auto coreDescr = TRule_sql_stmt_core::GetDescriptor();
diff --git a/ydb/library/yql/sql/v1/format/sql_format_ut.cpp b/ydb/library/yql/sql/v1/format/sql_format_ut.cpp
index a27d557e3ed..779398efb89 100644
--- a/ydb/library/yql/sql/v1/format/sql_format_ut.cpp
+++ b/ydb/library/yql/sql/v1/format/sql_format_ut.cpp
@@ -248,6 +248,20 @@ Y_UNIT_TEST_SUITE(CheckSqlFormatter) {
setup.Run(cases);
}
+ Y_UNIT_TEST(ObjectOperations) {
+ TCases cases = {
+ {"alter oBject usEr (TYpe abcde Set a = b)",
+ "ALTER OBJECT usEr (TYPE abcde SET a = b);\n"},
+ {"creAte oBject usEr (tYpe abcde With a = b)",
+ "CREATE OBJECT usEr (TYPE abcde WITH a = b);\n"},
+ {"dRop oBject usEr (tYpe abcde With aeEE)",
+ "DROP OBJECT usEr (TYPE abcde WITH aeEE);\n"}
+ };
+
+ TSetup setup;
+ setup.Run(cases);
+ }
+
Y_UNIT_TEST(AlterTable) {
TCases cases = {
{"alter table user add user int32",
diff --git a/ydb/library/yql/sql/v1/node.h b/ydb/library/yql/sql/v1/node.h
index e47b8ce49ab..e5591e42b3a 100644
--- a/ydb/library/yql/sql/v1/node.h
+++ b/ydb/library/yql/sql/v1/node.h
@@ -82,6 +82,7 @@ namespace NSQLTranslationV1 {
class ITableKeys;
class ISource;
class IAggregation;
+ class TObjectOperatorContext;
typedef TIntrusivePtr<IAggregation> TAggregationPtr;
struct TScopedState;
@@ -1380,6 +1381,12 @@ namespace NSQLTranslationV1 {
TScopedStatePtr scoped);
TNodePtr BuildRenameGroup(TPosition pos, const TString& service, const TDeferredAtom& cluster, const TDeferredAtom& name, const TDeferredAtom& newName, TScopedStatePtr scoped);
TNodePtr BuildDropRoles(TPosition pos, const TString& service, const TDeferredAtom& cluster, const TVector<TDeferredAtom>& toDrop, bool isUser, bool force, TScopedStatePtr scoped);
+ TNodePtr BuildCreateObjectOperation(TPosition pos, const TString& objectId, const TString& typeId,
+ std::map<TString, TDeferredAtom>&& features, const TObjectOperatorContext& context);
+ TNodePtr BuildAlterObjectOperation(TPosition pos, const TString& secretId, const TString& typeId,
+ std::map<TString, TDeferredAtom>&& features, const TObjectOperatorContext& context);
+ TNodePtr BuildDropObjectOperation(TPosition pos, const TString& secretId, const TString& typeId,
+ std::map<TString, TDeferredAtom>&& options, const TObjectOperatorContext& context);
TNodePtr BuildWriteTable(TPosition pos, const TString& label, const TTableRef& table, EWriteColumnMode mode, TNodePtr options,
TScopedStatePtr scoped);
TNodePtr BuildWriteResult(TPosition pos, const TString& label, TNodePtr settings);
diff --git a/ydb/library/yql/sql/v1/object_processing.cpp b/ydb/library/yql/sql/v1/object_processing.cpp
new file mode 100644
index 00000000000..d59b52efd95
--- /dev/null
+++ b/ydb/library/yql/sql/v1/object_processing.cpp
@@ -0,0 +1,62 @@
+#include "object_processing.h"
+
+#include <ydb/library/yql/core/yql_callable_names.h>
+
+namespace NSQLTranslationV1 {
+using namespace NYql;
+
+INode::TPtr TObjectProcessorImpl::BuildKeys() const {
+ auto keys = Y("Key");
+ keys = L(keys, Q(Y(Q("objectId"), Y("String", BuildQuotedAtom(Pos, ObjectId)))));
+ keys = L(keys, Q(Y(Q("typeId"), Y("String", BuildQuotedAtom(Pos, TypeId)))));
+ return keys;
+}
+
+TObjectProcessorImpl::TObjectProcessorImpl(TPosition pos, const TString& objectId, const TString& typeId, const TObjectOperatorContext& context)
+ : TBase(pos)
+ , TObjectOperatorContext(context)
+ , ObjectId(objectId)
+ , TypeId(typeId)
+{
+
+}
+
+bool TObjectProcessorImpl::DoInit(TContext& ctx, ISource* src) {
+ Y_UNUSED(src);
+ Scoped->UseCluster(ServiceId, Cluster);
+ auto options = FillFeatures(BuildOptions());
+ auto keys = BuildKeys();
+
+ Add("block", Q(Y(
+ Y("let", "sink", Y("DataSink", BuildQuotedAtom(Pos, ServiceId), Scoped->WrapCluster(Cluster, ctx))),
+ Y("let", "world", Y(TString(WriteName), "world", "sink", keys, Y("Void"), Q(options))),
+ Y("return", ctx.PragmaAutoCommit ? Y(TString(CommitName), "world", "sink") : AstNode("world"))
+ )));
+ return TAstListNode::DoInit(ctx, src);
+}
+
+INode::TPtr TCreateObject::FillFeatures(INode::TPtr options) const {
+ if (Features.size()) {
+ auto features = Y();
+ for (auto&& i : Features) {
+ if (!i.second.Empty()) {
+ features = L(features, Q(Y(BuildQuotedAtom(Pos, i.first), i.second.Build())));
+ } else {
+ features = L(features, Q(Y(BuildQuotedAtom(Pos, i.first))));
+ }
+ }
+ return L(options, Q(Y(Q("features"), Q(features))));
+ } else {
+ return options;
+ }
+}
+
+TObjectOperatorContext::TObjectOperatorContext(TScopedStatePtr scoped)
+ : Scoped(scoped)
+ , ServiceId(Scoped->CurrService)
+ , Cluster(Scoped->CurrCluster)
+{
+
+}
+
+}
diff --git a/ydb/library/yql/sql/v1/object_processing.h b/ydb/library/yql/sql/v1/object_processing.h
new file mode 100644
index 00000000000..a8ee0e1ef54
--- /dev/null
+++ b/ydb/library/yql/sql/v1/object_processing.h
@@ -0,0 +1,76 @@
+#pragma once
+#include "node.h"
+#include "context.h"
+
+namespace NSQLTranslationV1 {
+
+class TObjectOperatorContext {
+protected:
+ TScopedStatePtr Scoped;
+public:
+ TString ServiceId;
+ TDeferredAtom Cluster;
+ TObjectOperatorContext(const TObjectOperatorContext& baseItem) = default;
+ TObjectOperatorContext(TScopedStatePtr scoped);
+};
+
+class TObjectProcessorImpl: public TAstListNode, public TObjectOperatorContext {
+protected:
+ using TBase = TAstListNode;
+ TString ObjectId;
+ TString TypeId;
+
+ virtual INode::TPtr BuildOptions() const = 0;
+ virtual INode::TPtr FillFeatures(INode::TPtr options) const = 0;
+ INode::TPtr BuildKeys() const;
+public:
+ TObjectProcessorImpl(TPosition pos, const TString& objectId, const TString& typeId, const TObjectOperatorContext& context);
+
+ bool DoInit(TContext& ctx, ISource* src) override;
+
+ TPtr DoClone() const final {
+ return {};
+ }
+};
+
+class TCreateObject: public TObjectProcessorImpl {
+private:
+ using TBase = TObjectProcessorImpl;
+ std::map<TString, TDeferredAtom> Features;
+protected:
+ virtual INode::TPtr BuildOptions() const override {
+ return Y(Q(Y(Q("mode"), Q("createObject"))));
+ }
+ virtual INode::TPtr FillFeatures(INode::TPtr options) const override;
+public:
+ TCreateObject(TPosition pos, const TString& objectId,
+ const TString& typeId, std::map<TString, TDeferredAtom>&& features, const TObjectOperatorContext& context)
+ : TBase(pos, objectId, typeId, context)
+ , Features(std::move(features)) {
+
+ }
+};
+
+class TAlterObject final: public TCreateObject {
+private:
+ using TBase = TCreateObject;
+protected:
+ virtual INode::TPtr BuildOptions() const override {
+ return Y(Q(Y(Q("mode"), Q("alterObject"))));
+ }
+public:
+ using TBase::TBase;
+};
+
+class TDropObject final: public TCreateObject {
+private:
+ using TBase = TCreateObject;
+protected:
+ virtual INode::TPtr BuildOptions() const override {
+ return Y(Q(Y(Q("mode"), Q("dropObject"))));
+ }
+public:
+ using TBase::TBase;
+};
+
+}
diff --git a/ydb/library/yql/sql/v1/query.cpp b/ydb/library/yql/sql/v1/query.cpp
index fe45a5ffc49..359fb2e1b05 100644
--- a/ydb/library/yql/sql/v1/query.cpp
+++ b/ydb/library/yql/sql/v1/query.cpp
@@ -1,5 +1,6 @@
#include "node.h"
#include "context.h"
+#include "object_processing.h"
#include <ydb/library/yql/ast/yql_type_string.h>
#include <ydb/library/yql/core/yql_callable_names.h>
@@ -1492,6 +1493,21 @@ private:
TSourcePtr FakeSource;
};
+TNodePtr BuildCreateObjectOperation(TPosition pos, const TString& objectId, const TString& typeId,
+ std::map<TString, TDeferredAtom>&& features, const TObjectOperatorContext& context) {
+ return new TCreateObject(pos, objectId, typeId, std::move(features), context);
+}
+TNodePtr BuildAlterObjectOperation(TPosition pos, const TString& secretId, const TString& typeId,
+ std::map<TString, TDeferredAtom>&& features, const TObjectOperatorContext& context)
+{
+ return new TAlterObject(pos, secretId, typeId, std::move(features), context);
+}
+TNodePtr BuildDropObjectOperation(TPosition pos, const TString& secretId, const TString& typeId,
+ std::map<TString, TDeferredAtom>&& options, const TObjectOperatorContext& context)
+{
+ return new TDropObject(pos, secretId, typeId, std::move(options), context);
+}
+
TNodePtr BuildDropRoles(TPosition pos, const TString& service, const TDeferredAtom& cluster, const TVector<TDeferredAtom>& toDrop, bool isUser, bool force, TScopedStatePtr scoped) {
return new TDropRoles(pos, service, cluster, toDrop, isUser, force, scoped);
}
diff --git a/ydb/library/yql/sql/v1/sql.cpp b/ydb/library/yql/sql/v1/sql.cpp
index 76bc57bc943..4a89518ead9 100644
--- a/ydb/library/yql/sql/v1/sql.cpp
+++ b/ydb/library/yql/sql/v1/sql.cpp
@@ -3,6 +3,7 @@
#include "context.h"
#include "node.h"
#include "sql_call_param.h"
+#include "object_processing.h"
#include "ydb/library/yql/ast/yql_ast.h"
#include <ydb/library/yql/parser/lexer_common/hints.h>
#include <ydb/library/yql/parser/proto_ast/collect_issues/collect_issues.h>
@@ -496,27 +497,6 @@ static TIdentifier IdEx(const TRule& node, TTranslation& ctx) {
return TIdentifier(pos, name);
}
-static TString OptIdPrefixAsStr(const TRule_opt_id_prefix& node, TTranslation& ctx, const TString& defaultStr = {}) {
- if (!node.HasBlock1()) {
- return defaultStr;
- }
- return Id(node.GetBlock1().GetRule_an_id1(), ctx);
-}
-
-static TString OptIdPrefixAsStr(const TRule_opt_id_prefix_or_type& node, TTranslation& ctx, const TString& defaultStr = {}) {
- if (!node.HasBlock1()) {
- return defaultStr;
- }
- return Id(node.GetBlock1().GetRule_an_id_or_type1(), ctx);
-}
-
-static void PureColumnListStr(const TRule_pure_column_list& node, TTranslation& ctx, TVector<TString>& outList) {
- outList.push_back(Id(node.GetRule_an_id2(), ctx));
- for (auto& block: node.GetBlock3()) {
- outList.push_back(Id(block.GetRule_an_id2(), ctx));
- }
-}
-
static bool NamedNodeImpl(const TRule_bind_parameter& node, TString& name, TTranslation& ctx) {
// bind_parameter: DOLLAR (an_id_or_type | TRUE | FALSE);
TString id;
@@ -543,6 +523,27 @@ static bool NamedNodeImpl(const TRule_bind_parameter& node, TString& name, TTran
return true;
}
+static TString OptIdPrefixAsStr(const TRule_opt_id_prefix& node, TTranslation& ctx, const TString& defaultStr = {}) {
+ if (!node.HasBlock1()) {
+ return defaultStr;
+ }
+ return Id(node.GetBlock1().GetRule_an_id1(), ctx);
+}
+
+static TString OptIdPrefixAsStr(const TRule_opt_id_prefix_or_type& node, TTranslation& ctx, const TString& defaultStr = {}) {
+ if (!node.HasBlock1()) {
+ return defaultStr;
+ }
+ return Id(node.GetBlock1().GetRule_an_id_or_type1(), ctx);
+}
+
+static void PureColumnListStr(const TRule_pure_column_list& node, TTranslation& ctx, TVector<TString>& outList) {
+ outList.push_back(Id(node.GetRule_an_id2(), ctx));
+ for (auto& block: node.GetBlock3()) {
+ outList.push_back(Id(block.GetRule_an_id2(), ctx));
+ }
+}
+
static bool NamedNodeImpl(const TRule_opt_bind_parameter& node, TString& name, bool& isOptional, TTranslation& ctx) {
// opt_bind_parameter: bind_parameter QUESTION?;
isOptional = false;
@@ -896,6 +897,10 @@ protected:
bool IsDistinctOptSet(const TRule_opt_set_quantifier& node) const;
bool IsDistinctOptSet(const TRule_opt_set_quantifier& node, TPosition& distinctPos) const;
+ bool AddObjectFeature(std::map<TString, TDeferredAtom>& result, const TRule_object_feature& feature);
+ bool BindParameterClause(const TRule_bind_parameter& node, TDeferredAtom& result);
+ bool ObjectFeatureValueClause(const TRule_object_feature_value & node, TDeferredAtom & result);
+ bool ParseObjectFeatures(std::map<TString, TDeferredAtom> & result, const TRule_object_features & features);
bool RoleNameClause(const TRule_role_name& node, TDeferredAtom& result, bool allowSystemRoles);
bool RoleParameters(const TRule_create_user_option& node, TRoleParameters& result) ;
private:
@@ -3143,13 +3148,13 @@ bool TSqlTranslation::SimpleTableRefCoreImpl(const TRule_simple_table_ref_core&
TDeferredAtom cluster = Context().Scoped->CurrCluster;
switch (node.Alt_case()) {
case TRule_simple_table_ref_core::AltCase::kAltSimpleTableRefCore1: {
- if (node.GetAlt_simple_table_ref_core1().GetBlock1().HasBlock1()) {
+ if (node.GetAlt_simple_table_ref_core1().GetRule_object_ref1().HasBlock1()) {
if (Mode == NSQLTranslation::ESqlMode::LIMITED_VIEW) {
Error() << "Cluster should not be used in limited view";
return false;
}
- if (!ClusterExpr(node.GetAlt_simple_table_ref_core1().GetBlock1().GetBlock1().GetRule_cluster_expr1(), false, service, cluster)) {
+ if (!ClusterExpr(node.GetAlt_simple_table_ref_core1().GetRule_object_ref1().GetBlock1().GetRule_cluster_expr1(), false, service, cluster)) {
return false;
}
}
@@ -3160,7 +3165,7 @@ bool TSqlTranslation::SimpleTableRefCoreImpl(const TRule_simple_table_ref_core&
}
result = TTableRef(Context().MakeName("table"), service, cluster, nullptr);
- auto tableOrAt = Id(node.GetAlt_simple_table_ref_core1().GetBlock1().GetRule_id_or_at2(), *this);
+ auto tableOrAt = Id(node.GetAlt_simple_table_ref_core1().GetRule_object_ref1().GetRule_id_or_at2(), *this);
auto tableAndView = TableKeyImpl(tableOrAt, "", *this);
result.Keys = BuildTableKey(Context().Pos(), result.Service, result.Cluster,
TDeferredAtom(Context().Pos(), tableAndView.first), tableAndView.second);
@@ -6407,22 +6412,17 @@ bool TSqlTranslation::IsDistinctOptSet(const TRule_opt_set_quantifier& node, TPo
bool TSqlTranslation::RoleNameClause(const TRule_role_name& node, TDeferredAtom& result, bool allowSystemRoles) {
// role_name: an_id_or_type | bind_parameter;
switch (node.Alt_case()) {
- case TRule_role_name::kAltRoleName1: {
+ case TRule_role_name::kAltRoleName1:
+ {
TString name = Id(node.GetAlt_role_name1().GetRule_an_id_or_type1(), *this);
result = TDeferredAtom(Ctx.Pos(), name);
break;
}
- case TRule_role_name::kAltRoleName2: {
- TString paramName;
- if (!NamedNodeImpl(node.GetAlt_role_name2().GetRule_bind_parameter1(), paramName, *this)) {
- return false;
- }
- auto named = GetNamedNode(paramName);
- if (!named) {
+ case TRule_role_name::kAltRoleName2:
+ {
+ if (!BindParameterClause(node.GetAlt_role_name2().GetRule_bind_parameter1(), result)) {
return false;
}
-
- result = MakeAtomFromExpression(Ctx, named);
break;
}
default:
@@ -8219,9 +8219,9 @@ TNodePtr TSqlIntoTable::Build(const TRule_into_table_stmt& node) {
bool isBinding = false;
switch (tableRefCore.Alt_case()) {
case TRule_simple_table_ref_core::AltCase::kAltSimpleTableRefCore1: {
- if (tableRefCore.GetAlt_simple_table_ref_core1().GetBlock1().HasBlock1()) {
- const auto& clusterExpr = tableRefCore.GetAlt_simple_table_ref_core1().GetBlock1().GetBlock1().GetRule_cluster_expr1();
- bool hasAt = tableRefCore.GetAlt_simple_table_ref_core1().GetBlock1().GetRule_id_or_at2().HasBlock1();
+ if (tableRefCore.GetAlt_simple_table_ref_core1().GetRule_object_ref1().HasBlock1()) {
+ const auto& clusterExpr = tableRefCore.GetAlt_simple_table_ref_core1().GetRule_object_ref1().GetBlock1().GetRule_cluster_expr1();
+ bool hasAt = tableRefCore.GetAlt_simple_table_ref_core1().GetRule_object_ref1().GetRule_id_or_at2().HasBlock1();
bool result = !hasAt ?
ClusterExprOrBinding(clusterExpr, service, cluster, isBinding) : ClusterExpr(clusterExpr, false, service, cluster);
if (!result) {
@@ -8234,7 +8234,7 @@ TNodePtr TSqlIntoTable::Build(const TRule_into_table_stmt& node) {
return nullptr;
}
- auto id = Id(tableRefCore.GetAlt_simple_table_ref_core1().GetBlock1().GetRule_id_or_at2(), *this);
+ auto id = Id(tableRefCore.GetAlt_simple_table_ref_core1().GetRule_object_ref1().GetRule_id_or_at2(), *this);
nameOrAt = std::make_pair(id.first, TDeferredAtom(Ctx.Pos(), id.second));
break;
}
@@ -9000,7 +9000,8 @@ bool TSqlQuery::Statement(TVector<TNodePtr>& blocks, const TRule_sql_stmt_core&
AddStatementToBlocks(blocks, stmt);
break;
}
- case TRule_sql_stmt_core::kAltSqlStmtCore25: {
+ case TRule_sql_stmt_core::kAltSqlStmtCore25:
+ {
// drop_role_stmt: DROP (USER|GROUP) (IF EXISTS)? role_name (COMMA role_name)* COMMA?;
Ctx.BodyPart();
auto& node = core.GetAlt_sql_stmt_core25().GetRule_drop_role_stmt1();
@@ -9035,6 +9036,76 @@ bool TSqlQuery::Statement(TVector<TNodePtr>& blocks, const TRule_sql_stmt_core&
AddStatementToBlocks(blocks, BuildDropRoles(pos, service, cluster, roles, isUser, force, Ctx.Scoped));
break;
}
+ case TRule_sql_stmt_core::kAltSqlStmtCore26:
+ {
+ // create_object_stmt: CREATE OBJECT name (TYPE type [WITH k=v,...]);
+ auto& node = core.GetAlt_sql_stmt_core26().GetRule_create_object_stmt1();
+ TObjectOperatorContext context(Ctx.Scoped);
+ if (node.GetRule_object_ref3().HasBlock1()) {
+ if (!ClusterExpr(node.GetRule_object_ref3().GetBlock1().GetRule_cluster_expr1(),
+ false, context.ServiceId, context.Cluster)) {
+ return false;
+ }
+ }
+
+ const TString& objectId = Id(node.GetRule_object_ref3().GetRule_id_or_at2(), *this).second;
+ const TString& typeId = Id(node.GetRule_object_type_ref6().GetRule_an_id_or_type1(), *this);
+ std::map<TString, TDeferredAtom> kv;
+ if (node.HasBlock7()) {
+ if (!ParseObjectFeatures(kv, node.GetBlock7().GetRule_create_object_features1().GetRule_object_features2())) {
+ return false;
+ }
+ }
+
+ AddStatementToBlocks(blocks, BuildCreateObjectOperation(Ctx.Pos(), objectId, typeId, std::move(kv), context));
+ break;
+ }
+ case TRule_sql_stmt_core::kAltSqlStmtCore27:
+ {
+ // create_object_stmt: ALTER OBJECT name (TYPE type [SET k=v,...]);
+ auto& node = core.GetAlt_sql_stmt_core27().GetRule_alter_object_stmt1();
+ TObjectOperatorContext context(Ctx.Scoped);
+ if (node.GetRule_object_ref3().HasBlock1()) {
+ if (!ClusterExpr(node.GetRule_object_ref3().GetBlock1().GetRule_cluster_expr1(),
+ false, context.ServiceId, context.Cluster)) {
+ return false;
+ }
+ }
+
+ const TString& objectId = Id(node.GetRule_object_ref3().GetRule_id_or_at2(), *this).second;
+ const TString& typeId = Id(node.GetRule_object_type_ref6().GetRule_an_id_or_type1(), *this);
+ std::map<TString, TDeferredAtom> kv;
+ if (!ParseObjectFeatures(kv, node.GetRule_alter_object_features7().GetRule_object_features2())) {
+ return false;
+ }
+
+ AddStatementToBlocks(blocks, BuildAlterObjectOperation(Ctx.Pos(), objectId, typeId, std::move(kv), context));
+ break;
+ }
+ case TRule_sql_stmt_core::kAltSqlStmtCore28:
+ {
+ // create_object_stmt: DROP OBJECT name (TYPE type [WITH k=v,...]);
+ auto& node = core.GetAlt_sql_stmt_core28().GetRule_drop_object_stmt1();
+ TObjectOperatorContext context(Ctx.Scoped);
+ if (node.GetRule_object_ref3().HasBlock1()) {
+ if (!ClusterExpr(node.GetRule_object_ref3().GetBlock1().GetRule_cluster_expr1(),
+ false, context.ServiceId, context.Cluster)) {
+ return false;
+ }
+ }
+
+ const TString& objectId = Id(node.GetRule_object_ref3().GetRule_id_or_at2(), *this).second;
+ const TString& typeId = Id(node.GetRule_object_type_ref6().GetRule_an_id_or_type1(), *this);
+ std::map<TString, TDeferredAtom> kv;
+ if (node.HasBlock7()) {
+ if (!ParseObjectFeatures(kv, node.GetBlock7().GetRule_drop_object_options1().GetRule_object_features2())) {
+ return false;
+ }
+ }
+
+ AddStatementToBlocks(blocks, BuildDropObjectOperation(Ctx.Pos(), objectId, typeId, std::move(kv), context));
+ break;
+ }
default:
Ctx.IncrementMonCounter("sql_errors", "UnknownStatement" + internalStatementName);
AltNotImplemented("sql_stmt_core", core);
@@ -10512,4 +10583,68 @@ NYql::TAstParseResult SqlToYql(const TString& query, const NSQLTranslation::TTra
return res;
}
+bool TSqlTranslation::BindParameterClause(const TRule_bind_parameter& node, TDeferredAtom& result) {
+ TString paramName;
+ if (!NamedNodeImpl(node, paramName, *this)) {
+ return false;
+ }
+ auto named = GetNamedNode(paramName);
+ if (!named) {
+ return false;
+ }
+
+ result = MakeAtomFromExpression(Ctx, named);
+ return true;
+}
+
+bool TSqlTranslation::ObjectFeatureValueClause(const TRule_object_feature_value& node, TDeferredAtom& result) {
+ // object_feature_value: an_id_or_type | bind_parameter;
+ switch (node.Alt_case()) {
+ case TRule_object_feature_value::kAltObjectFeatureValue1:
+ {
+ TString name = Id(node.GetAlt_object_feature_value1().GetRule_an_id_or_type1(), *this);
+ result = TDeferredAtom(Ctx.Pos(), name);
+ break;
+ }
+ case TRule_object_feature_value::kAltObjectFeatureValue2:
+ {
+ if (!BindParameterClause(node.GetAlt_object_feature_value2().GetRule_bind_parameter1(), result)) {
+ return false;
+ }
+ break;
+ }
+ default:
+ Y_FAIL("You should change implementation according to grammar changes");
+ }
+ return true;
+}
+
+bool TSqlTranslation::AddObjectFeature(std::map<TString, TDeferredAtom>& result, const TRule_object_feature& feature) {
+ if (feature.has_alt_object_feature1()) {
+ auto& kv = feature.GetAlt_object_feature1().GetRule_object_feature_kv1();
+ const TString& key = Id(kv.GetRule_an_id_or_type1(), *this);
+ auto& ruleValue = kv.GetRule_object_feature_value3();
+ TDeferredAtom value;
+ if (!ObjectFeatureValueClause(ruleValue, value)) {
+ return false;
+ }
+ result[key] = value;
+ } else if (feature.has_alt_object_feature2()) {
+ result[Id(feature.GetAlt_object_feature2().GetRule_object_feature_flag1().GetRule_an_id_or_type1(), *this)] = TDeferredAtom();
+ }
+ return true;
+}
+
+bool TSqlTranslation::ParseObjectFeatures(std::map<TString, TDeferredAtom>& result, const TRule_object_features& features) {
+ if (!AddObjectFeature(result, features.GetRule_object_feature1())) {
+ return false;
+ }
+ for (auto&& i : features.GetBlock2()) {
+ if (!AddObjectFeature(result, i.GetRule_object_feature2())) {
+ return false;
+ }
+ }
+ return true;
+}
+
} // namespace NSQLTranslationV1
diff --git a/ydb/library/yql/sql/v1/sql_ut.cpp b/ydb/library/yql/sql/v1/sql_ut.cpp
index 0d738034942..98a6b682b15 100644
--- a/ydb/library/yql/sql/v1/sql_ut.cpp
+++ b/ydb/library/yql/sql/v1/sql_ut.cpp
@@ -613,6 +613,127 @@ Y_UNIT_TEST_SUITE(SqlParsingOnly) {
UNIT_ASSERT(res.Root);
}
+ Y_UNIT_TEST(CreateObjectWithFeatures) {
+ NYql::TAstParseResult res = SqlToYql("USE plato; CREATE OBJECT secretId (TYPE SECRET WITH Key1=Value1, K2=V2);");
+ UNIT_ASSERT(res.Root);
+
+ TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) {
+ if (word == "Write") {
+ UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("'('\"K2\" '\"V2\") '('\"Key1\" '\"Value1\")"));
+ UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("createObject"));
+ }
+ };
+
+ TWordCountHive elementStat = { {TString("Write"), 0}, {TString("SECRET"), 0} };
+ VerifyProgram(res, elementStat, verifyLine);
+
+ UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]);
+ UNIT_ASSERT_VALUES_EQUAL(1, elementStat["SECRET"]);
+ }
+
+ Y_UNIT_TEST(CreateObjectWithFeaturesAndFlags) {
+ NYql::TAstParseResult res = SqlToYql("USE plato; CREATE OBJECT secretId (TYPE SECRET WITH Key1=Value1, K2=V2, RECURSE);");
+ UNIT_ASSERT(res.Root);
+
+ TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) {
+ if (word == "Write") {
+ UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("'('\"Key1\" '\"Value1\") '('\"RECURSE\")"));
+ UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("createObject"));
+ }
+ };
+
+ TWordCountHive elementStat = { {TString("Write"), 0}, {TString("SECRET"), 0} };
+ VerifyProgram(res, elementStat, verifyLine);
+
+ UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]);
+ UNIT_ASSERT_VALUES_EQUAL(1, elementStat["SECRET"]);
+ }
+
+ Y_UNIT_TEST(CreateObjectNoFeatures) {
+ NYql::TAstParseResult res = SqlToYql("USE plato; CREATE OBJECT secretId (TYPE SECRET);");
+ UNIT_ASSERT(res.Root);
+
+ TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) {
+ if (word == "Write") {
+ UNIT_ASSERT_VALUES_EQUAL(TString::npos, line.find("'features"));
+ UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("createObject"));
+ }
+ };
+
+ TWordCountHive elementStat = { {TString("Write"), 0}, {TString("SECRET"), 0} };
+ VerifyProgram(res, elementStat, verifyLine);
+
+ UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]);
+ UNIT_ASSERT_VALUES_EQUAL(1, elementStat["SECRET"]);
+ }
+
+ Y_UNIT_TEST(AlterObjectWithFeatures) {
+ NYql::TAstParseResult res = SqlToYql(
+ "USE plato;\n"
+ "declare $path as String;\n"
+ "ALTER OBJECT secretId (TYPE SECRET SET Key1=$path, K2=V2);"
+ );
+ UNIT_ASSERT(res.Root);
+
+ TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) {
+ if (word == "Write") {
+ UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("'features"));
+ UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("'\"Key1\" (EvaluateAtom \"$path\""));
+ UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("'\"K2\" '\"V2\""));
+
+ UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("alterObject"));
+ }
+ };
+
+ TWordCountHive elementStat = { {TString("Write"), 0}, {TString("SECRET"), 0} };
+ VerifyProgram(res, elementStat, verifyLine);
+
+ UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]);
+ UNIT_ASSERT_VALUES_EQUAL(1, elementStat["SECRET"]);
+ }
+
+ Y_UNIT_TEST(AlterObjectNoFeatures) {
+ NYql::TAstParseResult res = SqlToYql("USE plato; ALTER OBJECT secretId (TYPE SECRET);");
+ UNIT_ASSERT(!res.Root);
+ Cerr << Err2Str(res) << Endl;
+ }
+
+ Y_UNIT_TEST(DropObjectNoFeatures) {
+ NYql::TAstParseResult res = SqlToYql("USE plato; DROP OBJECT secretId (TYPE SECRET);");
+ UNIT_ASSERT(res.Root);
+
+ TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) {
+ if (word == "Write") {
+ UNIT_ASSERT_VALUES_EQUAL(TString::npos, line.find("'features"));
+ UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("dropObject"));
+ }
+ };
+
+ TWordCountHive elementStat = { {TString("Write"), 0}, {TString("SECRET"), 0} };
+ VerifyProgram(res, elementStat, verifyLine);
+
+ UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]);
+ UNIT_ASSERT_VALUES_EQUAL(1, elementStat["SECRET"]);
+ }
+
+ Y_UNIT_TEST(DropObjectWithFeatures) {
+ NYql::TAstParseResult res = SqlToYql("USE plato; DROP OBJECT secretId (TYPE SECRET WITH A, B, C);");
+ UNIT_ASSERT(res.Root);
+
+ TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) {
+ if (word == "Write") {
+ UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("'features"));
+ UNIT_ASSERT_VALUES_UNEQUAL(TString::npos, line.find("dropObject"));
+ }
+ };
+
+ TWordCountHive elementStat = { {TString("Write"), 0}, {TString("SECRET"), 0} };
+ VerifyProgram(res, elementStat, verifyLine);
+
+ UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write"]);
+ UNIT_ASSERT_VALUES_EQUAL(1, elementStat["SECRET"]);
+ }
+
Y_UNIT_TEST(PrimaryKeyParseCorrect) {
NYql::TAstParseResult res = SqlToYql("USE plato; CREATE TABLE tableName (Key Uint32, Subkey Int64, Value String, PRIMARY KEY (Key, Subkey));");
UNIT_ASSERT(res.Root);