@@ -69,6 +69,7 @@ namespace NYql {
69
69
}
70
70
71
71
// data
72
+ MATCH_ATOM (Bool, BOOL, bool , bool );
72
73
MATCH_ATOM (Int8, INT8, int32, i8 );
73
74
MATCH_ATOM (Uint8, UINT8, uint32, ui8);
74
75
MATCH_ATOM (Int16, INT16, int32, i16 );
@@ -125,17 +126,41 @@ namespace NYql {
125
126
126
127
#undef EXPR_NODE_TO_COMPARE_TYPE
127
128
128
- bool SerializeCoalesce (const TCoCoalesce& coalesce, TPredicate* proto, const TCoArgument& arg, TStringBuilder& err) {
129
- auto predicate = coalesce.Predicate ();
130
- if (auto compare = predicate.Maybe <TCoCompare>()) {
131
- return SerializeCompare (compare.Cast (), proto, arg, err);
132
- }
129
+ bool SerializePredicate (const TExprBase& predicate, TPredicate* proto, const TCoArgument& arg, TStringBuilder& err, ui64 depth);
133
130
134
- err << " unknown coalesce predicate: " << predicate.Raw ()->Content ();
135
- return false ;
131
+ bool SerializeSqlIf (const TCoIf& sqlIf, TPredicate* proto, const TCoArgument& arg, TStringBuilder& err, ui64 depth) {
132
+ auto * dstProto = proto->mutable_if_ ();
133
+ return SerializePredicate (TExprBase (sqlIf.Predicate ()), dstProto->mutable_predicate (), arg, err, depth + 1 )
134
+ && SerializePredicate (TExprBase (sqlIf.ThenValue ()), dstProto->mutable_then_predicate (), arg, err, depth + 1 )
135
+ && SerializePredicate (TExprBase (sqlIf.ElseValue ()), dstProto->mutable_else_predicate (), arg, err, depth + 1 );
136
136
}
137
137
138
- bool SerializePredicate (const TExprBase& predicate, TPredicate* proto, const TCoArgument& arg, TStringBuilder& err);
138
+ bool SerializeCoalesce (const TCoCoalesce& coalesce, TPredicate* proto, const TCoArgument& arg, TStringBuilder& err, ui64 depth) {
139
+ // Special case for top level COALESCE: COALESCE(Predicat, FALSE)
140
+ // We can assume NULL as FALSE and skip COALESCE
141
+ if (depth == 0 ) {
142
+ auto value = coalesce.Value ().Maybe <TCoBool>();
143
+ if (value && TStringBuf (value.Cast ().Literal ()) == " false" sv) {
144
+ return SerializePredicate (TExprBase (coalesce.Predicate ()), proto, arg, err, 0 );
145
+ }
146
+ }
147
+
148
+ auto * dstProto = proto->mutable_coalesce ();
149
+ for (const auto & child : coalesce.Ptr ()->Children ()) {
150
+ if (!SerializePredicate (TExprBase (child), dstProto->add_operands (), arg, err, depth + 1 )) {
151
+ return false ;
152
+ }
153
+
154
+ // We can unwrap nested COALESCE:
155
+ // COALESCE(..., COALESCE(Predicat_1, Predicat_2), ...) -> COALESCE(..., Predicat_1, Predicat_2, ...)
156
+ if (dstProto->operands ().rbegin ()->has_coalesce ()) {
157
+ auto coalesceOperands = std::move (*dstProto->mutable_operands ()->rbegin ()->mutable_coalesce ()->mutable_operands ());
158
+ dstProto->mutable_operands ()->RemoveLast ();
159
+ dstProto->mutable_operands ()->Add (coalesceOperands.begin (), coalesceOperands.end ());
160
+ }
161
+ }
162
+ return true ;
163
+ }
139
164
140
165
bool SerializeExists (const TCoExists& exists, TPredicate* proto, const TCoArgument& arg, TStringBuilder& err, bool withNot = false ) {
141
166
auto * expressionProto = withNot ? proto->mutable_is_null ()->mutable_value () : proto->mutable_is_not_null ()->mutable_value ();
@@ -168,54 +193,54 @@ namespace NYql {
168
193
return true ;
169
194
}
170
195
171
- bool SerializeAnd (const TCoAnd& andExpr, TPredicate* proto, const TCoArgument& arg, TStringBuilder& err) {
196
+ bool SerializeAnd (const TCoAnd& andExpr, TPredicate* proto, const TCoArgument& arg, TStringBuilder& err, ui64 depth ) {
172
197
auto * dstProto = proto->mutable_conjunction ();
173
198
for (const auto & child : andExpr.Ptr ()->Children ()) {
174
- if (!SerializePredicate (TExprBase (child), dstProto->add_operands (), arg, err)) {
199
+ if (!SerializePredicate (TExprBase (child), dstProto->add_operands (), arg, err, depth + 1 )) {
175
200
return false ;
176
201
}
177
202
}
178
203
return true ;
179
204
}
180
205
181
- bool SerializeOr (const TCoOr& orExpr, TPredicate* proto, const TCoArgument& arg, TStringBuilder& err) {
206
+ bool SerializeOr (const TCoOr& orExpr, TPredicate* proto, const TCoArgument& arg, TStringBuilder& err, ui64 depth ) {
182
207
auto * dstProto = proto->mutable_disjunction ();
183
208
for (const auto & child : orExpr.Ptr ()->Children ()) {
184
- if (!SerializePredicate (TExprBase (child), dstProto->add_operands (), arg, err)) {
209
+ if (!SerializePredicate (TExprBase (child), dstProto->add_operands (), arg, err, depth + 1 )) {
185
210
return false ;
186
211
}
187
212
}
188
213
return true ;
189
214
}
190
215
191
- bool SerializeNot (const TCoNot& notExpr, TPredicate* proto, const TCoArgument& arg, TStringBuilder& err) {
216
+ bool SerializeNot (const TCoNot& notExpr, TPredicate* proto, const TCoArgument& arg, TStringBuilder& err, ui64 depth ) {
192
217
// Special case: (Not (Exists ...))
193
218
if (auto exists = notExpr.Value ().Maybe <TCoExists>()) {
194
219
return SerializeExists (exists.Cast (), proto, arg, err, true );
195
220
}
196
221
auto * dstProto = proto->mutable_negation ();
197
- return SerializePredicate (notExpr.Value (), dstProto->mutable_operand (), arg, err);
222
+ return SerializePredicate (notExpr.Value (), dstProto->mutable_operand (), arg, err, depth + 1 );
198
223
}
199
224
200
225
bool SerializeMember (const TCoMember& member, TPredicate* proto, const TCoArgument& arg, TStringBuilder& err) {
201
226
return SerializeMember (member, proto->mutable_bool_expression ()->mutable_value (), arg, err);
202
227
}
203
228
204
- bool SerializePredicate (const TExprBase& predicate, TPredicate* proto, const TCoArgument& arg, TStringBuilder& err) {
229
+ bool SerializePredicate (const TExprBase& predicate, TPredicate* proto, const TCoArgument& arg, TStringBuilder& err, ui64 depth ) {
205
230
if (auto compare = predicate.Maybe <TCoCompare>()) {
206
231
return SerializeCompare (compare.Cast (), proto, arg, err);
207
232
}
208
233
if (auto coalesce = predicate.Maybe <TCoCoalesce>()) {
209
- return SerializeCoalesce (coalesce.Cast (), proto, arg, err);
234
+ return SerializeCoalesce (coalesce.Cast (), proto, arg, err, depth );
210
235
}
211
236
if (auto andExpr = predicate.Maybe <TCoAnd>()) {
212
- return SerializeAnd (andExpr.Cast (), proto, arg, err);
237
+ return SerializeAnd (andExpr.Cast (), proto, arg, err, depth );
213
238
}
214
239
if (auto orExpr = predicate.Maybe <TCoOr>()) {
215
- return SerializeOr (orExpr.Cast (), proto, arg, err);
240
+ return SerializeOr (orExpr.Cast (), proto, arg, err, depth );
216
241
}
217
242
if (auto notExpr = predicate.Maybe <TCoNot>()) {
218
- return SerializeNot (notExpr.Cast (), proto, arg, err);
243
+ return SerializeNot (notExpr.Cast (), proto, arg, err, depth );
219
244
}
220
245
if (auto member = predicate.Maybe <TCoMember>()) {
221
246
return SerializeMember (member.Cast (), proto, arg, err);
@@ -226,9 +251,16 @@ namespace NYql {
226
251
if (auto sqlIn = predicate.Maybe <TCoSqlIn>()) {
227
252
return SerializeSqlIn (sqlIn.Cast (), proto, arg, err);
228
253
}
254
+ if (auto sqlIf = predicate.Maybe <TCoIf>()) {
255
+ return SerializeSqlIf (sqlIf.Cast (), proto, arg, err, depth);
256
+ }
257
+ if (auto just = predicate.Maybe <TCoJust>()) {
258
+ return SerializePredicate (TExprBase (just.Cast ().Input ()), proto, arg, err, depth + 1 );
259
+ }
229
260
230
- err << " unknown predicate: " << predicate.Raw ()->Content ();
231
- return false ;
261
+ // Try to serialize predicate as boolean expression
262
+ // For example single bool value TRUE in COALESCE or IF
263
+ return SerializeExpression (predicate, proto->mutable_bool_expression ()->mutable_value (), arg, err);
232
264
}
233
265
}
234
266
@@ -239,7 +271,7 @@ namespace NYql {
239
271
TString FormatValue (const Ydb::TypedValue& value) {
240
272
switch (value.value ().value_case ()) {
241
273
case Ydb::Value::kBoolValue :
242
- return ToString ( value.value ().bool_value ()) ;
274
+ return value.value ().bool_value () ? " TRUE " : " FALSE " ;
243
275
case Ydb::Value::kInt32Value :
244
276
return ToString (value.value ().int32_value ());
245
277
case Ydb::Value::kUint32Value :
@@ -383,6 +415,49 @@ namespace NYql {
383
415
return stream.Str ();
384
416
}
385
417
418
+ TString FormatCoalesce (const TPredicate::TCoalesce& coalesce) {
419
+ TStringStream stream;
420
+ TString first;
421
+ ui32 cnt = 0 ;
422
+
423
+ for (const auto & predicate : coalesce.operands ()) {
424
+ auto statement = FormatPredicate (predicate, false );
425
+
426
+ if (cnt > 0 ) {
427
+ if (cnt == 1 ) {
428
+ stream << " COALESCE(" ;
429
+ stream << first;
430
+ }
431
+
432
+ stream << " , " ;
433
+ stream << statement;
434
+ } else {
435
+ first = statement;
436
+ }
437
+ cnt++;
438
+ }
439
+
440
+ if (cnt == 0 ) {
441
+ throw yexception () << " failed to format COALESCE statement: no operands" ;
442
+ }
443
+
444
+ if (cnt == 1 ) {
445
+ stream << first;
446
+ } else {
447
+ stream << " )" ;
448
+ }
449
+
450
+ return stream.Str ();
451
+ }
452
+
453
+ TString FormatIf (const TPredicate::TIf& sqlIf) {
454
+ TStringStream stream;
455
+ stream << " IF(" << FormatPredicate (sqlIf.predicate (), false );
456
+ stream << " , " << FormatPredicate (sqlIf.then_predicate (), false );
457
+ stream << " , " << FormatPredicate (sqlIf.else_predicate (), false ) << " )" ;
458
+ return stream.Str ();
459
+ }
460
+
386
461
TString FormatIsNull (const TPredicate_TIsNull& isNull) {
387
462
auto statement = FormatExpression (isNull.value ());
388
463
return " (" + statement + " IS NULL)" ;
@@ -453,6 +528,10 @@ namespace NYql {
453
528
return FormatConjunction (predicate.conjunction (), topLevel);
454
529
case TPredicate::kDisjunction :
455
530
return FormatDisjunction (predicate.disjunction ());
531
+ case TPredicate::kCoalesce :
532
+ return FormatCoalesce (predicate.coalesce ());
533
+ case TPredicate::kIf :
534
+ return FormatIf (predicate.if_ ());
456
535
case TPredicate::kIsNull :
457
536
return FormatIsNull (predicate.is_null ());
458
537
case TPredicate::kIsNotNull :
@@ -477,7 +556,7 @@ namespace NYql {
477
556
}
478
557
479
558
bool SerializeFilterPredicate (const TCoLambda& predicate, TPredicate* proto, TStringBuilder& err) {
480
- return SerializePredicate (predicate.Body (), proto, predicate.Args ().Arg (0 ), err);
559
+ return SerializePredicate (predicate.Body (), proto, predicate.Args ().Arg (0 ), err, 0 );
481
560
}
482
561
483
562
TString FormatWhere (const TPredicate& predicate) {
0 commit comments