Browse Source

KIKIMR-19006: pg insert without target columns

qrort 1 year ago
parent
commit
fb5bbde000

+ 1 - 0
ydb/core/kqp/provider/CMakeLists.darwin-x86_64.txt

@@ -64,6 +64,7 @@ target_sources(core-kqp-provider PRIVATE
   ${CMAKE_SOURCE_DIR}/ydb/core/kqp/provider/yql_kikimr_results.cpp
   ${CMAKE_SOURCE_DIR}/ydb/core/kqp/provider/yql_kikimr_settings.cpp
   ${CMAKE_SOURCE_DIR}/ydb/core/kqp/provider/yql_kikimr_type_ann.cpp
+  ${CMAKE_SOURCE_DIR}/ydb/core/kqp/provider/yql_kikimr_type_ann_pg.cpp
   ${CMAKE_BINARY_DIR}/ydb/core/kqp/provider/yql_kikimr_expr_nodes.gen.h
   ${CMAKE_BINARY_DIR}/ydb/core/kqp/provider/yql_kikimr_expr_nodes.decl.inl.h
   ${CMAKE_BINARY_DIR}/ydb/core/kqp/provider/yql_kikimr_expr_nodes.defs.inl.h

+ 1 - 0
ydb/core/kqp/provider/CMakeLists.linux-aarch64.txt

@@ -65,6 +65,7 @@ target_sources(core-kqp-provider PRIVATE
   ${CMAKE_SOURCE_DIR}/ydb/core/kqp/provider/yql_kikimr_results.cpp
   ${CMAKE_SOURCE_DIR}/ydb/core/kqp/provider/yql_kikimr_settings.cpp
   ${CMAKE_SOURCE_DIR}/ydb/core/kqp/provider/yql_kikimr_type_ann.cpp
+  ${CMAKE_SOURCE_DIR}/ydb/core/kqp/provider/yql_kikimr_type_ann_pg.cpp
   ${CMAKE_BINARY_DIR}/ydb/core/kqp/provider/yql_kikimr_expr_nodes.gen.h
   ${CMAKE_BINARY_DIR}/ydb/core/kqp/provider/yql_kikimr_expr_nodes.decl.inl.h
   ${CMAKE_BINARY_DIR}/ydb/core/kqp/provider/yql_kikimr_expr_nodes.defs.inl.h

+ 1 - 0
ydb/core/kqp/provider/CMakeLists.linux-x86_64.txt

@@ -65,6 +65,7 @@ target_sources(core-kqp-provider PRIVATE
   ${CMAKE_SOURCE_DIR}/ydb/core/kqp/provider/yql_kikimr_results.cpp
   ${CMAKE_SOURCE_DIR}/ydb/core/kqp/provider/yql_kikimr_settings.cpp
   ${CMAKE_SOURCE_DIR}/ydb/core/kqp/provider/yql_kikimr_type_ann.cpp
+  ${CMAKE_SOURCE_DIR}/ydb/core/kqp/provider/yql_kikimr_type_ann_pg.cpp
   ${CMAKE_BINARY_DIR}/ydb/core/kqp/provider/yql_kikimr_expr_nodes.gen.h
   ${CMAKE_BINARY_DIR}/ydb/core/kqp/provider/yql_kikimr_expr_nodes.decl.inl.h
   ${CMAKE_BINARY_DIR}/ydb/core/kqp/provider/yql_kikimr_expr_nodes.defs.inl.h

+ 1 - 0
ydb/core/kqp/provider/CMakeLists.windows-x86_64.txt

@@ -64,6 +64,7 @@ target_sources(core-kqp-provider PRIVATE
   ${CMAKE_SOURCE_DIR}/ydb/core/kqp/provider/yql_kikimr_results.cpp
   ${CMAKE_SOURCE_DIR}/ydb/core/kqp/provider/yql_kikimr_settings.cpp
   ${CMAKE_SOURCE_DIR}/ydb/core/kqp/provider/yql_kikimr_type_ann.cpp
+  ${CMAKE_SOURCE_DIR}/ydb/core/kqp/provider/yql_kikimr_type_ann_pg.cpp
   ${CMAKE_BINARY_DIR}/ydb/core/kqp/provider/yql_kikimr_expr_nodes.gen.h
   ${CMAKE_BINARY_DIR}/ydb/core/kqp/provider/yql_kikimr_expr_nodes.decl.inl.h
   ${CMAKE_BINARY_DIR}/ydb/core/kqp/provider/yql_kikimr_expr_nodes.defs.inl.h

+ 2 - 0
ydb/core/kqp/provider/ya.make

@@ -18,6 +18,8 @@ SRCS(
     yql_kikimr_settings.cpp
     yql_kikimr_settings.h
     yql_kikimr_type_ann.cpp
+    yql_kikimr_type_ann_pg.h
+    yql_kikimr_type_ann_pg.cpp
 )
 
 PEERDIR(

+ 11 - 45
ydb/core/kqp/provider/yql_kikimr_type_ann.cpp

@@ -1,4 +1,5 @@
 #include "yql_kikimr_provider_impl.h"
+#include "yql_kikimr_type_ann_pg.h"
 
 #include <ydb/core/docapi/traits.h>
 
@@ -288,48 +289,6 @@ namespace {
         }
         return true;
     }
-
-    bool ValidatePgUpdateKeys(const TKiWriteTable& node, const TKikimrTableDescription* table, TExprContext& ctx) {
-        bool ok = true;
-        auto updateKeyCheck = [&](const TStringBuf& colName) {
-            if (table->GetKeyColumnIndex(TString(colName))) {
-                ctx.AddError(TIssue(ctx.GetPosition(node.Pos()), TStringBuilder()
-                    << "Cannot update primary key column: " << colName));
-                ok = false;
-            }
-        };
-        auto pgSelect = node.Input().Cast<TCoPgSelect>();
-        for (const auto& option : pgSelect.SelectOptions()) {
-            if (option.Name() == "set_items") {
-                auto pgSetItems = option.Value().Cast<TExprList>();
-                for (const auto& setItem : pgSetItems) {
-                    auto setItemNode = setItem.Cast<TCoPgSetItem>();
-                    for (const auto& setItemOption : setItemNode.SetItemOptions()) {
-                        if (setItemOption.Name() == "result") {
-                            auto resultList = setItemOption.Value().Cast<TExprList>();
-                            bool skipStar = true;
-                            for (const auto& pgResultItem : resultList) {
-                                if (skipStar) {
-                                    skipStar = false;
-                                    continue;
-                                }
-                                auto pgResultNode = pgResultItem.Cast<TCoPgResultItem>();
-                                if (pgResultNode.ExpandedColumns().Maybe<TExprList>()) {
-                                    auto list = pgResultNode.ExpandedColumns().Cast<TExprList>();
-                                    for (const auto& item : list) {
-                                        updateKeyCheck(item.Cast<TCoAtom>().Value());
-                                    }
-                                } else {
-                                    updateKeyCheck(pgResultNode.ExpandedColumns().Cast<TCoAtom>().Value());
-                                }
-                            }
-                        }
-                    }
-                }
-            }
-        }
-        return ok;
-    }
 }
 
 class TKiSinkTypeAnnotationTransformer : public TKiSinkVisitorTransformer
@@ -415,6 +374,15 @@ private:
             }
         }
 
+        auto op = GetTableOp(node);
+        if (NPgTypeAnn::NeedsValuesRename(node, op)) {
+            if (!NPgTypeAnn::RewriteValuesColumnNames(node, table, ctx, Types)) {
+                return TStatus::Error;
+            }
+            rowType = table->SchemeNode;
+            return TStatus::Repeat;
+        }
+
         if (!rowType) {
             ctx.AddError(TIssue(pos, TStringBuilder()
                 << "Expected list or stream of structs as input, but got: " << *inputType));
@@ -437,7 +405,6 @@ private:
             autoincrementColumns.emplace(keyColumnName);
         }
 
-        auto op = GetTableOp(node);
         if (op == TYdbOperation::InsertAbort || op == TYdbOperation::InsertRevert ||
             op == TYdbOperation::Upsert || op == TYdbOperation::Replace) {
             for (const auto& [name, meta] : table->Metadata->Columns) {
@@ -465,8 +432,7 @@ private:
             }
         } else if (op == TYdbOperation::UpdateOn) {
             if (TCoPgSelect::Match(node.Input().Ptr().Get())) {
-                auto ok = ValidatePgUpdateKeys(node, table, ctx);
-                if (!ok) {
+                if (!NPgTypeAnn::ValidatePgUpdateKeys(node, table, ctx)) {
                     return TStatus::Error;
                 }
             }

+ 156 - 0
ydb/core/kqp/provider/yql_kikimr_type_ann_pg.cpp

@@ -0,0 +1,156 @@
+#include "yql_kikimr_type_ann_pg.h"
+
+#include <util/string/join.h>
+
+namespace NYql {
+namespace NPgTypeAnn {
+    
+using namespace NNodes;
+
+namespace {
+    bool MatchesSetItemOption(const TExprBase& setItemOption, TStringBuf name) {
+        if (setItemOption.Ref().IsList() && setItemOption.Ref().ChildrenSize() > 0) {
+            if (setItemOption.Ref().ChildPtr(0)->Content() == name) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    TExprNode::TPtr GetSetItemOptionValue(const TExprBase& setItemOption) {
+        if (setItemOption.Ref().IsList() && setItemOption.Ref().ChildrenSize() > 1) {
+            return setItemOption.Ref().ChildPtr(1);
+        }
+        return nullptr;
+    }
+
+    bool TransformPgSetItemOption(
+        const TKiWriteTable& node, 
+        TStringBuf optionName, 
+        std::function<void(const TExprBase&)> lambda
+    ) {
+        bool applied = false;
+        if (auto pgSelect = node.Input().Maybe<TCoPgSelect>()) {    
+            for (const auto& option : pgSelect.Cast().SelectOptions()) {
+                if (option.Name() == "set_items") {
+                    auto pgSetItems = option.Value().Cast<TExprList>();
+                    for (const auto& setItem : pgSetItems) {
+                        auto setItemNode = setItem.Cast<TCoPgSetItem>();
+                        for (const auto& setItemOption : setItemNode.SetItemOptions()) {
+                            if (MatchesSetItemOption(setItemOption, optionName)) {
+                                applied = true;
+                                lambda(setItemOption);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        return applied;
+    }
+
+    TExprNode::TPtr GetSetItemOption(const TKiWriteTable& node, TStringBuf optionName) {
+        TExprNode::TPtr nodePtr = nullptr;
+        TransformPgSetItemOption(node, optionName, [&nodePtr](const TExprBase& option) {
+            nodePtr = option.Ptr();
+        });
+        return nodePtr;
+    }
+} //namespace
+
+bool NeedsValuesRename(const NNodes::TKiWriteTable &node, TYdbOperation op) {
+    auto fill = GetSetItemOption(node, "fill_target_columns");
+
+    return op == TYdbOperation::InsertAbort
+        && fill
+        && !GetSetItemOptionValue(TExprBase(fill));
+}
+
+bool RewriteValuesColumnNames(const TKiWriteTable& node, const TKikimrTableDescription* table, TExprContext& ctx, TTypeAnnotationContext& types) {
+    bool ok = true;
+    TransformPgSetItemOption(node, "values", [&ok, &node, &table, &ctx, &types](const TExprBase &setItemOption) {
+        auto values = GetSetItemOptionValue(setItemOption);
+        if (values->ChildrenSize() != table->Metadata->Columns.size()) {
+            ctx.AddError(TIssue(ctx.GetPosition(node.Pos()), TStringBuilder() << Sprintf(
+                "VALUES have %zu columns, INSERT INTO expects: %zu", 
+                values->ChildrenSize(), 
+                table->Metadata->Columns.size()
+            )));
+            ok = false;
+            return;
+        }
+        TExprNode::TListType columns;
+        THashMap<TString, TString> valueColumnName;
+        columns.reserve(values->ChildrenSize()); 
+        for (ui32 index = 0; index < values->ChildrenSize(); ++index) {
+            valueColumnName[values->Child(index)->Content()] = table->Metadata->ColumnOrder[index];
+            columns.push_back(Build<TCoAtom>(ctx, node.Pos())
+                .Value(table->Metadata->ColumnOrder[index])
+            .Done().Ptr());
+            columns.back()->SetTypeAnn(values->Child(index)->GetTypeAnn());
+        }
+        values->ChangeChildrenInplace(std::move(columns));
+        auto input = node.Ptr()->ChildRef(TKiWriteTable::idx_Input);
+        const TTypeAnnotationNode* inputType;
+        switch (input->GetTypeAnn()->GetKind()) {
+            case ETypeAnnotationKind::List:
+                inputType = input->GetTypeAnn()->Cast<TListExprType>()->GetItemType();
+                break;
+            default:
+                inputType = input->GetTypeAnn();
+                break;
+        }
+        Y_ENSURE(inputType->GetKind() == ETypeAnnotationKind::Struct);
+        TVector<const TItemExprType*> rowTypeItems;
+        for (const auto& item : inputType->Cast<TStructExprType>()->GetItems()) {
+            rowTypeItems.emplace_back(ctx.MakeType<TItemExprType>(valueColumnName[item->GetName()], item->GetItemType()));
+        }  
+        const TStructExprType* rowStructType = ctx.MakeType<TStructExprType>(rowTypeItems);
+        if (input->GetTypeAnn()->GetKind() == ETypeAnnotationKind::List) {
+            input->SetTypeAnn(ctx.MakeType<TListExprType>(rowStructType));
+        } else {
+            input->SetTypeAnn(rowStructType);
+        }
+        types.SetColumnOrder(*input, table->Metadata->ColumnOrder, ctx, /*overwrite=*/true);  
+    });
+    if (ok) {
+        auto fill = GetSetItemOption(node, "fill_target_columns");
+        fill->ChangeChildrenInplace({
+            fill->Child(0),
+            Build<TCoAtom>(ctx, node.Pos())
+                .Value("done")
+            .Done().Ptr()
+        });
+        fill->ChildPtr(1)->SetTypeAnn(ctx.MakeType<TUnitExprType>());
+    }
+    return ok;
+}
+
+bool ValidatePgUpdateKeys(const TKiWriteTable& node, const TKikimrTableDescription* table, TExprContext& ctx) {
+    bool ok = true;
+    auto updateKeyCheck = [&](const TStringBuf& colName) {
+        if (table->GetKeyColumnIndex(TString(colName))) {
+            ctx.AddError(TIssue(ctx.GetPosition(node.Pos()), TStringBuilder()
+                << "Cannot update primary key column: " << colName));
+            ok = false;
+        }
+    };
+    TransformPgSetItemOption(node, "result", [&updateKeyCheck](const TExprBase& setItemOptionNode) {
+        auto setItemOption = setItemOptionNode.Cast<TCoNameValueTuple>();
+        auto resultList = setItemOption.Value().Cast<TExprList>();
+        for (size_t id = 1; id < resultList.Size(); id++) {
+            auto pgResultNode = resultList.Item(id).Cast<TCoPgResultItem>();
+            if (pgResultNode.ExpandedColumns().Maybe<TExprList>()) {
+                auto list = pgResultNode.ExpandedColumns().Cast<TExprList>();
+                for (const auto& item : list) {
+                    updateKeyCheck(item.Cast<TCoAtom>().Value());
+                }
+            } else {
+                updateKeyCheck(pgResultNode.ExpandedColumns().Cast<TCoAtom>().Value());
+            }
+        }
+    });
+    return ok;
+}
+} //namespace NPgTypeAnn
+} //namespace NYql

+ 26 - 0
ydb/core/kqp/provider/yql_kikimr_type_ann_pg.h

@@ -0,0 +1,26 @@
+#pragma once
+#include <ydb/library/yql/ast/yql_expr.h>
+#include <ydb/library/yql/core/yql_expr_type_annotation.h>
+#include <ydb/core/kqp/provider/yql_kikimr_expr_nodes.h>
+
+namespace NYql {
+namespace NPgTypeAnn {
+    
+bool NeedsValuesRename(
+    const NNodes::TKiWriteTable& node, 
+    TYdbOperation op);
+
+bool RewriteValuesColumnNames(
+    const NNodes::TKiWriteTable& node, 
+    const TKikimrTableDescription* table, 
+    TExprContext& ctx, 
+    TTypeAnnotationContext& types);
+
+bool ValidatePgUpdateKeys(
+    const NNodes::TKiWriteTable& node, 
+    const TKikimrTableDescription* table, 
+    TExprContext& ctx);
+
+
+} // namespace NPgTypeAnn
+} // namespace NYql

+ 174 - 1
ydb/core/kqp/ut/pg/kqp_pg_ut.cpp

@@ -1571,7 +1571,7 @@ Y_UNIT_TEST_SUITE(KqpPg) {
 
     Y_UNIT_TEST(CreateTempTable) {
         NKikimrConfig::TAppConfig appConfig;
-        appConfig.MutableTableServiceConfig()->SetEnablePreparedDdl(true);;
+        appConfig.MutableTableServiceConfig()->SetEnablePreparedDdl(true);
         auto setting = NKikimrKqp::TKqpSetting();
         auto serverSettings = TKikimrSettings()
             .SetAppConfig(appConfig)
@@ -2271,6 +2271,179 @@ Y_UNIT_TEST_SUITE(KqpPg) {
             CompareYson(R"([["6"]])", FormatResultSetYson(result.GetResultSet(0)));
         }
     }
+
+    Y_UNIT_TEST(InsertNoTargetColumns_Simple) {
+        NKikimrConfig::TAppConfig appConfig;
+        appConfig.MutableTableServiceConfig()->SetEnablePreparedDdl(true);
+        auto setting = NKikimrKqp::TKqpSetting();
+        auto serverSettings = TKikimrSettings()
+            .SetAppConfig(appConfig)
+            .SetKqpSettings({setting});
+        TKikimrRunner kikimr(serverSettings.SetWithSampleTables(false));
+        auto db = kikimr.GetQueryClient();
+        auto settings = NYdb::NQuery::TExecuteQuerySettings().Syntax(NYdb::NQuery::ESyntax::Pg);
+        {
+            auto result = db.ExecuteQuery(R"(
+                CREATE TABLE t(columnA int4, columnB text, primary key(columnA));
+            )", NYdb::NQuery::TTxControl::NoTx(), settings).ExtractValueSync();
+            UNIT_ASSERT_C(result.IsSuccess(), result.GetIssues().ToString());
+        }
+        {
+            auto result = db.ExecuteQuery(R"(
+                INSERT INTO t VALUES (1, 'a'), (2, 'b'), (3, 'c');
+            )", NYdb::NQuery::TTxControl::BeginTx().CommitTx(), settings).ExtractValueSync();
+            UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString());
+        }
+        {
+            auto result = db.ExecuteQuery(R"(
+                SELECT * FROM t;
+            )", NYdb::NQuery::TTxControl::BeginTx().CommitTx(), settings).ExtractValueSync();
+            UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString());
+
+            UNIT_ASSERT_C(!result.GetResultSets().empty(), "results are empty");
+            CompareYson(R"(
+                [["1";"a"];["2";"b"];["3";"c"]]
+            )", FormatResultSetYson(result.GetResultSet(0)));
+        }
+    }
+
+    Y_UNIT_TEST(InsertNoTargetColumns_ColumnOrder) {
+        NKikimrConfig::TAppConfig appConfig;
+        appConfig.MutableTableServiceConfig()->SetEnablePreparedDdl(true);
+        auto setting = NKikimrKqp::TKqpSetting();
+        auto serverSettings = TKikimrSettings()
+            .SetAppConfig(appConfig)
+            .SetKqpSettings({setting});
+        TKikimrRunner kikimr(serverSettings.SetWithSampleTables(false));
+            auto db = kikimr.GetQueryClient();
+        auto settings = NYdb::NQuery::TExecuteQuerySettings().Syntax(NYdb::NQuery::ESyntax::Pg);
+        {
+            auto result = db.ExecuteQuery(R"(
+                CREATE TABLE t(columnC int4, columnA text, columnB text, primary key(columnC));
+            )", NYdb::NQuery::TTxControl::NoTx(), settings).ExtractValueSync();
+            UNIT_ASSERT_C(result.IsSuccess(), result.GetIssues().ToString());
+        }
+        {
+            auto result = db.ExecuteQuery(R"(
+                INSERT INTO t VALUES (1, 'a', 'b'), (2, 'c', 'd'), (3, 'e', 'f');
+            )", NYdb::NQuery::TTxControl::BeginTx().CommitTx(), settings).ExtractValueSync();
+            UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString());
+        }
+        {
+            auto result = db.ExecuteQuery(R"(
+                SELECT * FROM t;
+            )", NYdb::NQuery::TTxControl::BeginTx().CommitTx(), settings).ExtractValueSync();
+            UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString());
+
+            UNIT_ASSERT_C(!result.GetResultSets().empty(), "results are empty");
+            CompareYson(R"(
+                [["1";"a";"b"];["2";"c";"d"];["3";"e";"f"]]
+            )", FormatResultSetYson(result.GetResultSet(0)));
+        }
+    }
+
+    Y_UNIT_TEST(InsertNoTargetColumns_Incorrect) {
+        NKikimrConfig::TAppConfig appConfig;
+        appConfig.MutableTableServiceConfig()->SetEnablePreparedDdl(true);
+        auto setting = NKikimrKqp::TKqpSetting();
+        auto serverSettings = TKikimrSettings()
+            .SetAppConfig(appConfig)
+            .SetKqpSettings({setting});
+        TKikimrRunner kikimr(serverSettings.SetWithSampleTables(false));
+                auto db = kikimr.GetQueryClient();
+        auto settings = NYdb::NQuery::TExecuteQuerySettings().Syntax(NYdb::NQuery::ESyntax::Pg);
+        {
+            auto result = db.ExecuteQuery(R"(
+                CREATE TABLE t(id int4, value text, primary key(id));
+            )", NYdb::NQuery::TTxControl::NoTx(), settings).ExtractValueSync();
+            UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString());
+
+            result = db.ExecuteQuery(R"(
+                CREATE TABLE nopg(id uint64, primary key(id));
+            )", NYdb::NQuery::TTxControl::NoTx()).ExtractValueSync();
+            UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString());
+        }
+        {
+            auto result = db.ExecuteQuery(R"(
+                INSERT INTO t VALUES (1);
+            )", NYdb::NQuery::TTxControl::BeginTx().CommitTx(), settings).ExtractValueSync();
+            UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::GENERIC_ERROR, result.GetIssues().ToString());
+            UNIT_ASSERT(result.GetIssues().ToString().Contains("VALUES have 1 columns, INSERT INTO expects: 2"));
+        }
+        {
+            auto result = db.ExecuteQuery(R"(
+                INSERT INTO t VALUES (1, 'a', 'a');
+            )", NYdb::NQuery::TTxControl::BeginTx().CommitTx(), settings).ExtractValueSync();            
+            UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::GENERIC_ERROR, result.GetIssues().ToString());
+            UNIT_ASSERT(result.GetIssues().ToString().Contains("VALUES have 3 columns, INSERT INTO expects: 2"));
+        }
+        {
+            auto result = db.ExecuteQuery(R"(
+                INSERT INTO t VALUES ('a', 1);
+            )", NYdb::NQuery::TTxControl::BeginTx().CommitTx(), settings).ExtractValueSync();
+            UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::GENERIC_ERROR, result.GetIssues().ToString());
+            UNIT_ASSERT(result.GetIssues().ToString().Contains("Failed to convert 'id': pgtext to pgint4"));
+        }
+        {
+            auto result = db.ExecuteQuery(R"(
+                INSERT INTO nopg VALUES ('a');
+            )", NYdb::NQuery::TTxControl::BeginTx().CommitTx(), settings).ExtractValueSync();
+            UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::GENERIC_ERROR, result.GetIssues().ToString());
+            UNIT_ASSERT(result.GetIssues().ToString().Contains("Failed to convert 'id': pgtext to Optional<Uint64>"));
+        }
+    }
+
+    Y_UNIT_TEST(InsertNoTargetColumns_Alter) {
+        NKikimrConfig::TAppConfig appConfig;
+        appConfig.MutableTableServiceConfig()->SetEnablePreparedDdl(true);
+        auto setting = NKikimrKqp::TKqpSetting();
+        auto serverSettings = TKikimrSettings()
+            .SetAppConfig(appConfig)
+            .SetKqpSettings({setting});
+        TKikimrRunner kikimr(serverSettings.SetWithSampleTables(false));
+        auto db = kikimr.GetQueryClient();
+        auto tableClient = kikimr.GetTableClient();
+        auto settings = NYdb::NQuery::TExecuteQuerySettings().Syntax(NYdb::NQuery::ESyntax::Pg);
+        {
+            auto result = db.ExecuteQuery(R"(
+                CREATE TABLE t(columnB int4, columnA int4, columnC text, primary key(columnA));
+            )", NYdb::NQuery::TTxControl::NoTx(), settings).ExtractValueSync();
+            UNIT_ASSERT_C(result.IsSuccess(), result.GetIssues().ToString());
+        }
+        {
+            auto result = db.ExecuteQuery(R"(
+                INSERT INTO t VALUES (1, 1, 'a'), (2, 2, 'b');
+            )", NYdb::NQuery::TTxControl::BeginTx().CommitTx(), settings).ExtractValueSync();
+            UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString());
+        }
+        {
+            auto session = tableClient.CreateSession().GetValueSync().GetSession();
+            auto result = session.ExecuteSchemeQuery(R"(
+                ALTER TABLE t DROP COLUMN columnB;
+            )").ExtractValueSync();
+            UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString());
+        }
+        {
+            auto result = db.ExecuteQuery(R"(
+                INSERT INTO t VALUES (3, 'c');
+            )", NYdb::NQuery::TTxControl::BeginTx().CommitTx(), settings).ExtractValueSync();
+            UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString());
+        }
+        {
+            auto result = db.ExecuteQuery(R"(
+                SELECT * FROM t;
+            )", NYdb::NQuery::TTxControl::BeginTx().CommitTx(), settings).ExtractValueSync();
+            UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString());
+
+            UNIT_ASSERT_C(!result.GetResultSets().empty(), "results are empty");
+            CompareYson(R"(
+                [["1";"a"];["2";"b"];["3";"c"]]
+            )", FormatResultSetYson(result.GetResultSet(0)));
+        }
+    }
+
+
+
 }
 
 } // namespace NKqp

+ 1 - 1
ydb/library/yql/core/expr_nodes/yql_expr_nodes.json

@@ -2406,7 +2406,7 @@
             "Base": "TCallable",
             "Match": {"Type": "Callable", "Name": "PgSetItem"},
             "Children": [
-                {"Index": 0, "Name": "SetItemOptions", "Type": "TCoNameValueTupleList"}
+                {"Index": 0, "Name": "SetItemOptions", "Type": "TExprList"}
             ]
         },
         {

Some files were not shown because too many files changed in this diff