1313namespace NKikimr ::NMiniKQL {
1414
1515// NOTE: TCell's can reference memomry from tupleValue
16+ // TODO: Place notNull flag in to the NScheme::TTypeInfo?
1617bool CellsFromTuple (const NKikimrMiniKQL::TType* tupleType,
1718 const NKikimrMiniKQL::TValue& tupleValue,
1819 const TConstArrayRef<NScheme::TTypeInfo>& types,
20+ TVector<bool > notNullTypes,
1921 bool allowCastFromString,
2022 TVector<TCell>& key,
2123 TString& errStr,
@@ -28,6 +30,18 @@ bool CellsFromTuple(const NKikimrMiniKQL::TType* tupleType,
2830 return false ; \
2931 }
3032
33+ // Please note we modify notNullTypes during tuplyType verification to allow cast nullable to non nullable value
34+ if (notNullTypes) {
35+ CHECK_OR_RETURN_ERROR (notNullTypes.size () == types.size (),
36+ " The size of type array and given not null markers must be equial" );
37+ if (tupleType) {
38+ CHECK_OR_RETURN_ERROR (notNullTypes.size () >= tupleType->GetTuple ().ElementSize (),
39+ " The size of tuple type and given not null markers must be equal" );
40+ }
41+ } else {
42+ notNullTypes.resize (types.size ());
43+ }
44+
3145 if (tupleType) {
3246 CHECK_OR_RETURN_ERROR (tupleType->GetKind () == NKikimrMiniKQL::Tuple ||
3347 (tupleType->GetKind () == NKikimrMiniKQL::Unknown && tupleType->GetTuple ().ElementSize () == 0 ), " Must be a tuple" );
@@ -36,8 +50,14 @@ bool CellsFromTuple(const NKikimrMiniKQL::TType* tupleType,
3650
3751 for (size_t i = 0 ; i < tupleType->GetTuple ().ElementSize (); ++i) {
3852 const auto & ti = tupleType->GetTuple ().GetElement (i);
39- CHECK_OR_RETURN_ERROR (ti.GetKind () == NKikimrMiniKQL::Optional, " Element at index " + ToString (i) + " in not an Optional" );
40- const auto & item = ti.GetOptional ().GetItem ();
53+ if (notNullTypes[i]) {
54+ // For not null column type we allow to build cell from nullable mkql type for compatibility reason.
55+ notNullTypes[i] = ti.GetKind () != NKikimrMiniKQL::Optional;
56+ } else {
57+ // But we do not allow to build cell for nullable column from not nullable type
58+ CHECK_OR_RETURN_ERROR (ti.GetKind () == NKikimrMiniKQL::Optional, " Element at index " + ToString (i) + " in not an Optional" );
59+ }
60+ const auto & item = notNullTypes[i] ? ti : ti.GetOptional ().GetItem ();
4161 CHECK_OR_RETURN_ERROR (item.GetKind () == NKikimrMiniKQL::Data, " Element at index " + ToString (i) + " Item kind is not Data" );
4262 const auto & typeId = item.GetData ().GetScheme ();
4363 CHECK_OR_RETURN_ERROR (typeId == types[i].GetTypeId () ||
@@ -53,26 +73,36 @@ bool CellsFromTuple(const NKikimrMiniKQL::TType* tupleType,
5373 }
5474
5575 for (ui32 i = 0 ; i < tupleValue.TupleSize (); ++i) {
56- auto & o = tupleValue.GetTuple (i);
57-
58- auto element_case = o.value_value_case ();
59-
60- CHECK_OR_RETURN_ERROR (element_case == NKikimrMiniKQL::TValue::kOptional ||
61- element_case == NKikimrMiniKQL::TValue::VALUE_VALUE_NOT_SET,
62- Sprintf (" Optional type is expected in tuple at position %" PRIu32, i));
6376
64- CHECK_OR_RETURN_ERROR (o.ListSize () == 0 &&
65- o.StructSize () == 0 &&
66- o.TupleSize () == 0 &&
67- o.DictSize () == 0 ,
68- Sprintf (" Optional type is expected in tuple at position %" PRIu32, i));
77+ auto & o = tupleValue.GetTuple (i);
6978
70- if (!o.HasOptional ()) {
71- key.push_back (TCell ());
72- continue ;
79+ if (notNullTypes[i]) {
80+ CHECK_OR_RETURN_ERROR (o.ListSize () == 0 &&
81+ o.StructSize () == 0 &&
82+ o.TupleSize () == 0 &&
83+ o.DictSize () == 0 &&
84+ !o.HasOptional (),
85+ Sprintf (" Primitive type is expected in tuple at position %" PRIu32, i));
86+ } else {
87+ auto element_case = o.value_value_case ();
88+
89+ CHECK_OR_RETURN_ERROR (element_case == NKikimrMiniKQL::TValue::kOptional ||
90+ element_case == NKikimrMiniKQL::TValue::VALUE_VALUE_NOT_SET,
91+ Sprintf (" Optional type is expected in tuple at position %" PRIu32, i));
92+
93+ CHECK_OR_RETURN_ERROR (o.ListSize () == 0 &&
94+ o.StructSize () == 0 &&
95+ o.TupleSize () == 0 &&
96+ o.DictSize () == 0 ,
97+ Sprintf (" Optional type is expected in tuple at position %" PRIu32, i));
98+
99+ if (!o.HasOptional ()) {
100+ key.push_back (TCell ());
101+ continue ;
102+ }
73103 }
74104
75- auto & v = o.GetOptional ();
105+ auto & v = notNullTypes[i] ? o : o.GetOptional ();
76106
77107 auto value_case = v.value_value_case ();
78108
0 commit comments