diff options
Diffstat (limited to 'lib/statement.cpp')
| -rw-r--r-- | lib/statement.cpp | 232 |
1 files changed, 180 insertions, 52 deletions
| diff --git a/lib/statement.cpp b/lib/statement.cpp index 562eef2..b892cab 100644 --- a/lib/statement.cpp +++ b/lib/statement.cpp | |||
| @@ -3,13 +3,6 @@ | |||
| 3 | #include <utility> | 3 | #include <utility> |
| 4 | #include "filter.h" | 4 | #include "filter.h" |
| 5 | #include "util.h" | 5 | #include "util.h" |
| 6 | #include "notion.h" | ||
| 7 | #include "word.h" | ||
| 8 | #include "frame.h" | ||
| 9 | #include "part.h" | ||
| 10 | #include "lemma.h" | ||
| 11 | #include "form.h" | ||
| 12 | #include "pronunciation.h" | ||
| 13 | #include "order.h" | 6 | #include "order.h" |
| 14 | 7 | ||
| 15 | namespace verbly { | 8 | namespace verbly { |
| @@ -17,7 +10,7 @@ namespace verbly { | |||
| 17 | statement::statement( | 10 | statement::statement( |
| 18 | object context, | 11 | object context, |
| 19 | filter queryFilter) : | 12 | filter queryFilter) : |
| 20 | statement(getTableForContext(context), queryFilter.compact().normalize(context)) | 13 | statement(context, getTableForContext(context), queryFilter.compact().normalize(context)) |
| 21 | { | 14 | { |
| 22 | } | 15 | } |
| 23 | 16 | ||
| @@ -104,24 +97,29 @@ namespace verbly { | |||
| 104 | queryStream << " WHERE "; | 97 | queryStream << " WHERE "; |
| 105 | queryStream << topCondition_.flatten().toSql(true, debug); | 98 | queryStream << topCondition_.flatten().toSql(true, debug); |
| 106 | } | 99 | } |
| 107 | 100 | ||
| 101 | queryStream << " GROUP BY "; | ||
| 102 | queryStream << topTable_; | ||
| 103 | queryStream << "."; | ||
| 104 | queryStream << select.front(); | ||
| 105 | |||
| 108 | queryStream << " ORDER BY "; | 106 | queryStream << " ORDER BY "; |
| 109 | 107 | ||
| 110 | switch (sortOrder.getType()) | 108 | switch (sortOrder.getType()) |
| 111 | { | 109 | { |
| 112 | case order::type::random: | 110 | case order::type::random: |
| 113 | { | 111 | { |
| 114 | queryStream << "RANDOM()"; | 112 | queryStream << "RANDOM()"; |
| 115 | 113 | ||
| 116 | break; | 114 | break; |
| 117 | } | 115 | } |
| 118 | 116 | ||
| 119 | case order::type::field: | 117 | case order::type::field: |
| 120 | { | 118 | { |
| 121 | queryStream << topTable_; | 119 | queryStream << topTable_; |
| 122 | queryStream << "."; | 120 | queryStream << "."; |
| 123 | queryStream << sortOrder.getSortField().getColumn(); | 121 | queryStream << sortOrder.getSortField().getColumn(); |
| 124 | 122 | ||
| 125 | break; | 123 | break; |
| 126 | } | 124 | } |
| 127 | } | 125 | } |
| @@ -156,10 +154,12 @@ namespace verbly { | |||
| 156 | } | 154 | } |
| 157 | 155 | ||
| 158 | statement::statement( | 156 | statement::statement( |
| 157 | object context, | ||
| 159 | std::string tableName, | 158 | std::string tableName, |
| 160 | filter clause, | 159 | filter clause, |
| 161 | int nextTableId, | 160 | int nextTableId, |
| 162 | int nextWithId) : | 161 | int nextWithId) : |
| 162 | context_(context), | ||
| 163 | nextTableId_(nextTableId), | 163 | nextTableId_(nextTableId), |
| 164 | nextWithId_(nextWithId), | 164 | nextWithId_(nextWithId), |
| 165 | topTable_(instantiateTable(std::move(tableName))), | 165 | topTable_(instantiateTable(std::move(tableName))), |
| @@ -266,6 +266,16 @@ namespace verbly { | |||
| 266 | return condition(topTable_, clause.getField().getColumn(), condition::comparison::is_not_like, clause.getStringArgument()); | 266 | return condition(topTable_, clause.getField().getColumn(), condition::comparison::is_not_like, clause.getStringArgument()); |
| 267 | } | 267 | } |
| 268 | 268 | ||
| 269 | case filter::comparison::field_equals: | ||
| 270 | { | ||
| 271 | return condition(topTable_, clause.getField().getColumn(), condition::comparison::equals, {"", clause.getCompareField().getColumn()}, clause.getCompareField().getObject()); | ||
| 272 | } | ||
| 273 | |||
| 274 | case filter::comparison::field_does_not_equal: | ||
| 275 | { | ||
| 276 | return condition(topTable_, clause.getField().getColumn(), condition::comparison::does_not_equal, {"", clause.getCompareField().getColumn()}, clause.getCompareField().getObject()); | ||
| 277 | } | ||
| 278 | |||
| 269 | case filter::comparison::matches: | 279 | case filter::comparison::matches: |
| 270 | case filter::comparison::does_not_match: | 280 | case filter::comparison::does_not_match: |
| 271 | case filter::comparison::hierarchally_matches: | 281 | case filter::comparison::hierarchally_matches: |
| @@ -281,26 +291,29 @@ namespace verbly { | |||
| 281 | { | 291 | { |
| 282 | // First, figure out what table we need to join against. | 292 | // First, figure out what table we need to join against. |
| 283 | std::string joinTableName; | 293 | std::string joinTableName; |
| 294 | object joinContext = object::undefined; | ||
| 284 | if (clause.getField().hasTable()) | 295 | if (clause.getField().hasTable()) |
| 285 | { | 296 | { |
| 286 | joinTableName = clause.getField().getTable(); | 297 | joinTableName = clause.getField().getTable(); |
| 287 | } else { | 298 | } else { |
| 288 | joinTableName = getTableForContext(clause.getField().getJoinObject()); | 299 | joinContext = clause.getField().getJoinObject(); |
| 300 | joinTableName = getTableForContext(joinContext); | ||
| 289 | } | 301 | } |
| 290 | 302 | ||
| 291 | filter joinCondition = clause.getJoinCondition(); | 303 | filter joinCondition = clause.getJoinCondition(); |
| 292 | 304 | ||
| 293 | // If this is a condition join, we need to add the field join | 305 | // If this is a condition join, we need to add the field join |
| 294 | // condition to the clause. | 306 | // condition to the clause. |
| 295 | if (clause.getField().getType() == field::type::join_where) | 307 | if (clause.getField().getType() == field::type::join_where) |
| 296 | { | 308 | { |
| 297 | joinCondition &= (clause.getField().getConditionField() == clause.getField().getConditionValue()); | 309 | joinCondition &= (field::integerField(joinTableName.c_str(), clause.getField().getConditionColumn()) == clause.getField().getConditionValue()); |
| 298 | } | 310 | } |
| 299 | 311 | ||
| 300 | // Recursively parse the subquery, and therefore obtain an | 312 | // Recursively parse the subquery, and therefore obtain an |
| 301 | // instantiated table to join against, as well as any joins or CTEs | 313 | // instantiated table to join against, as well as any joins or CTEs |
| 302 | // that the subquery may require to function. | 314 | // that the subquery may require to function. |
| 303 | statement joinStmt( | 315 | statement joinStmt( |
| 316 | joinContext, | ||
| 304 | joinTableName, | 317 | joinTableName, |
| 305 | std::move(joinCondition).normalize(clause.getField().getJoinObject()), | 318 | std::move(joinCondition).normalize(clause.getField().getJoinObject()), |
| 306 | nextTableId_, | 319 | nextTableId_, |
| @@ -368,11 +381,13 @@ namespace verbly { | |||
| 368 | } | 381 | } |
| 369 | 382 | ||
| 370 | case field::type::join_through: | 383 | case field::type::join_through: |
| 384 | case field::type::join_through_where: | ||
| 371 | { | 385 | { |
| 372 | // Recursively parse the subquery, and therefore obtain an | 386 | // Recursively parse the subquery, and therefore obtain an |
| 373 | // instantiated table to join against, as well as any joins or CTEs | 387 | // instantiated table to join against, as well as any joins or CTEs |
| 374 | // that the subquery may require to function. | 388 | // that the subquery may require to function. |
| 375 | statement joinStmt( | 389 | statement joinStmt( |
| 390 | clause.getField().getJoinObject(), | ||
| 376 | getTableForContext(clause.getField().getJoinObject()), | 391 | getTableForContext(clause.getField().getJoinObject()), |
| 377 | clause.getJoinCondition().normalize(clause.getField().getJoinObject()), | 392 | clause.getJoinCondition().normalize(clause.getField().getJoinObject()), |
| 378 | nextTableId_, | 393 | nextTableId_, |
| @@ -424,6 +439,17 @@ namespace verbly { | |||
| 424 | std::list<join> cteJoins = std::move(joinStmt.joins_); | 439 | std::list<join> cteJoins = std::move(joinStmt.joins_); |
| 425 | condition cteCondition = integrate(std::move(joinStmt), true); | 440 | condition cteCondition = integrate(std::move(joinStmt), true); |
| 426 | 441 | ||
| 442 | // If this is a condition join, add the condition. | ||
| 443 | if (clause.getField().getType() == field::type::join_through_where) | ||
| 444 | { | ||
| 445 | cteCondition &= | ||
| 446 | condition( | ||
| 447 | throughTable, | ||
| 448 | clause.getField().getConditionColumn(), | ||
| 449 | condition::comparison::equals, | ||
| 450 | clause.getField().getConditionValue()); | ||
| 451 | } | ||
| 452 | |||
| 427 | withs_.emplace_back( | 453 | withs_.emplace_back( |
| 428 | std::move(withName), | 454 | std::move(withName), |
| 429 | clause.getField(), | 455 | clause.getField(), |
| @@ -453,7 +479,7 @@ namespace verbly { | |||
| 453 | joins_.emplace_back( | 479 | joins_.emplace_back( |
| 454 | false, | 480 | false, |
| 455 | getTableForContext(clause.getField().getJoinObject()), | 481 | getTableForContext(clause.getField().getJoinObject()), |
| 456 | std::move(throughTable), | 482 | throughTable, |
| 457 | clause.getField().getForeignJoinColumn(), | 483 | clause.getField().getForeignJoinColumn(), |
| 458 | std::move(joinTable), | 484 | std::move(joinTable), |
| 459 | clause.getField().getForeignColumn()); | 485 | clause.getField().getForeignColumn()); |
| @@ -461,7 +487,20 @@ namespace verbly { | |||
| 461 | // Integrate the subquery's table mappings, joins, and CTEs into | 487 | // Integrate the subquery's table mappings, joins, and CTEs into |
| 462 | // this statement, and return the subquery condition as our | 488 | // this statement, and return the subquery condition as our |
| 463 | // condition. | 489 | // condition. |
| 464 | return integrate(std::move(joinStmt)); | 490 | condition resultCond = integrate(std::move(joinStmt)); |
| 491 | |||
| 492 | // If this is a condition join, add the condition. | ||
| 493 | if (clause.getField().getType() == field::type::join_through_where) | ||
| 494 | { | ||
| 495 | resultCond &= | ||
| 496 | condition( | ||
| 497 | throughTable, | ||
| 498 | clause.getField().getConditionColumn(), | ||
| 499 | condition::comparison::equals, | ||
| 500 | clause.getField().getConditionValue()); | ||
| 501 | } | ||
| 502 | |||
| 503 | return std::move(resultCond); | ||
| 465 | } | 504 | } |
| 466 | } | 505 | } |
| 467 | 506 | ||
| @@ -491,6 +530,7 @@ namespace verbly { | |||
| 491 | 530 | ||
| 492 | // Recursively parse the subquery in order to create the CTE. | 531 | // Recursively parse the subquery in order to create the CTE. |
| 493 | statement withStmt( | 532 | statement withStmt( |
| 533 | clause.getField().getObject(), | ||
| 494 | getTableForContext(clause.getField().getObject()), | 534 | getTableForContext(clause.getField().getObject()), |
| 495 | clause.getJoinCondition().normalize(clause.getField().getObject()), | 535 | clause.getJoinCondition().normalize(clause.getField().getObject()), |
| 496 | nextTableId_, | 536 | nextTableId_, |
| @@ -593,7 +633,7 @@ namespace verbly { | |||
| 593 | nextTableId_ = subStmt.nextTableId_; | 633 | nextTableId_ = subStmt.nextTableId_; |
| 594 | nextWithId_ = subStmt.nextWithId_; | 634 | nextWithId_ = subStmt.nextWithId_; |
| 595 | 635 | ||
| 596 | return subStmt.topCondition_; | 636 | return subStmt.topCondition_.resolveCompareFields(context_, topTable_); |
| 597 | } | 637 | } |
| 598 | 638 | ||
| 599 | std::ostream& operator<<(std::ostream& oss, const statement::join& j) | 639 | std::ostream& operator<<(std::ostream& oss, const statement::join& j) |
| @@ -637,6 +677,7 @@ namespace verbly { | |||
| 637 | new(&singleton_.column_) std::string(other.singleton_.column_); | 677 | new(&singleton_.column_) std::string(other.singleton_.column_); |
| 638 | singleton_.comparison_ = other.singleton_.comparison_; | 678 | singleton_.comparison_ = other.singleton_.comparison_; |
| 639 | new(&singleton_.value_) binding(other.singleton_.value_); | 679 | new(&singleton_.value_) binding(other.singleton_.value_); |
| 680 | singleton_.parentObject_ = other.singleton_.parentObject_; | ||
| 640 | 681 | ||
| 641 | break; | 682 | break; |
| 642 | } | 683 | } |
| @@ -673,6 +714,7 @@ namespace verbly { | |||
| 673 | std::string tempColumn; | 714 | std::string tempColumn; |
| 674 | condition::comparison tempComparison; | 715 | condition::comparison tempComparison; |
| 675 | binding tempBinding; | 716 | binding tempBinding; |
| 717 | object tempParentObject; | ||
| 676 | std::list<condition> tempChildren; | 718 | std::list<condition> tempChildren; |
| 677 | bool tempOrlogic; | 719 | bool tempOrlogic; |
| 678 | 720 | ||
| @@ -689,6 +731,7 @@ namespace verbly { | |||
| 689 | tempColumn = std::move(first.singleton_.column_); | 731 | tempColumn = std::move(first.singleton_.column_); |
| 690 | tempComparison = first.singleton_.comparison_; | 732 | tempComparison = first.singleton_.comparison_; |
| 691 | tempBinding = std::move(first.singleton_.value_); | 733 | tempBinding = std::move(first.singleton_.value_); |
| 734 | tempParentObject = first.singleton_.parentObject_; | ||
| 692 | 735 | ||
| 693 | break; | 736 | break; |
| 694 | } | 737 | } |
| @@ -719,6 +762,7 @@ namespace verbly { | |||
| 719 | new(&first.singleton_.column_) std::string(std::move(second.singleton_.column_)); | 762 | new(&first.singleton_.column_) std::string(std::move(second.singleton_.column_)); |
| 720 | first.singleton_.comparison_ = second.singleton_.comparison_; | 763 | first.singleton_.comparison_ = second.singleton_.comparison_; |
| 721 | new(&first.singleton_.value_) binding(std::move(second.singleton_.value_)); | 764 | new(&first.singleton_.value_) binding(std::move(second.singleton_.value_)); |
| 765 | first.singleton_.parentObject_ = second.singleton_.parentObject_; | ||
| 722 | 766 | ||
| 723 | break; | 767 | break; |
| 724 | } | 768 | } |
| @@ -749,6 +793,7 @@ namespace verbly { | |||
| 749 | new(&second.singleton_.column_) std::string(std::move(tempColumn)); | 793 | new(&second.singleton_.column_) std::string(std::move(tempColumn)); |
| 750 | second.singleton_.comparison_ = tempComparison; | 794 | second.singleton_.comparison_ = tempComparison; |
| 751 | new(&second.singleton_.value_) binding(std::move(tempBinding)); | 795 | new(&second.singleton_.value_) binding(std::move(tempBinding)); |
| 796 | second.singleton_.parentObject_ = tempParentObject; | ||
| 752 | 797 | ||
| 753 | break; | 798 | break; |
| 754 | } | 799 | } |
| @@ -813,19 +858,23 @@ namespace verbly { | |||
| 813 | } else { | 858 | } else { |
| 814 | singleton_.comparison_ = comparison::is_not_null; | 859 | singleton_.comparison_ = comparison::is_not_null; |
| 815 | } | 860 | } |
| 861 | |||
| 862 | singleton_.parentObject_ = object::undefined; | ||
| 816 | } | 863 | } |
| 817 | 864 | ||
| 818 | statement::condition::condition( | 865 | statement::condition::condition( |
| 819 | std::string table, | 866 | std::string table, |
| 820 | std::string column, | 867 | std::string column, |
| 821 | comparison comp, | 868 | comparison comp, |
| 822 | binding value) : | 869 | binding value, |
| 870 | object parentObject) : | ||
| 823 | type_(type::singleton) | 871 | type_(type::singleton) |
| 824 | { | 872 | { |
| 825 | new(&singleton_.table_) std::string(std::move(table)); | 873 | new(&singleton_.table_) std::string(std::move(table)); |
| 826 | new(&singleton_.column_) std::string(std::move(column)); | 874 | new(&singleton_.column_) std::string(std::move(column)); |
| 827 | singleton_.comparison_ = comp; | 875 | singleton_.comparison_ = comp; |
| 828 | new(&singleton_.value_) binding(std::move(value)); | 876 | new(&singleton_.value_) binding(std::move(value)); |
| 877 | singleton_.parentObject_ = parentObject; | ||
| 829 | } | 878 | } |
| 830 | 879 | ||
| 831 | std::string statement::condition::toSql(bool toplevel, bool debug) const | 880 | std::string statement::condition::toSql(bool toplevel, bool debug) const |
| @@ -845,14 +894,35 @@ namespace verbly { | |||
| 845 | { | 894 | { |
| 846 | if (debug) | 895 | if (debug) |
| 847 | { | 896 | { |
| 848 | if (singleton_.value_.getType() == binding::type::string) | 897 | switch (singleton_.value_.getType()) |
| 849 | { | 898 | { |
| 850 | return singleton_.table_ + "." + singleton_.column_ + " = \"" + singleton_.value_.getString() + "\""; | 899 | case binding::type::string: |
| 851 | } else { | 900 | { |
| 852 | return singleton_.table_ + "." + singleton_.column_ + " = " + std::to_string(singleton_.value_.getInteger()); | 901 | return singleton_.table_ + "." + singleton_.column_ + " = \"" + singleton_.value_.getString() + "\""; |
| 902 | } | ||
| 903 | |||
| 904 | case binding::type::integer: | ||
| 905 | { | ||
| 906 | return singleton_.table_ + "." + singleton_.column_ + " = " + std::to_string(singleton_.value_.getInteger()); | ||
| 907 | } | ||
| 908 | |||
| 909 | case binding::type::field: | ||
| 910 | { | ||
| 911 | return singleton_.table_ + "." + singleton_.column_ + " = " + singleton_.value_.getTable() + "." + singleton_.value_.getColumn(); | ||
| 912 | } | ||
| 913 | |||
| 914 | case binding::type::invalid: | ||
| 915 | { | ||
| 916 | throw std::logic_error("Invalid binding in statement generation"); | ||
| 917 | } | ||
| 853 | } | 918 | } |
| 854 | } else { | 919 | } else { |
| 855 | return singleton_.table_ + "." + singleton_.column_ + " = ?"; | 920 | if (singleton_.value_.getType() == binding::type::field) |
| 921 | { | ||
| 922 | return singleton_.table_ + "." + singleton_.column_ + " = " + singleton_.value_.getTable() + "." + singleton_.value_.getColumn(); | ||
| 923 | } else { | ||
| 924 | return singleton_.table_ + "." + singleton_.column_ + " = ?"; | ||
| 925 | } | ||
| 856 | } | 926 | } |
| 857 | } | 927 | } |
| 858 | 928 | ||
| @@ -860,14 +930,35 @@ namespace verbly { | |||
| 860 | { | 930 | { |
| 861 | if (debug) | 931 | if (debug) |
| 862 | { | 932 | { |
| 863 | if (singleton_.value_.getType() == binding::type::string) | 933 | switch (singleton_.value_.getType()) |
| 864 | { | 934 | { |
| 865 | return singleton_.table_ + "." + singleton_.column_ + " != \"" + singleton_.value_.getString() + "\""; | 935 | case binding::type::string: |
| 866 | } else { | 936 | { |
| 867 | return singleton_.table_ + "." + singleton_.column_ + " != " + std::to_string(singleton_.value_.getInteger()); | 937 | return singleton_.table_ + "." + singleton_.column_ + " != \"" + singleton_.value_.getString() + "\""; |
| 938 | } | ||
| 939 | |||
| 940 | case binding::type::integer: | ||
| 941 | { | ||
| 942 | return singleton_.table_ + "." + singleton_.column_ + " != " + std::to_string(singleton_.value_.getInteger()); | ||
| 943 | } | ||
| 944 | |||
| 945 | case binding::type::field: | ||
| 946 | { | ||
| 947 | return singleton_.table_ + "." + singleton_.column_ + " != " + singleton_.value_.getTable() + "." + singleton_.value_.getColumn(); | ||
| 948 | } | ||
| 949 | |||
| 950 | case binding::type::invalid: | ||
| 951 | { | ||
| 952 | throw std::logic_error("Invalid binding in statement generation"); | ||
| 953 | } | ||
| 868 | } | 954 | } |
| 869 | } else { | 955 | } else { |
| 870 | return singleton_.table_ + "." + singleton_.column_ + " != ?"; | 956 | if (singleton_.value_.getType() == binding::type::field) |
| 957 | { | ||
| 958 | return singleton_.table_ + "." + singleton_.column_ + " != " + singleton_.value_.getTable() + "." + singleton_.value_.getColumn(); | ||
| 959 | } else { | ||
| 960 | return singleton_.table_ + "." + singleton_.column_ + " != ?"; | ||
| 961 | } | ||
| 871 | } | 962 | } |
| 872 | } | 963 | } |
| 873 | 964 | ||
| @@ -959,7 +1050,7 @@ namespace verbly { | |||
| 959 | return clauses.front(); | 1050 | return clauses.front(); |
| 960 | } else { | 1051 | } else { |
| 961 | std::string result = implode(std::begin(clauses), std::end(clauses), group_.orlogic_ ? " OR " : " AND "); | 1052 | std::string result = implode(std::begin(clauses), std::end(clauses), group_.orlogic_ ? " OR " : " AND "); |
| 962 | 1053 | ||
| 963 | if (toplevel) | 1054 | if (toplevel) |
| 964 | { | 1055 | { |
| 965 | return result; | 1056 | return result; |
| @@ -982,24 +1073,29 @@ namespace verbly { | |||
| 982 | 1073 | ||
| 983 | case type::singleton: | 1074 | case type::singleton: |
| 984 | { | 1075 | { |
| 985 | switch (singleton_.comparison_) | 1076 | if (singleton_.value_.getType() == binding::type::field) |
| 986 | { | 1077 | { |
| 987 | case comparison::equals: | 1078 | return {}; |
| 988 | case comparison::does_not_equal: | 1079 | } else { |
| 989 | case comparison::is_greater_than: | 1080 | switch (singleton_.comparison_) |
| 990 | case comparison::is_at_most: | ||
| 991 | case comparison::is_less_than: | ||
| 992 | case comparison::is_at_least: | ||
| 993 | case comparison::is_like: | ||
| 994 | case comparison::is_not_like: | ||
| 995 | { | 1081 | { |
| 996 | return {singleton_.value_}; | 1082 | case comparison::equals: |
| 997 | } | 1083 | case comparison::does_not_equal: |
| 1084 | case comparison::is_greater_than: | ||
| 1085 | case comparison::is_at_most: | ||
| 1086 | case comparison::is_less_than: | ||
| 1087 | case comparison::is_at_least: | ||
| 1088 | case comparison::is_like: | ||
| 1089 | case comparison::is_not_like: | ||
| 1090 | { | ||
| 1091 | return {singleton_.value_}; | ||
| 1092 | } | ||
| 998 | 1093 | ||
| 999 | case comparison::is_not_null: | 1094 | case comparison::is_not_null: |
| 1000 | case comparison::is_null: | 1095 | case comparison::is_null: |
| 1001 | { | 1096 | { |
| 1002 | return {}; | 1097 | return {}; |
| 1098 | } | ||
| 1003 | } | 1099 | } |
| 1004 | } | 1100 | } |
| 1005 | } | 1101 | } |
| @@ -1080,7 +1176,7 @@ namespace verbly { | |||
| 1080 | throw std::domain_error("Cannot get children of non-group condition"); | 1176 | throw std::domain_error("Cannot get children of non-group condition"); |
| 1081 | } | 1177 | } |
| 1082 | } | 1178 | } |
| 1083 | 1179 | ||
| 1084 | statement::condition statement::condition::flatten() const | 1180 | statement::condition statement::condition::flatten() const |
| 1085 | { | 1181 | { |
| 1086 | switch (type_) | 1182 | switch (type_) |
| @@ -1090,15 +1186,15 @@ namespace verbly { | |||
| 1090 | { | 1186 | { |
| 1091 | return *this; | 1187 | return *this; |
| 1092 | } | 1188 | } |
| 1093 | 1189 | ||
| 1094 | case type::group: | 1190 | case type::group: |
| 1095 | { | 1191 | { |
| 1096 | condition result(group_.orlogic_); | 1192 | condition result(group_.orlogic_); |
| 1097 | 1193 | ||
| 1098 | for (const condition& child : group_.children_) | 1194 | for (const condition& child : group_.children_) |
| 1099 | { | 1195 | { |
| 1100 | condition newChild = child.flatten(); | 1196 | condition newChild = child.flatten(); |
| 1101 | 1197 | ||
| 1102 | if ((newChild.type_ == type::group) && (newChild.group_.orlogic_ == group_.orlogic_)) | 1198 | if ((newChild.type_ == type::group) && (newChild.group_.orlogic_ == group_.orlogic_)) |
| 1103 | { | 1199 | { |
| 1104 | for (condition subChild : std::move(newChild.group_.children_)) | 1200 | for (condition subChild : std::move(newChild.group_.children_)) |
| @@ -1109,7 +1205,39 @@ namespace verbly { | |||
| 1109 | result += std::move(newChild); | 1205 | result += std::move(newChild); |
| 1110 | } | 1206 | } |
| 1111 | } | 1207 | } |
| 1112 | 1208 | ||
| 1209 | return result; | ||
| 1210 | } | ||
| 1211 | } | ||
| 1212 | } | ||
| 1213 | |||
| 1214 | statement::condition statement::condition::resolveCompareFields(object context, std::string tableName) const | ||
| 1215 | { | ||
| 1216 | switch (type_) | ||
| 1217 | { | ||
| 1218 | case type::empty: | ||
| 1219 | { | ||
| 1220 | return *this; | ||
| 1221 | } | ||
| 1222 | |||
| 1223 | case type::singleton: | ||
| 1224 | { | ||
| 1225 | if ((singleton_.parentObject_ != object::undefined) && (singleton_.parentObject_ == context)) | ||
| 1226 | { | ||
| 1227 | return condition(singleton_.table_, singleton_.column_, singleton_.comparison_, {tableName, singleton_.value_.getColumn()}); | ||
| 1228 | } else { | ||
| 1229 | return *this; | ||
| 1230 | } | ||
| 1231 | } | ||
| 1232 | |||
| 1233 | case type::group: | ||
| 1234 | { | ||
| 1235 | condition result(group_.orlogic_); | ||
| 1236 | for (const condition& cond : group_.children_) | ||
| 1237 | { | ||
| 1238 | result += cond.resolveCompareFields(context, tableName); | ||
| 1239 | } | ||
| 1240 | |||
| 1113 | return result; | 1241 | return result; |
| 1114 | } | 1242 | } |
| 1115 | } | 1243 | } |
