diff --git a/ydb/core/kqp/session_actor/kqp_query_state.h b/ydb/core/kqp/session_actor/kqp_query_state.h index dbb83613f42c..ee6ca15b7796 100644 --- a/ydb/core/kqp/session_actor/kqp_query_state.h +++ b/ydb/core/kqp/session_actor/kqp_query_state.h @@ -432,14 +432,14 @@ class TKqpQueryState : public TNonCopyable { return true; } - TKqpPhyTxHolder::TConstPtr GetCurrentPhyTx(bool isBatchQuery = false) { + TKqpPhyTxHolder::TConstPtr GetCurrentPhyTx(bool isBatchQuery, NMiniKQL::TTypeEnvironment& txTypeEnv) { const auto& phyQuery = PreparedQuery->GetPhysicalQuery(); auto tx = PreparedQuery->GetPhyTxOrEmpty(CurrentTx); if (TxCtx->CanDeferEffects() && !isBatchQuery) { // Olap sinks require separate tnx with commit. while (tx && tx->GetHasEffects() && !TxCtx->HasOlapTable) { - QueryData->CreateKqpValueMap(tx); + QueryData->PrepareParameters(tx, PreparedQuery, txTypeEnv); bool success = TxCtx->AddDeferredEffect(tx, QueryData); YQL_ENSURE(success); if (CurrentTx + 1 < phyQuery.TransactionsSize()) { diff --git a/ydb/core/kqp/session_actor/kqp_session_actor.cpp b/ydb/core/kqp/session_actor/kqp_session_actor.cpp index 524858c6637b..18348af42231 100644 --- a/ydb/core/kqp/session_actor/kqp_session_actor.cpp +++ b/ydb/core/kqp/session_actor/kqp_session_actor.cpp @@ -1169,7 +1169,7 @@ class TKqpSessionActor : public TActorBootstrapped { TKqpPhyTxHolder::TConstPtr tx; try { - tx = QueryState->GetCurrentPhyTx(isBatchQuery); + tx = QueryState->GetCurrentPhyTx(isBatchQuery, QueryState->TxCtx->TxAlloc->TypeEnv); } catch (const yexception& ex) { ythrow TRequestFail(Ydb::StatusIds::BAD_REQUEST) << ex.what(); } diff --git a/ydb/core/kqp/ut/query/kqp_params_ut.cpp b/ydb/core/kqp/ut/query/kqp_params_ut.cpp index 32e9b715d223..8542f017abad 100644 --- a/ydb/core/kqp/ut/query/kqp_params_ut.cpp +++ b/ydb/core/kqp/ut/query/kqp_params_ut.cpp @@ -78,6 +78,45 @@ Y_UNIT_TEST_SUITE(KqpParams) { UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::BAD_REQUEST, result.GetIssues().ToString()); } + Y_UNIT_TEST_TWIN(MissingOptionalParameter, UseSink) { + NKikimrConfig::TAppConfig appConfig; + appConfig.MutableTableServiceConfig()->SetEnableOltpSink(UseSink); + auto settings = TKikimrSettings() + .SetAppConfig(appConfig) + .SetWithSampleTables(true); + TKikimrRunner kikimr(settings); + auto db = kikimr.GetTableClient(); + auto session = db.CreateSession().GetValueSync().GetSession(); + + { + auto params = db.GetParamsBuilder() + .AddParam("$_amount") + .Uint64(42) + .Build() + .Build(); + auto result = session.ExecuteDataQuery(Q_(R"( + --!syntax_v1 + + DECLARE $_amount AS Uint64; + DECLARE $_comment AS String?; + + UPSERT INTO `/Root/Test` (Group, Name, Amount, Comment) VALUES + (1u, "test", $_amount, $_comment); + )"), TTxControl::BeginTx(TTxSettings::SerializableRW()).CommitTx(), params).ExtractValueSync(); + + UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString()); + } + + { + auto result = session.ExecuteDataQuery(Q_(R"( + SELECT * FROM `/Root/Test` WHERE Group = 1 AND Name = "test"; + )"), TTxControl::BeginTx(TTxSettings::SerializableRW()).CommitTx()).ExtractValueSync(); + UNIT_ASSERT(result.IsSuccess()); + + CompareYson(R"([[[42u];#;[1u];["test"]]])", FormatResultSetYson(result.GetResultSet(0))); + } + } + Y_UNIT_TEST(BadParameterType) { TKikimrRunner kikimr; auto db = kikimr.GetTableClient();