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.cpp164
1 files changed, 145 insertions, 19 deletions
diff --git a/lib/statement.cpp b/lib/statement.cpp index 846b9de..1512aa5 100644 --- a/lib/statement.cpp +++ b/lib/statement.cpp
@@ -5,11 +5,12 @@
5#include "util.h" 5#include "util.h"
6#include "notion.h" 6#include "notion.h"
7#include "word.h" 7#include "word.h"
8#include "group.h"
9#include "frame.h" 8#include "frame.h"
9#include "part.h"
10#include "lemma.h" 10#include "lemma.h"
11#include "form.h" 11#include "form.h"
12#include "pronunciation.h" 12#include "pronunciation.h"
13#include "order.h"
13 14
14namespace verbly { 15namespace verbly {
15 16
@@ -20,7 +21,7 @@ namespace verbly {
20 { 21 {
21 } 22 }
22 23
23 std::string statement::getQueryString(std::list<std::string> select, bool random, int limit) const 24 std::string statement::getQueryString(std::list<std::string> select, order sortOrder, int limit, bool debug) const
24 { 25 {
25 std::stringstream queryStream; 26 std::stringstream queryStream;
26 27
@@ -49,7 +50,7 @@ namespace verbly {
49 if (cte.getCondition().getType() != condition::type::empty) 50 if (cte.getCondition().getType() != condition::type::empty)
50 { 51 {
51 cteStream << " WHERE "; 52 cteStream << " WHERE ";
52 cteStream << cte.getCondition().toSql(); 53 cteStream << cte.getCondition().flatten().toSql(true, debug);
53 } 54 }
54 55
55 if (cte.isRecursive()) 56 if (cte.isRecursive())
@@ -101,12 +102,28 @@ namespace verbly {
101 if (topCondition_.getType() != condition::type::empty) 102 if (topCondition_.getType() != condition::type::empty)
102 { 103 {
103 queryStream << " WHERE "; 104 queryStream << " WHERE ";
104 queryStream << topCondition_.toSql(); 105 queryStream << topCondition_.flatten().toSql(true, debug);
105 } 106 }
106 107
107 if (random) 108 queryStream << " ORDER BY ";
109
110 switch (sortOrder.getType())
108 { 111 {
109 queryStream << " ORDER BY RANDOM()"; 112 case order::type::random:
113 {
114 queryStream << "RANDOM()";
115
116 break;
117 }
118
119 case order::type::field:
120 {
121 queryStream << topTable_;
122 queryStream << ".";
123 queryStream << sortOrder.getSortField().getColumn();
124
125 break;
126 }
110 } 127 }
111 128
112 if (limit > 0) 129 if (limit > 0)
@@ -260,6 +277,7 @@ namespace verbly {
260 } 277 }
261 278
262 case field::type::join: 279 case field::type::join:
280 case field::type::join_where:
263 { 281 {
264 // First, figure out what table we need to join against. 282 // First, figure out what table we need to join against.
265 std::string joinTableName; 283 std::string joinTableName;
@@ -269,13 +287,22 @@ namespace verbly {
269 } else { 287 } else {
270 joinTableName = getTableForContext(clause.getField().getJoinObject()); 288 joinTableName = getTableForContext(clause.getField().getJoinObject());
271 } 289 }
290
291 filter joinCondition = clause.getJoinCondition();
292
293 // If this is a condition join, we need to add the field join
294 // condition to the clause.
295 if (clause.getField().getType() == field::type::join_where)
296 {
297 joinCondition &= (clause.getField().getConditionField() == clause.getField().getConditionValue());
298 }
272 299
273 // Recursively parse the subquery, and therefore obtain an 300 // Recursively parse the subquery, and therefore obtain an
274 // instantiated table to join against, as well as any joins or CTEs 301 // instantiated table to join against, as well as any joins or CTEs
275 // that the subquery may require to function. 302 // that the subquery may require to function.
276 statement joinStmt( 303 statement joinStmt(
277 joinTableName, 304 joinTableName,
278 clause.getJoinCondition().normalize(clause.getField().getJoinObject()), 305 std::move(joinCondition).normalize(clause.getField().getJoinObject()),
279 nextTableId_, 306 nextTableId_,
280 nextWithId_); 307 nextWithId_);
281 308
@@ -801,7 +828,7 @@ namespace verbly {
801 new(&singleton_.value_) binding(std::move(value)); 828 new(&singleton_.value_) binding(std::move(value));
802 } 829 }
803 830
804 std::string statement::condition::toSql() const 831 std::string statement::condition::toSql(bool toplevel, bool debug) const
805 { 832 {
806 switch (type_) 833 switch (type_)
807 { 834 {
@@ -816,42 +843,92 @@ namespace verbly {
816 { 843 {
817 case comparison::equals: 844 case comparison::equals:
818 { 845 {
819 return singleton_.table_ + "." + singleton_.column_ + " = ?"; 846 if (debug)
847 {
848 if (singleton_.value_.getType() == binding::type::string)
849 {
850 return singleton_.table_ + "." + singleton_.column_ + " = \"" + singleton_.value_.getString() + "\"";
851 } else {
852 return singleton_.table_ + "." + singleton_.column_ + " = " + std::to_string(singleton_.value_.getInteger());
853 }
854 } else {
855 return singleton_.table_ + "." + singleton_.column_ + " = ?";
856 }
820 } 857 }
821 858
822 case comparison::does_not_equal: 859 case comparison::does_not_equal:
823 { 860 {
824 return singleton_.table_ + "." + singleton_.column_ + " != ?"; 861 if (debug)
862 {
863 if (singleton_.value_.getType() == binding::type::string)
864 {
865 return singleton_.table_ + "." + singleton_.column_ + " != \"" + singleton_.value_.getString() + "\"";
866 } else {
867 return singleton_.table_ + "." + singleton_.column_ + " != " + std::to_string(singleton_.value_.getInteger());
868 }
869 } else {
870 return singleton_.table_ + "." + singleton_.column_ + " != ?";
871 }
825 } 872 }
826 873
827 case comparison::is_greater_than: 874 case comparison::is_greater_than:
828 { 875 {
829 return singleton_.table_ + "." + singleton_.column_ + " > ?"; 876 if (debug)
877 {
878 return singleton_.table_ + "." + singleton_.column_ + " > " + std::to_string(singleton_.value_.getInteger());
879 } else {
880 return singleton_.table_ + "." + singleton_.column_ + " > ?";
881 }
830 } 882 }
831 883
832 case comparison::is_at_most: 884 case comparison::is_at_most:
833 { 885 {
834 return singleton_.table_ + "." + singleton_.column_ + " <= ?"; 886 if (debug)
887 {
888 return singleton_.table_ + "." + singleton_.column_ + " <= " + std::to_string(singleton_.value_.getInteger());
889 } else {
890 return singleton_.table_ + "." + singleton_.column_ + " <= ?";
891 }
835 } 892 }
836 893
837 case comparison::is_less_than: 894 case comparison::is_less_than:
838 { 895 {
839 return singleton_.table_ + "." + singleton_.column_ + " < ?"; 896 if (debug)
897 {
898 return singleton_.table_ + "." + singleton_.column_ + " < " + std::to_string(singleton_.value_.getInteger());
899 } else {
900 return singleton_.table_ + "." + singleton_.column_ + " < ?";
901 }
840 } 902 }
841 903
842 case comparison::is_at_least: 904 case comparison::is_at_least:
843 { 905 {
844 return singleton_.table_ + "." + singleton_.column_ + " >= ?"; 906 if (debug)
907 {
908 return singleton_.table_ + "." + singleton_.column_ + " >= " + std::to_string(singleton_.value_.getInteger());
909 } else {
910 return singleton_.table_ + "." + singleton_.column_ + " >= ?";
911 }
845 } 912 }
846 913
847 case comparison::is_like: 914 case comparison::is_like:
848 { 915 {
849 return singleton_.table_ + "." + singleton_.column_ + " LIKE ?"; 916 if (debug)
917 {
918 return singleton_.table_ + "." + singleton_.column_ + " LIKE \"" + singleton_.value_.getString() + "\"";
919 } else {
920 return singleton_.table_ + "." + singleton_.column_ + " LIKE ?";
921 }
850 } 922 }
851 923
852 case comparison::is_not_like: 924 case comparison::is_not_like:
853 { 925 {
854 return singleton_.table_ + "." + singleton_.column_ + " NOT LIKE ?"; 926 if (debug)
927 {
928 return singleton_.table_ + "." + singleton_.column_ + " NOT LIKE \"" + singleton_.value_.getString() + "\"";
929 } else {
930 return singleton_.table_ + "." + singleton_.column_ + " NOT LIKE ?";
931 }
855 } 932 }
856 933
857 case comparison::is_not_null: 934 case comparison::is_not_null:
@@ -871,10 +948,25 @@ namespace verbly {
871 std::list<std::string> clauses; 948 std::list<std::string> clauses;
872 for (const condition& cond : group_.children_) 949 for (const condition& cond : group_.children_)
873 { 950 {
874 clauses.push_back(cond.toSql()); 951 clauses.push_back(cond.toSql(false, debug));
875 } 952 }
876 953
877 return implode(std::begin(clauses), std::end(clauses), group_.orlogic_ ? " OR " : " AND "); 954 if (clauses.empty())
955 {
956 return "";
957 } else if (clauses.size() == 1)
958 {
959 return clauses.front();
960 } else {
961 std::string result = implode(std::begin(clauses), std::end(clauses), group_.orlogic_ ? " OR " : " AND ");
962
963 if (toplevel)
964 {
965 return result;
966 } else {
967 return "(" + result + ")";
968 }
969 }
878 } 970 }
879 } 971 }
880 } 972 }
@@ -988,5 +1080,39 @@ namespace verbly {
988 throw std::domain_error("Cannot get children of non-group condition"); 1080 throw std::domain_error("Cannot get children of non-group condition");
989 } 1081 }
990 } 1082 }
1083
1084 statement::condition statement::condition::flatten() const
1085 {
1086 switch (type_)
1087 {
1088 case type::empty:
1089 case type::singleton:
1090 {
1091 return *this;
1092 }
1093
1094 case type::group:
1095 {
1096 condition result(group_.orlogic_);
1097
1098 for (const condition& child : group_.children_)
1099 {
1100 condition newChild = child.flatten();
1101
1102 if ((newChild.type_ == type::group) && (newChild.group_.orlogic_ == group_.orlogic_))
1103 {
1104 for (condition subChild : std::move(newChild.group_.children_))
1105 {
1106 result += std::move(subChild);
1107 }
1108 } else {
1109 result += std::move(newChild);
1110 }
1111 }
1112
1113 return result;
1114 }
1115 }
1116 }
991 1117
992}; 1118};