summary refs log tree commit diff stats
path: root/lib/statement.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/statement.cpp')
-rw-r--r--lib/statement.cpp621
1 files changed, 268 insertions, 353 deletions
diff --git a/lib/statement.cpp b/lib/statement.cpp index ac83084..669dc2a 100644 --- a/lib/statement.cpp +++ b/lib/statement.cpp
@@ -133,19 +133,19 @@ namespace verbly {
133 return queryStream.str(); 133 return queryStream.str();
134 } 134 }
135 135
136 std::list<binding> statement::getBindings() const 136 std::list<hatkirby::binding> statement::getBindings() const
137 { 137 {
138 std::list<binding> result; 138 std::list<hatkirby::binding> result;
139 139
140 for (const with& w : withs_) 140 for (const with& w : withs_)
141 { 141 {
142 for (binding value : w.getCondition().flattenBindings()) 142 for (hatkirby::binding value : w.getCondition().flattenBindings())
143 { 143 {
144 result.push_back(std::move(value)); 144 result.push_back(std::move(value));
145 } 145 }
146 } 146 }
147 147
148 for (binding value : topCondition_.flattenBindings()) 148 for (hatkirby::binding value : topCondition_.flattenBindings())
149 { 149 {
150 result.push_back(std::move(value)); 150 result.push_back(std::move(value));
151 } 151 }
@@ -203,77 +203,152 @@ namespace verbly {
203 { 203 {
204 case filter::comparison::is_null: 204 case filter::comparison::is_null:
205 { 205 {
206 return condition(topTable_, clause.getField().getColumn(), true); 206 return {
207 topTable_,
208 clause.getField().getColumn(),
209 true
210 };
207 } 211 }
208 212
209 case filter::comparison::is_not_null: 213 case filter::comparison::is_not_null:
210 { 214 {
211 return condition(topTable_, clause.getField().getColumn(), false); 215 return {
216 topTable_,
217 clause.getField().getColumn(),
218 false
219 };
212 } 220 }
213 221
214 case filter::comparison::int_equals: 222 case filter::comparison::int_equals:
215 { 223 {
216 return condition(topTable_, clause.getField().getColumn(), condition::comparison::equals, clause.getIntegerArgument()); 224 return {
225 topTable_,
226 clause.getField().getColumn(),
227 condition::comparison::equals,
228 clause.getIntegerArgument()
229 };
217 } 230 }
218 231
219 case filter::comparison::int_does_not_equal: 232 case filter::comparison::int_does_not_equal:
220 { 233 {
221 return condition(topTable_, clause.getField().getColumn(), condition::comparison::does_not_equal, clause.getIntegerArgument()); 234 return {
235 topTable_,
236 clause.getField().getColumn(),
237 condition::comparison::does_not_equal,
238 clause.getIntegerArgument()
239 };
222 } 240 }
223 241
224 case filter::comparison::int_is_at_least: 242 case filter::comparison::int_is_at_least:
225 { 243 {
226 return condition(topTable_, clause.getField().getColumn(), condition::comparison::is_at_least, clause.getIntegerArgument()); 244 return {
245 topTable_,
246 clause.getField().getColumn(),
247 condition::comparison::is_at_least,
248 clause.getIntegerArgument()
249 };
227 } 250 }
228 251
229 case filter::comparison::int_is_greater_than: 252 case filter::comparison::int_is_greater_than:
230 { 253 {
231 return condition(topTable_, clause.getField().getColumn(), condition::comparison::is_greater_than, clause.getIntegerArgument()); 254 return {
255 topTable_,
256 clause.getField().getColumn(),
257 condition::comparison::is_greater_than,
258 clause.getIntegerArgument()
259 };
232 } 260 }
233 261
234 case filter::comparison::int_is_at_most: 262 case filter::comparison::int_is_at_most:
235 { 263 {
236 return condition(topTable_, clause.getField().getColumn(), condition::comparison::is_at_most, clause.getIntegerArgument()); 264 return {
265 topTable_,
266 clause.getField().getColumn(),
267 condition::comparison::is_at_most,
268 clause.getIntegerArgument()
269 };
237 } 270 }
238 271
239 case filter::comparison::int_is_less_than: 272 case filter::comparison::int_is_less_than:
240 { 273 {
241 return condition(topTable_, clause.getField().getColumn(), condition::comparison::is_less_than, clause.getIntegerArgument()); 274 return {
275 topTable_,
276 clause.getField().getColumn(),
277 condition::comparison::is_less_than,
278 clause.getIntegerArgument()
279 };
242 } 280 }
243 281
244 case filter::comparison::boolean_equals: 282 case filter::comparison::boolean_equals:
245 { 283 {
246 return condition(topTable_, clause.getField().getColumn(), condition::comparison::equals, clause.getBooleanArgument() ? 1 : 0); 284 return {
285 topTable_,
286 clause.getField().getColumn(),
287 condition::comparison::equals,
288 clause.getBooleanArgument() ? 1 : 0
289 };
247 } 290 }
248 291
249 case filter::comparison::string_equals: 292 case filter::comparison::string_equals:
250 { 293 {
251 return condition(topTable_, clause.getField().getColumn(), condition::comparison::equals, clause.getStringArgument()); 294 return {
295 topTable_,
296 clause.getField().getColumn(),
297 condition::comparison::equals,
298 clause.getStringArgument()
299 };
252 } 300 }
253 301
254 case filter::comparison::string_does_not_equal: 302 case filter::comparison::string_does_not_equal:
255 { 303 {
256 return condition(topTable_, clause.getField().getColumn(), condition::comparison::does_not_equal, clause.getStringArgument()); 304 return {
305 topTable_,
306 clause.getField().getColumn(),
307 condition::comparison::does_not_equal,
308 clause.getStringArgument()
309 };
257 } 310 }
258 311
259 case filter::comparison::string_is_like: 312 case filter::comparison::string_is_like:
260 { 313 {
261 return condition(topTable_, clause.getField().getColumn(), condition::comparison::is_like, clause.getStringArgument()); 314 return {
315 topTable_,
316 clause.getField().getColumn(),
317 condition::comparison::is_like,
318 clause.getStringArgument()
319 };
262 } 320 }
263 321
264 case filter::comparison::string_is_not_like: 322 case filter::comparison::string_is_not_like:
265 { 323 {
266 return condition(topTable_, clause.getField().getColumn(), condition::comparison::is_not_like, clause.getStringArgument()); 324 return {
325 topTable_,
326 clause.getField().getColumn(),
327 condition::comparison::is_not_like,
328 clause.getStringArgument()
329 };
267 } 330 }
268 331
269 case filter::comparison::field_equals: 332 case filter::comparison::field_equals:
270 { 333 {
271 return condition(topTable_, clause.getField().getColumn(), condition::comparison::equals, {"", clause.getCompareField().getColumn()}, clause.getCompareField().getObject()); 334 return {
335 topTable_,
336 clause.getField().getColumn(),
337 condition::comparison::equals,
338 field_binding {"", clause.getCompareField().getColumn()},
339 clause.getCompareField().getObject()
340 };
272 } 341 }
273 342
274 case filter::comparison::field_does_not_equal: 343 case filter::comparison::field_does_not_equal:
275 { 344 {
276 return condition(topTable_, clause.getField().getColumn(), condition::comparison::does_not_equal, {"", clause.getCompareField().getColumn()}, clause.getCompareField().getObject()); 345 return {
346 topTable_,
347 clause.getField().getColumn(),
348 condition::comparison::does_not_equal,
349 field_binding {"", clause.getCompareField().getColumn()},
350 clause.getCompareField().getObject()
351 };
277 } 352 }
278 353
279 case filter::comparison::matches: 354 case filter::comparison::matches:
@@ -680,206 +755,19 @@ namespace verbly {
680 << j.getJoinColumn(); 755 << j.getJoinColumn();
681 } 756 }
682 757
683 statement::condition::condition(const condition& other)
684 {
685 type_ = other.type_;
686
687 switch (type_)
688 {
689 case type::empty:
690 {
691 break;
692 }
693
694 case type::singleton:
695 {
696 new(&singleton_.table_) std::string(other.singleton_.table_);
697 new(&singleton_.column_) std::string(other.singleton_.column_);
698 singleton_.comparison_ = other.singleton_.comparison_;
699 new(&singleton_.value_) binding(other.singleton_.value_);
700 singleton_.parentObject_ = other.singleton_.parentObject_;
701
702 break;
703 }
704
705 case type::group:
706 {
707 new(&group_.children_) std::list<condition>(other.group_.children_);
708 group_.orlogic_ = other.group_.orlogic_;
709
710 break;
711 }
712 }
713 }
714
715 statement::condition::condition(condition&& other) : condition()
716 {
717 swap(*this, other);
718 }
719
720 statement::condition& statement::condition::operator=(condition other)
721 {
722 swap(*this, other);
723
724 return *this;
725 }
726
727 void swap(statement::condition& first, statement::condition& second)
728 {
729 using type = statement::condition::type;
730 using condition = statement::condition;
731
732 type tempType = first.type_;
733 std::string tempTable;
734 std::string tempColumn;
735 condition::comparison tempComparison;
736 binding tempBinding;
737 object tempParentObject;
738 std::list<condition> tempChildren;
739 bool tempOrlogic;
740
741 switch (tempType)
742 {
743 case type::empty:
744 {
745 break;
746 }
747
748 case type::singleton:
749 {
750 tempTable = std::move(first.singleton_.table_);
751 tempColumn = std::move(first.singleton_.column_);
752 tempComparison = first.singleton_.comparison_;
753 tempBinding = std::move(first.singleton_.value_);
754 tempParentObject = first.singleton_.parentObject_;
755
756 break;
757 }
758
759 case type::group:
760 {
761 tempChildren = std::move(first.group_.children_);
762 tempOrlogic = first.group_.orlogic_;
763
764 break;
765 }
766 }
767
768 first.~condition();
769
770 first.type_ = second.type_;
771
772 switch (first.type_)
773 {
774 case type::empty:
775 {
776 break;
777 }
778
779 case type::singleton:
780 {
781 new(&first.singleton_.table_) std::string(std::move(second.singleton_.table_));
782 new(&first.singleton_.column_) std::string(std::move(second.singleton_.column_));
783 first.singleton_.comparison_ = second.singleton_.comparison_;
784 new(&first.singleton_.value_) binding(std::move(second.singleton_.value_));
785 first.singleton_.parentObject_ = second.singleton_.parentObject_;
786
787 break;
788 }
789
790 case type::group:
791 {
792 new(&first.group_.children_) std::list<condition>(std::move(second.group_.children_));
793 first.group_.orlogic_ = second.group_.orlogic_;
794
795 break;
796 }
797 }
798
799 second.~condition();
800
801 second.type_ = tempType;
802
803 switch (second.type_)
804 {
805 case type::empty:
806 {
807 break;
808 }
809
810 case type::singleton:
811 {
812 new(&second.singleton_.table_) std::string(std::move(tempTable));
813 new(&second.singleton_.column_) std::string(std::move(tempColumn));
814 second.singleton_.comparison_ = tempComparison;
815 new(&second.singleton_.value_) binding(std::move(tempBinding));
816 second.singleton_.parentObject_ = tempParentObject;
817
818 break;
819 }
820
821 case type::group:
822 {
823 new(&second.group_.children_) std::list<condition>(std::move(tempChildren));
824 second.group_.orlogic_ = tempOrlogic;
825
826 break;
827 }
828 }
829 }
830
831 statement::condition::~condition()
832 {
833 switch (type_)
834 {
835 case type::empty:
836 {
837 break;
838 }
839
840 case type::singleton:
841 {
842 using string_type = std::string;
843
844 singleton_.table_.~string_type();
845 singleton_.column_.~string_type();
846 singleton_.value_.~binding();
847
848 break;
849 }
850
851 case type::group:
852 {
853 using list_type = std::list<condition>;
854
855 group_.children_.~list_type();
856
857 break;
858 }
859 }
860 }
861
862 statement::condition::condition() : type_(type::empty)
863 {
864 }
865
866 statement::condition::condition( 758 statement::condition::condition(
867 std::string table, 759 std::string table,
868 std::string column, 760 std::string column,
869 bool isNull) : 761 bool isNull) :
870 type_(type::singleton) 762 type_(type::singleton),
763 variant_(singleton_type {
764 std::move(table),
765 std::move(column),
766 isNull ? comparison::is_null : comparison::is_not_null,
767 {},
768 object::undefined
769 })
871 { 770 {
872 new(&singleton_.table_) std::string(std::move(table));
873 new(&singleton_.column_) std::string(std::move(column));
874
875 if (isNull)
876 {
877 singleton_.comparison_ = comparison::is_null;
878 } else {
879 singleton_.comparison_ = comparison::is_not_null;
880 }
881
882 singleton_.parentObject_ = object::undefined;
883 } 771 }
884 772
885 statement::condition::condition( 773 statement::condition::condition(
@@ -888,201 +776,210 @@ namespace verbly {
888 comparison comp, 776 comparison comp,
889 binding value, 777 binding value,
890 object parentObject) : 778 object parentObject) :
891 type_(type::singleton) 779 type_(type::singleton),
780 variant_(singleton_type {
781 std::move(table),
782 std::move(column),
783 comp,
784 std::move(value),
785 parentObject
786 })
892 { 787 {
893 new(&singleton_.table_) std::string(std::move(table));
894 new(&singleton_.column_) std::string(std::move(column));
895 singleton_.comparison_ = comp;
896 new(&singleton_.value_) binding(std::move(value));
897 singleton_.parentObject_ = parentObject;
898 } 788 }
899 789
900 std::string statement::condition::toSql(bool toplevel, bool debug) const 790 std::string statement::condition::toSql(bool toplevel, bool debug) const
901 { 791 {
792 std::ostringstream sql;
793
902 switch (type_) 794 switch (type_)
903 { 795 {
904 case type::empty: 796 case type::empty:
905 { 797 {
906 return ""; 798 break;
907 } 799 }
908 800
909 case type::singleton: 801 case type::singleton:
910 { 802 {
911 switch (singleton_.comparison_) 803 const singleton_type& singleton = mpark::get<singleton_type>(variant_);
804
805 sql << singleton.table << "." << singleton.column;
806
807 switch (singleton.comparison)
912 { 808 {
913 case comparison::equals: 809 case comparison::equals:
810 case comparison::does_not_equal:
914 { 811 {
915 if (debug) 812 if (singleton.comparison == comparison::equals)
916 { 813 {
917 switch (singleton_.value_.getType()) 814 sql << " = ";
918 {
919 case binding::type::string:
920 {
921 return singleton_.table_ + "." + singleton_.column_ + " = \"" + singleton_.value_.getString() + "\"";
922 }
923
924 case binding::type::integer:
925 {
926 return singleton_.table_ + "." + singleton_.column_ + " = " + std::to_string(singleton_.value_.getInteger());
927 }
928
929 case binding::type::field:
930 {
931 return singleton_.table_ + "." + singleton_.column_ + " = " + singleton_.value_.getTable() + "." + singleton_.value_.getColumn();
932 }
933
934 case binding::type::invalid:
935 {
936 throw std::logic_error("Invalid binding in statement generation");
937 }
938 }
939 } else { 815 } else {
940 if (singleton_.value_.getType() == binding::type::field) 816 sql << " != ";
941 {
942 return singleton_.table_ + "." + singleton_.column_ + " = " + singleton_.value_.getTable() + "." + singleton_.value_.getColumn();
943 } else {
944 return singleton_.table_ + "." + singleton_.column_ + " = ?";
945 }
946 } 817 }
947 }
948 818
949 case comparison::does_not_equal: 819 if (mpark::holds_alternative<field_binding>(singleton.value))
950 { 820 {
951 if (debug) 821 sql << std::get<0>(mpark::get<field_binding>(singleton.value))
822 << "."
823 << std::get<1>(mpark::get<field_binding>(singleton.value));
824 } else if (debug)
952 { 825 {
953 switch (singleton_.value_.getType()) 826 if (mpark::holds_alternative<std::string>(singleton.value))
954 { 827 {
955 case binding::type::string: 828 sql << "\"" << mpark::get<std::string>(singleton.value) << "\"";
956 {
957 return singleton_.table_ + "." + singleton_.column_ + " != \"" + singleton_.value_.getString() + "\"";
958 }
959
960 case binding::type::integer:
961 {
962 return singleton_.table_ + "." + singleton_.column_ + " != " + std::to_string(singleton_.value_.getInteger());
963 }
964
965 case binding::type::field:
966 {
967 return singleton_.table_ + "." + singleton_.column_ + " != " + singleton_.value_.getTable() + "." + singleton_.value_.getColumn();
968 }
969
970 case binding::type::invalid:
971 {
972 throw std::logic_error("Invalid binding in statement generation");
973 }
974 } 829 }
975 } else { 830 else if (mpark::holds_alternative<int>(singleton.value))
976 if (singleton_.value_.getType() == binding::type::field)
977 { 831 {
978 return singleton_.table_ + "." + singleton_.column_ + " != " + singleton_.value_.getTable() + "." + singleton_.value_.getColumn(); 832 sql << mpark::get<int>(singleton.value);
979 } else {
980 return singleton_.table_ + "." + singleton_.column_ + " != ?";
981 } 833 }
834 } else {
835 sql << "?";
982 } 836 }
837
838 break;
983 } 839 }
984 840
985 case comparison::is_greater_than: 841 case comparison::is_greater_than:
986 { 842 {
843 sql << " > ";
844
987 if (debug) 845 if (debug)
988 { 846 {
989 return singleton_.table_ + "." + singleton_.column_ + " > " + std::to_string(singleton_.value_.getInteger()); 847 sql << mpark::get<int>(singleton.value);
990 } else { 848 } else {
991 return singleton_.table_ + "." + singleton_.column_ + " > ?"; 849 sql << "?";
992 } 850 }
851
852 break;
993 } 853 }
994 854
995 case comparison::is_at_most: 855 case comparison::is_at_most:
996 { 856 {
857 sql << " <= ";
858
997 if (debug) 859 if (debug)
998 { 860 {
999 return singleton_.table_ + "." + singleton_.column_ + " <= " + std::to_string(singleton_.value_.getInteger()); 861 sql << mpark::get<int>(singleton.value);
1000 } else { 862 } else {
1001 return singleton_.table_ + "." + singleton_.column_ + " <= ?"; 863 sql << "?";
1002 } 864 }
865
866 break;
1003 } 867 }
1004 868
1005 case comparison::is_less_than: 869 case comparison::is_less_than:
1006 { 870 {
871 sql << " < ";
872
1007 if (debug) 873 if (debug)
1008 { 874 {
1009 return singleton_.table_ + "." + singleton_.column_ + " < " + std::to_string(singleton_.value_.getInteger()); 875 sql << mpark::get<int>(singleton.value);
1010 } else { 876 } else {
1011 return singleton_.table_ + "." + singleton_.column_ + " < ?"; 877 sql << "?";
1012 } 878 }
879
880 break;
1013 } 881 }
1014 882
1015 case comparison::is_at_least: 883 case comparison::is_at_least:
1016 { 884 {
885 sql << " >= ";
886
1017 if (debug) 887 if (debug)
1018 { 888 {
1019 return singleton_.table_ + "." + singleton_.column_ + " >= " + std::to_string(singleton_.value_.getInteger()); 889 sql << mpark::get<int>(singleton.value);
1020 } else { 890 } else {
1021 return singleton_.table_ + "." + singleton_.column_ + " >= ?"; 891 sql << "?";
1022 } 892 }
893
894 break;
1023 } 895 }
1024 896
1025 case comparison::is_like: 897 case comparison::is_like:
1026 { 898 {
899 sql << " LIKE ";
900
1027 if (debug) 901 if (debug)
1028 { 902 {
1029 return singleton_.table_ + "." + singleton_.column_ + " LIKE \"" + singleton_.value_.getString() + "\""; 903 sql << "\"" << mpark::get<std::string>(singleton.value) << "\"";
1030 } else { 904 } else {
1031 return singleton_.table_ + "." + singleton_.column_ + " LIKE ?"; 905 sql << "?";
1032 } 906 }
907
908 break;
1033 } 909 }
1034 910
1035 case comparison::is_not_like: 911 case comparison::is_not_like:
1036 { 912 {
913 sql << " NOT LIKE ";
914
1037 if (debug) 915 if (debug)
1038 { 916 {
1039 return singleton_.table_ + "." + singleton_.column_ + " NOT LIKE \"" + singleton_.value_.getString() + "\""; 917 sql << "\"" << mpark::get<std::string>(singleton.value) << "\"";
1040 } else { 918 } else {
1041 return singleton_.table_ + "." + singleton_.column_ + " NOT LIKE ?"; 919 sql << "?";
1042 } 920 }
921
922 break;
1043 } 923 }
1044 924
1045 case comparison::is_not_null: 925 case comparison::is_not_null:
1046 { 926 {
1047 return singleton_.table_ + "." + singleton_.column_ + " IS NOT NULL"; 927 sql << " IS NOT NULL";
928
929 break;
1048 } 930 }
1049 931
1050 case comparison::is_null: 932 case comparison::is_null:
1051 { 933 {
1052 return singleton_.table_ + "." + singleton_.column_ + " IS NULL"; 934 sql << " IS NULL";
935
936 break;
1053 } 937 }
1054 } 938 }
939
940 break;
1055 } 941 }
1056 942
1057 case type::group: 943 case type::group:
1058 { 944 {
945 const group_type& group = mpark::get<group_type>(variant_);
946
1059 std::list<std::string> clauses; 947 std::list<std::string> clauses;
1060 for (const condition& cond : group_.children_) 948 for (const condition& cond : group.children)
1061 { 949 {
1062 clauses.push_back(cond.toSql(false, debug)); 950 clauses.push_back(cond.toSql(false, debug));
1063 } 951 }
1064 952
1065 if (clauses.empty()) 953 if (clauses.size() == 1)
1066 { 954 {
1067 return ""; 955 sql << clauses.front();
1068 } else if (clauses.size() == 1) 956 } else if (!clauses.empty())
1069 { 957 {
1070 return clauses.front(); 958 if (!toplevel)
1071 } else { 959 {
1072 std::string result = hatkirby::implode(std::begin(clauses), std::end(clauses), group_.orlogic_ ? " OR " : " AND "); 960 sql << "(";
961 }
962
963 sql <<
964 hatkirby::implode(
965 std::begin(clauses),
966 std::end(clauses),
967 group.orlogic ? " OR " : " AND ");
1073 968
1074 if (toplevel) 969 if (!toplevel)
1075 { 970 {
1076 return result; 971 sql << ")";
1077 } else {
1078 return "(" + result + ")";
1079 } 972 }
1080 } 973 }
974
975 break;
1081 } 976 }
1082 } 977 }
978
979 return sql.str();
1083 } 980 }
1084 981
1085 std::list<binding> statement::condition::flattenBindings() const 982 std::list<hatkirby::binding> statement::condition::flattenBindings() const
1086 { 983 {
1087 switch (type_) 984 switch (type_)
1088 { 985 {
@@ -1093,39 +990,27 @@ namespace verbly {
1093 990
1094 case type::singleton: 991 case type::singleton:
1095 { 992 {
1096 if (singleton_.value_.getType() == binding::type::field) 993 const singleton_type& singleton = mpark::get<singleton_type>(variant_);
994
995 if (mpark::holds_alternative<std::string>(singleton.value))
1097 { 996 {
1098 return {}; 997 return {{ mpark::get<std::string>(singleton.value) }};
998 } else if (mpark::holds_alternative<int>(singleton.value))
999 {
1000 return {{ mpark::get<int>(singleton.value) }};
1099 } else { 1001 } else {
1100 switch (singleton_.comparison_) 1002 return {};
1101 {
1102 case comparison::equals:
1103 case comparison::does_not_equal:
1104 case comparison::is_greater_than:
1105 case comparison::is_at_most:
1106 case comparison::is_less_than:
1107 case comparison::is_at_least:
1108 case comparison::is_like:
1109 case comparison::is_not_like:
1110 {
1111 return {singleton_.value_};
1112 }
1113
1114 case comparison::is_not_null:
1115 case comparison::is_null:
1116 {
1117 return {};
1118 }
1119 }
1120 } 1003 }
1121 } 1004 }
1122 1005
1123 case type::group: 1006 case type::group:
1124 { 1007 {
1125 std::list<binding> bindings; 1008 const group_type& group = mpark::get<group_type>(variant_);
1126 for (const condition& cond : group_.children_) 1009
1010 std::list<hatkirby::binding> bindings;
1011 for (const condition& cond : group.children)
1127 { 1012 {
1128 for (binding value : cond.flattenBindings()) 1013 for (hatkirby::binding value : cond.flattenBindings())
1129 { 1014 {
1130 bindings.push_back(std::move(value)); 1015 bindings.push_back(std::move(value));
1131 } 1016 }
@@ -1136,22 +1021,24 @@ namespace verbly {
1136 } 1021 }
1137 } 1022 }
1138 1023
1139 statement::condition::condition(bool orlogic) : type_(type::group) 1024 statement::condition::condition(
1025 bool orlogic) :
1026 type_(type::group),
1027 variant_(group_type { {}, orlogic })
1140 { 1028 {
1141 new(&group_.children_) std::list<condition>();
1142 group_.orlogic_ = orlogic;
1143 } 1029 }
1144 1030
1145 statement::condition& statement::condition::operator+=(condition n) 1031 statement::condition& statement::condition::operator+=(condition n)
1146 { 1032 {
1147 if (type_ == type::group) 1033 if (type_ != type::group)
1148 { 1034 {
1149 group_.children_.push_back(std::move(n));
1150
1151 return *this;
1152 } else {
1153 throw std::domain_error("Cannot add condition to non-group condition"); 1035 throw std::domain_error("Cannot add condition to non-group condition");
1154 } 1036 }
1037
1038 group_type& group = mpark::get<group_type>(variant_);
1039 group.children.emplace_back(std::move(n));
1040
1041 return *this;
1155 } 1042 }
1156 1043
1157 statement::condition& statement::condition::operator&=(condition n) 1044 statement::condition& statement::condition::operator&=(condition n)
@@ -1187,14 +1074,17 @@ namespace verbly {
1187 return *this; 1074 return *this;
1188 } 1075 }
1189 1076
1190 const std::list<statement::condition>& statement::condition::getChildren() const 1077 const std::list<statement::condition>& statement::condition::getChildren()
1078 const
1191 { 1079 {
1192 if (type_ == type::group) 1080 if (type_ != type::group)
1193 { 1081 {
1194 return group_.children_;
1195 } else {
1196 throw std::domain_error("Cannot get children of non-group condition"); 1082 throw std::domain_error("Cannot get children of non-group condition");
1197 } 1083 }
1084
1085 const group_type& group = mpark::get<group_type>(variant_);
1086
1087 return group.children;
1198 } 1088 }
1199 1089
1200 statement::condition statement::condition::flatten() const 1090 statement::condition statement::condition::flatten() const
@@ -1209,17 +1099,27 @@ namespace verbly {
1209 1099
1210 case type::group: 1100 case type::group:
1211 { 1101 {
1212 condition result(group_.orlogic_); 1102 const group_type& group = mpark::get<group_type>(variant_);
1213 1103
1214 for (const condition& child : group_.children_) 1104 condition result(group.orlogic);
1105
1106 for (const condition& child : group.children)
1215 { 1107 {
1216 condition newChild = child.flatten(); 1108 condition newChild = child.flatten();
1217 1109
1218 if ((newChild.type_ == type::group) && (newChild.group_.orlogic_ == group_.orlogic_)) 1110 if (newChild.type_ == type::group)
1219 { 1111 {
1220 for (condition subChild : std::move(newChild.group_.children_)) 1112 group_type& childGroup =
1113 mpark::get<group_type>(newChild.variant_);
1114
1115 if (childGroup.orlogic == group.orlogic)
1221 { 1116 {
1222 result += std::move(subChild); 1117 for (condition subChild : std::move(childGroup.children))
1118 {
1119 result += std::move(subChild);
1120 }
1121 } else {
1122 result += std::move(newChild);
1223 } 1123 }
1224 } else { 1124 } else {
1225 result += std::move(newChild); 1125 result += std::move(newChild);
@@ -1231,7 +1131,9 @@ namespace verbly {
1231 } 1131 }
1232 } 1132 }
1233 1133
1234 statement::condition statement::condition::resolveCompareFields(object context, std::string tableName) const 1134 statement::condition statement::condition::resolveCompareFields(
1135 object context,
1136 std::string tableName) const
1235 { 1137 {
1236 switch (type_) 1138 switch (type_)
1237 { 1139 {
@@ -1242,9 +1144,20 @@ namespace verbly {
1242 1144
1243 case type::singleton: 1145 case type::singleton:
1244 { 1146 {
1245 if ((singleton_.parentObject_ != object::undefined) && (singleton_.parentObject_ == context)) 1147 const singleton_type& singleton = mpark::get<singleton_type>(variant_);
1148
1149 if (singleton.parentObject != object::undefined &&
1150 singleton.parentObject == context)
1246 { 1151 {
1247 return condition(singleton_.table_, singleton_.column_, singleton_.comparison_, {tableName, singleton_.value_.getColumn()}); 1152 return {
1153 singleton.table,
1154 singleton.column,
1155 singleton.comparison,
1156 field_binding {
1157 tableName,
1158 std::get<1>(mpark::get<field_binding>(singleton.value))
1159 }
1160 };
1248 } else { 1161 } else {
1249 return *this; 1162 return *this;
1250 } 1163 }
@@ -1252,8 +1165,10 @@ namespace verbly {
1252 1165
1253 case type::group: 1166 case type::group:
1254 { 1167 {
1255 condition result(group_.orlogic_); 1168 const group_type& group = mpark::get<group_type>(variant_);
1256 for (const condition& cond : group_.children_) 1169
1170 condition result(group.orlogic);
1171 for (const condition& cond : group.children)
1257 { 1172 {
1258 result += cond.resolveCompareFields(context, tableName); 1173 result += cond.resolveCompareFields(context, tableName);
1259 } 1174 }