@@ -304,15 +304,9 @@ void QueryToOperatorTransformer::Visit(
304
304
void QueryToOperatorTransformer::Visit (expression::ComparisonExpression *expr) {
305
305
auto expr_type = expr->GetExpressionType ();
306
306
if (expr->GetExpressionType () == ExpressionType::COMPARE_IN) {
307
- std::vector<expression::AbstractExpression *> select_list;
308
- if (GenerateSubquerytree (expr->GetModifiableChild (1 ), select_list) ==
309
- true ) {
310
- if (select_list.size () != 1 ) {
311
- throw Exception (" Array in predicates not supported" );
312
- }
313
-
314
- // Set the right child as the output of the subquery
315
- expr->SetChild (1 , select_list.at (0 )->Copy ());
307
+ if (GenerateSubquerytree (expr, 1 )) {
308
+ // TODO(boweic): Should use IN to preserve the semantic, for now we do not
309
+ // have semi-join so use = to transform into inner join
316
310
expr->SetExpressionType (ExpressionType::COMPARE_EQUAL);
317
311
}
318
312
@@ -321,40 +315,25 @@ void QueryToOperatorTransformer::Visit(expression::ComparisonExpression *expr) {
321
315
expr_type == ExpressionType::COMPARE_GREATERTHANOREQUALTO ||
322
316
expr_type == ExpressionType::COMPARE_LESSTHAN ||
323
317
expr_type == ExpressionType::COMPARE_LESSTHANOREQUALTO) {
324
- std::vector<expression::AbstractExpression *> select_list;
325
- if (GenerateSubquerytree (expr->GetModifiableChild (0 ), select_list, true ) ==
326
- true ) {
327
- if (select_list.size () != 1 ) {
328
- throw Exception (" Array in predicates not supported" );
329
- }
330
-
331
- // Set the left child as the output of the subquery
332
- expr->SetChild (0 , select_list.at (0 )->Copy ());
333
- }
334
- select_list.clear ();
335
- if (GenerateSubquerytree (expr->GetModifiableChild (1 ), select_list, true ) ==
336
- true ) {
337
- if (select_list.size () != 1 ) {
338
- throw Exception (" Array in predicates not supported" );
339
- }
340
-
341
- // Set the right child as the output of the subquery
342
- expr->SetChild (1 , select_list.at (0 )->Copy ());
318
+ if (expr->GetChild (0 )->GetExpressionType () ==
319
+ ExpressionType::ROW_SUBQUERY &&
320
+ expr->GetChild (1 )->GetExpressionType () ==
321
+ ExpressionType::ROW_SUBQUERY) {
322
+ throw Exception (" Do not support comparison between sub-select" );
343
323
}
324
+ // Transform if either child is sub-query
325
+ GenerateSubquerytree (expr, 0 , true ) || GenerateSubquerytree (expr, 1 , true );
344
326
}
345
327
expr->AcceptChildren (this );
346
328
}
347
329
348
330
void QueryToOperatorTransformer::Visit (expression::OperatorExpression *expr) {
331
+ // TODO(boweic): We may want to do the rewrite (exist -> in) in the binder
349
332
if (expr->GetExpressionType () == ExpressionType::OPERATOR_EXISTS) {
350
- std::vector<expression::AbstractExpression *> select_list;
351
- if (GenerateSubquerytree (expr->GetModifiableChild (0 ), select_list) ==
352
- true ) {
353
- PL_ASSERT (!select_list.empty ());
354
-
355
- // Set the right child as the output of the subquery
333
+ if (GenerateSubquerytree (expr, 0 )) {
334
+ // Already reset the child to column, we need to transform exist to
335
+ // not-null to preserve semantic
356
336
expr->SetExpressionType (ExpressionType::OPERATOR_IS_NOT_NULL);
357
- expr->SetChild (0 , select_list.at (0 )->Copy ());
358
337
}
359
338
}
360
339
@@ -391,24 +370,117 @@ bool QueryToOperatorTransformer::RequireAggregation(
391
370
392
371
void QueryToOperatorTransformer::CollectPredicates (
393
372
expression::AbstractExpression *expr) {
373
+ // First check if all conjunctive predicates are supported before
374
+ // transfoming
375
+ // predicate with sub-select into regular predicates
376
+ std::vector<expression::AbstractExpression *> predicates;
377
+ util::SplitPredicates (expr, predicates);
378
+ for (const auto &pred : predicates) {
379
+ if (!IsSupportedConjunctivePredicate (pred)) {
380
+ throw Exception (" Predicate type not supported yet" );
381
+ }
382
+ }
383
+ // Accept will change the expression, e.g. (a in (select b from test)) into
384
+ // (a IN test.b), after the rewrite, we can extract the table aliases
385
+ // information correctly
394
386
expr->Accept (this );
395
387
util::ExtractPredicates (expr, predicates_);
396
388
}
397
389
398
- bool QueryToOperatorTransformer::GenerateSubquerytree (
399
- expression::AbstractExpression *expr,
400
- std::vector<expression::AbstractExpression *> &select_list,
401
- bool single_join) {
402
- if (expr->GetExpressionType () != ExpressionType::ROW_SUBQUERY) {
403
- return false ;
390
+ bool QueryToOperatorTransformer::IsSupportedConjunctivePredicate (
391
+ expression::AbstractExpression *expr) {
392
+ // Currently support : 1. expr without subquery
393
+ // 2. subquery without disjunction. Since the expr is already one of the
394
+ // conjunctive exprs, we'll only need to check if the root level is an
395
+ // operator with subquery
396
+ if (!expr->HasSubquery ()) {
397
+ return true ;
398
+ }
399
+ auto expr_type = expr->GetExpressionType ();
400
+ // Subquery with IN
401
+ if (expr_type == ExpressionType::COMPARE_IN &&
402
+ expr->GetChild (1 )->GetExpressionType () == ExpressionType::ROW_SUBQUERY) {
403
+ return true ;
404
+ }
405
+ // Subquery with EXIST
406
+ if (expr_type == ExpressionType::OPERATOR_EXISTS &&
407
+ expr->GetChild (0 )->GetExpressionType () == ExpressionType::ROW_SUBQUERY) {
408
+ return true ;
409
+ }
410
+ // Subquery with other operator
411
+ if (expr_type == ExpressionType::COMPARE_EQUAL ||
412
+ expr_type == ExpressionType::COMPARE_GREATERTHAN ||
413
+ expr_type == ExpressionType::COMPARE_GREATERTHANOREQUALTO ||
414
+ expr_type == ExpressionType::COMPARE_LESSTHAN ||
415
+ expr_type == ExpressionType::COMPARE_LESSTHANOREQUALTO) {
416
+ // Supported is one child is subquery and the other is not
417
+ if ((!expr->GetChild (0 )->HasSubquery () &&
418
+ expr->GetChild (1 )->GetExpressionType () ==
419
+ ExpressionType::ROW_SUBQUERY) ||
420
+ (!expr->GetChild (1 )->HasSubquery () &&
421
+ expr->GetChild (0 )->GetExpressionType () ==
422
+ ExpressionType::ROW_SUBQUERY)) {
423
+ return true ;
424
+ }
404
425
}
405
- auto subquery_expr = dynamic_cast <expression::SubqueryExpression *>(expr) ;
406
- auto sub_select = subquery_expr-> GetSubSelect ();
426
+ return false ;
427
+ }
407
428
408
- for (auto &ele : sub_select->select_list ) {
409
- select_list.push_back (ele.get ());
429
+ bool QueryToOperatorTransformer::IsSupportedSubSelect (
430
+ const parser::SelectStatement *op) {
431
+ // Supported if 1. No aggregation. 2. With aggregation and WHERE clause only
432
+ // have correlated columns in conjunctive predicates in the form of
433
+ // "outer_relation.a = ..."
434
+ // TODO(boweic): Add support for arbitary expressions, this would require
435
+ // the
436
+ // support for mark join & some special operators, see Hyper's unnesting
437
+ // arbitary query slides
438
+ if (!RequireAggregation (op)) {
439
+ return true ;
440
+ }
441
+
442
+ std::vector<expression::AbstractExpression *> predicates;
443
+ util::SplitPredicates (op->where_clause .get (), predicates);
444
+ for (const auto &pred : predicates) {
445
+ // If correlated predicate
446
+ if (pred->GetDepth () < op->depth ) {
447
+ if (pred->GetExpressionType () != ExpressionType::COMPARE_EQUAL) {
448
+ return false ;
449
+ }
450
+ // Check if in the form of
451
+ // "outer_relation.a = (expr only columns in inner relation)"
452
+ if (!((pred->GetChild (0 )->GetDepth () == op->depth &&
453
+ pred->GetChild (0 )->GetExpressionType () ==
454
+ ExpressionType::VALUE_TUPLE) ||
455
+ (pred->GetChild (1 )->GetDepth () == op->depth &&
456
+ pred->GetChild (1 )->GetExpressionType () ==
457
+ ExpressionType::VALUE_TUPLE))) {
458
+ return false ;
459
+ }
460
+ }
410
461
}
462
+ return true ;
463
+ }
411
464
465
+ bool QueryToOperatorTransformer::GenerateSubquerytree (
466
+ expression::AbstractExpression *expr, oid_t child_id, bool single_join) {
467
+ // Get potential subquery
468
+ auto subquery_expr = expr->GetChild (child_id);
469
+ if (subquery_expr->GetExpressionType () != ExpressionType::ROW_SUBQUERY) {
470
+ return false ;
471
+ }
472
+ auto sub_select =
473
+ static_cast <const expression::SubqueryExpression *>(subquery_expr)
474
+ ->GetSubSelect ()
475
+ .get ();
476
+ if (!IsSupportedSubSelect (sub_select)) {
477
+ throw Exception (" Sub-select not supported" );
478
+ }
479
+ // We only support subselect with single row
480
+ if (sub_select->select_list .size () != 1 ) {
481
+ throw Exception (" Array in predicates not supported" );
482
+ }
483
+ std::vector<expression::AbstractExpression *> select_list;
412
484
// Construct join
413
485
std::shared_ptr<OperatorExpression> op_expr;
414
486
if (single_join) {
@@ -426,6 +498,8 @@ bool QueryToOperatorTransformer::GenerateSubquerytree(
426
498
op_expr->PushChild (output_expr_);
427
499
428
500
output_expr_ = op_expr;
501
+ // Convert subquery to the selected column in the sub-select
502
+ expr->SetChild (child_id, sub_select->select_list .at (0 )->Copy ());
429
503
return true ;
430
504
}
431
505
0 commit comments