| 486 | } |
| 487 | |
| 488 | static inline void PrintToImpl(const std::string& factory_name, |
| 489 | const ExecNodeOptions& opts, std::ostream* os) { |
| 490 | if (factory_name == "filter") { |
| 491 | return PrintTo(OptionsAs<FilterNodeOptions>(opts).filter_expression, os); |
| 492 | } |
| 493 | |
| 494 | if (factory_name == "project") { |
| 495 | auto o = &OptionsAs<ProjectNodeOptions>(opts); |
| 496 | *os << "expressions={"; |
| 497 | for (const auto& expr : o->expressions) { |
| 498 | PrintTo(expr, os); |
| 499 | *os << ","; |
| 500 | } |
| 501 | *os << "},"; |
| 502 | |
| 503 | if (!o->names.empty()) { |
| 504 | *os << "names={"; |
| 505 | for (const auto& name : o->names) { |
| 506 | *os << name << ","; |
| 507 | } |
| 508 | *os << "}"; |
| 509 | } |
| 510 | return; |
| 511 | } |
| 512 | |
| 513 | if (factory_name == "aggregate") { |
| 514 | auto o = &OptionsAs<AggregateNodeOptions>(opts); |
| 515 | |
| 516 | *os << "aggregates={"; |
| 517 | for (const auto& agg : o->aggregates) { |
| 518 | *os << "function=" << agg.function << "<"; |
| 519 | if (agg.options) PrintTo(*agg.options, os); |
| 520 | *os << ">,"; |
| 521 | *os << "target="; |
| 522 | if (agg.target.size() == 0) { |
| 523 | *os << "*"; |
| 524 | } else if (agg.target.size() == 1) { |
| 525 | *os << agg.target[0].ToString(); |
| 526 | } else { |
| 527 | *os << "(" << agg.target[0].ToString(); |
| 528 | for (size_t i = 1; i < agg.target.size(); i++) { |
| 529 | *os << "," << agg.target[i].ToString(); |
| 530 | } |
| 531 | *os << ")"; |
| 532 | } |
| 533 | *os << ","; |
| 534 | *os << "name=" << agg.name; |
| 535 | } |
| 536 | *os << "}"; |
| 537 | |
| 538 | if (!o->keys.empty()) { |
| 539 | *os << ",keys={"; |
| 540 | for (const auto& key : o->keys) { |
| 541 | *os << key.ToString() << ","; |
| 542 | } |
| 543 | *os << "}"; |
| 544 | } |
| 545 | return; |