aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNikolay Shumkov <153636981+shnikd@users.noreply.github.com>2024-02-08 15:11:09 +0300
committerGitHub <noreply@github.com>2024-02-08 15:11:09 +0300
commit3ce09536fbee061fa6594e6d5137b8bb779e946c (patch)
treec1a439ac6784b9672e023c94bba196be96cb6e17
parent8adf99d6be768fcbea7566e7d3a2bd4226139c04 (diff)
downloadydb-3ce09536fbee061fa6594e6d5137b8bb779e946c.tar.gz
Support temp tables in yql (#1589)
* Initial commit * Fixes
-rw-r--r--ydb/core/kqp/ut/service/kqp_qs_queries_ut.cpp131
-rw-r--r--ydb/library/yql/sql/v1/SQLv1.g.in2
-rw-r--r--ydb/library/yql/sql/v1/format/sql_format_ut.cpp4
-rw-r--r--ydb/library/yql/sql/v1/node.h1
-rw-r--r--ydb/library/yql/sql/v1/query.cpp4
-rw-r--r--ydb/library/yql/sql/v1/sql_query.cpp6
-rw-r--r--ydb/library/yql/sql/v1/sql_ut.cpp34
7 files changed, 179 insertions, 3 deletions
diff --git a/ydb/core/kqp/ut/service/kqp_qs_queries_ut.cpp b/ydb/core/kqp/ut/service/kqp_qs_queries_ut.cpp
index 32181f5da4..079a3d85a9 100644
--- a/ydb/core/kqp/ut/service/kqp_qs_queries_ut.cpp
+++ b/ydb/core/kqp/ut/service/kqp_qs_queries_ut.cpp
@@ -860,6 +860,137 @@ Y_UNIT_TEST_SUITE(KqpQueryService) {
UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString());
}
+ Y_UNIT_TEST(CreateTempTable) {
+ NKikimrConfig::TAppConfig appConfig;
+ appConfig.MutableTableServiceConfig()->SetEnablePreparedDdl(true);
+ auto setting = NKikimrKqp::TKqpSetting();
+ auto serverSettings = TKikimrSettings()
+ .SetAppConfig(appConfig)
+ .SetKqpSettings({setting});
+ TKikimrRunner kikimr(
+ serverSettings.SetWithSampleTables(false).SetEnableTempTables(true));
+ auto clientConfig = NGRpcProxy::TGRpcClientConfig(kikimr.GetEndpoint());
+ auto client = kikimr.GetQueryClient();
+ {
+ auto session = client.GetSession().GetValueSync().GetSession();
+ auto id = session.GetId();
+
+ const auto queryCreate = Q_(R"(
+ --!syntax_v1
+ CREATE TEMP TABLE Temp (
+ Key Uint64 NOT NULL,
+ Value String,
+ PRIMARY KEY (Key)
+ );)");
+
+ auto resultCreate = session.ExecuteQuery(queryCreate, NYdb::NQuery::TTxControl::NoTx()).ExtractValueSync();
+ UNIT_ASSERT_C(resultCreate.IsSuccess(), resultCreate.GetIssues().ToString());
+
+ const auto querySelect = Q_(R"(
+ --!syntax_v1
+ SELECT * FROM Temp;
+ )");
+
+ auto resultSelect = session.ExecuteQuery(
+ querySelect, NYdb::NQuery::TTxControl::BeginTx().CommitTx()).ExtractValueSync();
+ UNIT_ASSERT_C(resultSelect.IsSuccess(), resultSelect.GetIssues().ToString());
+
+ bool allDoneOk = true;
+ NTestHelpers::CheckDelete(clientConfig, id, Ydb::StatusIds::SUCCESS, allDoneOk);
+
+ UNIT_ASSERT(allDoneOk);
+ }
+
+ {
+ const auto querySelect = Q_(R"(
+ --!syntax_v1
+ SELECT * FROM Temp;
+ )");
+
+ auto resultSelect = client.ExecuteQuery(
+ querySelect, NYdb::NQuery::TTxControl::BeginTx().CommitTx()).ExtractValueSync();
+ UNIT_ASSERT(!resultSelect.IsSuccess());
+ }
+ }
+
+ Y_UNIT_TEST(TempTablesDrop) {
+ NKikimrConfig::TAppConfig appConfig;
+ appConfig.MutableTableServiceConfig()->SetEnablePreparedDdl(true);
+ auto setting = NKikimrKqp::TKqpSetting();
+ auto serverSettings = TKikimrSettings()
+ .SetAppConfig(appConfig)
+ .SetKqpSettings({setting});
+ TKikimrRunner kikimr(
+ serverSettings.SetWithSampleTables(false).SetEnableTempTables(true));
+ auto clientConfig = NGRpcProxy::TGRpcClientConfig(kikimr.GetEndpoint());
+ auto client = kikimr.GetQueryClient();
+
+ auto session = client.GetSession().GetValueSync().GetSession();
+ auto id = session.GetId();
+
+ const auto queryCreate = Q_(R"(
+ --!syntax_v1
+ CREATE TEMPORARY TABLE Temp (
+ Key Uint64 NOT NULL,
+ Value String,
+ PRIMARY KEY (Key)
+ );)");
+
+ auto resultCreate = session.ExecuteQuery(queryCreate, NYdb::NQuery::TTxControl::NoTx()).ExtractValueSync();
+ UNIT_ASSERT_C(resultCreate.IsSuccess(), resultCreate.GetIssues().ToString());
+
+ {
+ const auto querySelect = Q_(R"(
+ --!syntax_v1
+ SELECT * FROM Temp;
+ )");
+
+ auto resultSelect = session.ExecuteQuery(
+ querySelect, NYdb::NQuery::TTxControl::BeginTx().CommitTx()).ExtractValueSync();
+ UNIT_ASSERT_C(resultSelect.IsSuccess(), resultSelect.GetIssues().ToString());
+ }
+
+ const auto queryDrop = Q_(R"(
+ --!syntax_v1
+ DROP TABLE Temp;
+ )");
+
+ auto resultDrop = session.ExecuteQuery(
+ queryDrop, NYdb::NQuery::TTxControl::NoTx()).ExtractValueSync();
+ UNIT_ASSERT_C(resultDrop.IsSuccess(), resultDrop.GetIssues().ToString());
+
+ {
+ const auto querySelect = Q_(R"(
+ --!syntax_v1
+ SELECT * FROM Temp;
+ )");
+
+ auto resultSelect = session.ExecuteQuery(
+ querySelect, NYdb::NQuery::TTxControl::BeginTx().CommitTx()).ExtractValueSync();
+ UNIT_ASSERT(!resultSelect.IsSuccess());
+ }
+
+ bool allDoneOk = true;
+ NTestHelpers::CheckDelete(clientConfig, id, Ydb::StatusIds::SUCCESS, allDoneOk);
+
+ UNIT_ASSERT(allDoneOk);
+
+ auto sessionAnother = client.GetSession().GetValueSync().GetSession();
+ auto idAnother = sessionAnother.GetId();
+ UNIT_ASSERT(id != idAnother);
+
+ {
+ const auto querySelect = Q_(R"(
+ --!syntax_v1
+ SELECT * FROM Temp;
+ )");
+
+ auto resultSelect = sessionAnother.ExecuteQuery(
+ querySelect, NYdb::NQuery::TTxControl::BeginTx().CommitTx()).ExtractValueSync();
+ UNIT_ASSERT(!resultSelect.IsSuccess());
+ }
+ }
+
Y_UNIT_TEST(DdlGroup) {
NKikimrConfig::TAppConfig appConfig;
appConfig.MutableTableServiceConfig()->SetEnablePreparedDdl(true);
diff --git a/ydb/library/yql/sql/v1/SQLv1.g.in b/ydb/library/yql/sql/v1/SQLv1.g.in
index 642c0a0466..35862dc972 100644
--- a/ydb/library/yql/sql/v1/SQLv1.g.in
+++ b/ydb/library/yql/sql/v1/SQLv1.g.in
@@ -623,7 +623,7 @@ object_features: object_feature | LPAREN object_feature (COMMA object_feature)*
object_type_ref: an_id_or_type;
-create_table_stmt: CREATE (OR REPLACE)? (TABLE | TABLESTORE | EXTERNAL TABLE) (IF NOT EXISTS)? simple_table_ref LPAREN create_table_entry (COMMA create_table_entry)* COMMA? RPAREN
+create_table_stmt: CREATE (OR REPLACE)? (TABLE | TABLESTORE | EXTERNAL TABLE | TEMP TABLE | TEMPORARY TABLE) (IF NOT EXISTS)? simple_table_ref LPAREN create_table_entry (COMMA create_table_entry)* COMMA? RPAREN
table_inherits?
table_partition_by?
with_table_settings?
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 7d211e3262..fe757781c3 100644
--- a/ydb/library/yql/sql/v1/format/sql_format_ut.cpp
+++ b/ydb/library/yql/sql/v1/format/sql_format_ut.cpp
@@ -307,7 +307,9 @@ Y_UNIT_TEST_SUITE(CheckSqlFormatter) {
")\n"
"PARTITION BY HASH (a, b, hash)\n"
"WITH (tiering = 'some');\n"},
- {"create table if not exists user(user int32)", "CREATE TABLE IF NOT EXISTS user (\n\tuser int32\n);\n"}
+ {"create table if not exists user(user int32)", "CREATE TABLE IF NOT EXISTS user (\n\tuser int32\n);\n"},
+ {"create temp table user(user int32)", "CREATE TEMP TABLE user (\n\tuser int32\n);\n"},
+ {"create temporary table user(user int32)", "CREATE TEMPORARY TABLE user (\n\tuser int32\n);\n"}
};
TSetup setup;
diff --git a/ydb/library/yql/sql/v1/node.h b/ydb/library/yql/sql/v1/node.h
index a7e359f695..812665ccef 100644
--- a/ydb/library/yql/sql/v1/node.h
+++ b/ydb/library/yql/sql/v1/node.h
@@ -1046,6 +1046,7 @@ namespace NSQLTranslationV1 {
TVector<TChangefeedDescription> Changefeeds;
TTableSettings TableSettings;
ETableType TableType = ETableType::Table;
+ bool Temporary = false;
};
struct TAlterTableParameters {
diff --git a/ydb/library/yql/sql/v1/query.cpp b/ydb/library/yql/sql/v1/query.cpp
index aaa1a7ddd4..d6de36f795 100644
--- a/ydb/library/yql/sql/v1/query.cpp
+++ b/ydb/library/yql/sql/v1/query.cpp
@@ -1140,6 +1140,10 @@ public:
break;
}
+ if (Params.Temporary) {
+ opts = L(opts, Q(Y(Q("temporary"))));
+ }
+
Add("block", Q(Y(
Y("let", "sink", Y("DataSink", BuildQuotedAtom(Pos, Table.Service), Scoped->WrapCluster(Table.Cluster, ctx))),
Y("let", "world", Y(TString(WriteName), "world", "sink", keys, Y("Void"), Q(opts))),
diff --git a/ydb/library/yql/sql/v1/sql_query.cpp b/ydb/library/yql/sql/v1/sql_query.cpp
index e33b2282e0..8c9dca1c0d 100644
--- a/ydb/library/yql/sql/v1/sql_query.cpp
+++ b/ydb/library/yql/sql/v1/sql_query.cpp
@@ -171,10 +171,14 @@ bool TSqlQuery::Statement(TVector<TNodePtr>& blocks, const TRule_sql_stmt_core&
const auto& block = rule.GetBlock3();
ETableType tableType = ETableType::Table;
+ bool temporary = false;
if (block.HasAlt2() && block.GetAlt2().GetToken1().GetId() == SQLv1LexerTokens::TOKEN_TABLESTORE) {
tableType = ETableType::TableStore;
} else if (block.HasAlt3() && block.GetAlt3().GetToken1().GetId() == SQLv1LexerTokens::TOKEN_EXTERNAL) {
tableType = ETableType::ExternalTable;
+ } else if (block.HasAlt4() && block.GetAlt4().GetToken1().GetId() == SQLv1LexerTokens::TOKEN_TEMP ||
+ block.HasAlt5() && block.GetAlt5().GetToken1().GetId() == SQLv1LexerTokens::TOKEN_TEMPORARY) {
+ temporary = true;
}
bool existingOk = false;
@@ -198,7 +202,7 @@ bool TSqlQuery::Statement(TVector<TNodePtr>& blocks, const TRule_sql_stmt_core&
return false;
}
- TCreateTableParameters params{.TableType=tableType};
+ TCreateTableParameters params{.TableType=tableType, .Temporary=temporary};
if (!CreateTableEntry(rule.GetRule_create_table_entry7(), params)) {
return false;
}
diff --git a/ydb/library/yql/sql/v1/sql_ut.cpp b/ydb/library/yql/sql/v1/sql_ut.cpp
index b7e265d520..d640235bf2 100644
--- a/ydb/library/yql/sql/v1/sql_ut.cpp
+++ b/ydb/library/yql/sql/v1/sql_ut.cpp
@@ -1007,6 +1007,40 @@ Y_UNIT_TEST_SUITE(SqlParsingOnly) {
UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write!"]);
}
+ Y_UNIT_TEST(CreateTempTable) {
+ NYql::TAstParseResult res = SqlToYql("USE plato; CREATE TEMP TABLE t (a int32, primary key(a));");
+ UNIT_ASSERT(res.Root);
+
+ TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) {
+ if (word == "Write!") {
+ UNIT_ASSERT_VALUES_UNEQUAL_C(TString::npos,
+ line.find(R"__((Write! world sink (Key '('tablescheme (String '"t"))) (Void) '('('mode 'create) '('columns '('('"a" (AsOptionalType (DataType 'Int32)) '('columnConstrains '()) '()))) '('primarykey '('"a")) '('temporary))))__"), line);
+ }
+ };
+
+ TWordCountHive elementStat = {{TString("Write!"), 0}};
+ VerifyProgram(res, elementStat, verifyLine);
+
+ UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write!"]);
+ }
+
+ Y_UNIT_TEST(CreateTemporaryTable) {
+ NYql::TAstParseResult res = SqlToYql("USE plato; CREATE TEMPORARY TABLE t (a int32, primary key(a));");
+ UNIT_ASSERT(res.Root);
+
+ TVerifyLineFunc verifyLine = [](const TString& word, const TString& line) {
+ if (word == "Write!") {
+ UNIT_ASSERT_VALUES_UNEQUAL_C(TString::npos,
+ line.find(R"__((Write! world sink (Key '('tablescheme (String '"t"))) (Void) '('('mode 'create) '('columns '('('"a" (AsOptionalType (DataType 'Int32)) '('columnConstrains '()) '()))) '('primarykey '('"a")) '('temporary))))__"), line);
+ }
+ };
+
+ TWordCountHive elementStat = {{TString("Write!"), 0}};
+ VerifyProgram(res, elementStat, verifyLine);
+
+ UNIT_ASSERT_VALUES_EQUAL(1, elementStat["Write!"]);
+ }
+
Y_UNIT_TEST(CreateTableDuplicatedPkColumnsFail) {
NYql::TAstParseResult res = SqlToYql("USE plato; CREATE TABLE t (a int32 not null, primary key(a, a));");
UNIT_ASSERT(!res.Root);