@@ -39,9 +39,9 @@ NYql::TExprNode::TPtr MakeUniqCheckDict(const TCoLambda& selector,
3939
4040class TInsertUniqBuildHelper : public TUniqBuildHelper {
4141public:
42- TInsertUniqBuildHelper (const NYql::TKikimrTableDescription& table, NYql::TPositionHandle pos ,
43- NYql::TExprContext& ctx)
44- : TUniqBuildHelper(table, nullptr , nullptr , pos, ctx, false )
42+ TInsertUniqBuildHelper (const NYql::TKikimrTableDescription& table, const TMaybe<THashSet<TStringBuf>>& inputColumns ,
43+ NYql::TPositionHandle pos, NYql:: TExprContext& ctx)
44+ : TUniqBuildHelper(table, inputColumns , nullptr , pos, ctx, true )
4545 {}
4646
4747private:
@@ -119,9 +119,9 @@ class TInsertUniqBuildHelper : public TUniqBuildHelper {
119119
120120class TUpsertUniqBuildHelper : public TUniqBuildHelper {
121121public:
122- TUpsertUniqBuildHelper (const NYql::TKikimrTableDescription& table, const THashSet<TStringBuf>* inputColumns, const THashSet<TString>& usedIndexes,
122+ TUpsertUniqBuildHelper (const NYql::TKikimrTableDescription& table, const TMaybe< THashSet<TStringBuf>>& inputColumns, const THashSet<TString>& usedIndexes,
123123 NYql::TPositionHandle pos, NYql::TExprContext& ctx)
124- : TUniqBuildHelper(table, inputColumns, &usedIndexes, pos, ctx, true )
124+ : TUniqBuildHelper(table, inputColumns, &usedIndexes, pos, ctx, false )
125125 , PkDict(MakeUniqCheckDict(MakeTableKeySelector(table.Metadata, pos, ctx), RowsListArg, pos, ctx))
126126 {}
127127
@@ -243,12 +243,12 @@ class TUpsertUniqBuildHelper : public TUniqBuildHelper {
243243}
244244
245245TVector<TUniqBuildHelper::TUniqCheckNodes> TUniqBuildHelper::Prepare (const TCoArgument& rowsListArg,
246- const TKikimrTableDescription& table, const THashSet<TStringBuf>* inputColumns,
247- const THashSet<TString>* usedIndexes, TPositionHandle pos, TExprContext& ctx, bool skipPkCheck )
246+ const TKikimrTableDescription& table, const TMaybe< THashSet<TStringBuf>>& inputColumns,
247+ const THashSet<TString>* usedIndexes, TPositionHandle pos, TExprContext& ctx, bool insertMode )
248248{
249249 TVector<TUniqCheckNodes> checks;
250250
251- if (!skipPkCheck ) {
251+ if (insertMode ) {
252252 checks.emplace_back (MakeUniqCheckNodes (MakeTableKeySelector (table.Metadata , pos, ctx), rowsListArg, pos, ctx));
253253 }
254254
@@ -262,19 +262,34 @@ TVector<TUniqBuildHelper::TUniqCheckNodes> TUniqBuildHelper::Prepare(const TCoAr
262262 continue ;
263263
264264 // Compatibility with PG semantic - allow multiple null in columns with unique constaint
265+ // NOTE: to change this it's important to consider insert and replace in case of partial column set
265266 TVector<TCoAtom> skipNullColumns;
266267 skipNullColumns.reserve (table.Metadata ->Indexes [i].KeyColumns .size ());
267268
268269 bool used = false ;
270+ bool skip = false ;
271+
272+ YQL_ENSURE (inputColumns, " Attempt to check uniq constraint without given columns" );
273+
269274 for (const auto & column : table.Metadata ->Indexes [i].KeyColumns ) {
270- used |= (!inputColumns || inputColumns->contains (column));
275+ if (inputColumns->contains (column)) {
276+ // Skip check if no input for index update
277+ used = true ;
278+ } else if (insertMode) {
279+ // In case of insert, 'column' will contain NULL for the new PK (or query will fail in case of NOT NULL)
280+ // NULL != NULL and NULL != "any other value" so we can just skip uniq check.
281+ skip = true ;
282+ continue ;
283+ }
271284 TCoAtom atom (ctx.NewAtom (pos, column));
272285 skipNullColumns.emplace_back (atom);
273286 }
274287
275- // Just to doublecheck we are not trying to update index without data to update
276- YQL_ENSURE (used, " Index is used but not input columns for update. Probably it's a bug."
277- " Index: " << table.Metadata ->Indexes [i].Name );
288+ if (!used)
289+ continue ;
290+
291+ if (skip)
292+ continue ;
278293
279294 auto skipNull = Build<TCoSkipNullMembers>(ctx, pos)
280295 .Input (rowsListArg)
@@ -292,7 +307,7 @@ TVector<TUniqBuildHelper::TUniqCheckNodes> TUniqBuildHelper::Prepare(const TCoAr
292307 return checks;
293308}
294309
295- static TExprNode::TPtr CreateRowsToPass (const TCoArgument& rowsListArg, const THashSet<TStringBuf>* inputColumns,
310+ static TExprNode::TPtr CreateRowsToPass (const TCoArgument& rowsListArg, const TMaybe< THashSet<TStringBuf>>& inputColumns,
296311 TPositionHandle pos, TExprContext& ctx)
297312{
298313 if (!inputColumns) {
@@ -326,11 +341,11 @@ static TExprNode::TPtr CreateRowsToPass(const TCoArgument& rowsListArg, const TH
326341 .Done ().Ptr ();
327342}
328343
329- TUniqBuildHelper::TUniqBuildHelper (const TKikimrTableDescription& table, const THashSet<TStringBuf>* inputColumns, const THashSet<TString>* usedIndexes,
330- TPositionHandle pos, TExprContext& ctx, bool skipPkCheck )
344+ TUniqBuildHelper::TUniqBuildHelper (const TKikimrTableDescription& table, const TMaybe< THashSet<TStringBuf>>& inputColumns, const THashSet<TString>* usedIndexes,
345+ TPositionHandle pos, TExprContext& ctx, bool insertMode )
331346 : RowsListArg(ctx.NewArgument(pos, " rows_list" ))
332347 , False(MakeBool(pos, false , ctx))
333- , Checks(Prepare(RowsListArg, table, inputColumns, usedIndexes, pos, ctx, skipPkCheck ))
348+ , Checks(Prepare(RowsListArg, table, inputColumns, usedIndexes, pos, ctx, insertMode ))
334349 , RowsToPass(CreateRowsToPass(RowsListArg, inputColumns, pos, ctx))
335350{}
336351
@@ -548,14 +563,15 @@ TDqStage TUniqBuildHelper::CreateLookupExistStage(const TDqStage& computeKeysSta
548563namespace NKikimr ::NKqp::NOpt {
549564
550565
551- TUniqBuildHelper::TPtr CreateInsertUniqBuildHelper (const NYql::TKikimrTableDescription& table, NYql::TPositionHandle pos,
552- NYql::TExprContext& ctx)
566+ TUniqBuildHelper::TPtr CreateInsertUniqBuildHelper (const NYql::TKikimrTableDescription& table,
567+ const TMaybe<THashSet<TStringBuf>>& inputColumns, NYql::TPositionHandle pos,
568+ NYql::TExprContext& ctx)
553569{
554- return std::make_unique<TInsertUniqBuildHelper>(table, pos, ctx);
570+ return std::make_unique<TInsertUniqBuildHelper>(table, inputColumns, pos, ctx);
555571}
556572
557573TUniqBuildHelper::TPtr CreateUpsertUniqBuildHelper (const NYql::TKikimrTableDescription& table,
558- const THashSet<TStringBuf>* inputColumns,
574+ const TMaybe< THashSet<TStringBuf>>& inputColumns,
559575 const THashSet<TString>& usedIndexes, NYql::TPositionHandle pos, NYql::TExprContext& ctx)
560576{
561577 return std::make_unique<TUpsertUniqBuildHelper>(table, inputColumns, usedIndexes, pos, ctx);
0 commit comments