1 module shark.clause;
2 
3 import std.conv : to;
4 
5 /**
6  * Clauses for select, update and delete.
7  */
8 public struct Clause {
9 	
10 	@disable this();
11 	
12 	/**
13 	 * Where clause.
14 	 */
15 	static struct Where {
16 		
17 		GenericStatement statement;
18 		
19 		static interface GenericStatement {}
20 		
21 		static class Statement : GenericStatement {
22 			
23 			string field;
24 			
25 			Operator operator;
26 			
27 			string value;
28 			
29 			bool needsEscaping;
30 			
31 			this(T)(string field, Operator operator, T value, bool variable=false) {
32 				this.field = field;
33 				this.operator = operator;
34 				this.value = value.to!string;
35 				static if(is(T : string)) needsEscaping = !variable;
36 			}
37 			
38 			ComplexStatement opBinary(string op : "&")(GenericStatement statement) {
39 				return new ComplexStatement(this, Glue.and, statement);
40 			}
41 			
42 			ComplexStatement opBinary(string op : "|")(GenericStatement statement) {
43 				return new ComplexStatement(this, Glue.or, statement);
44 			}
45 			
46 		}
47 		
48 		static class ComplexStatement : GenericStatement {
49 			
50 			GenericStatement leftStatement;
51 			
52 			Glue glue;
53 			
54 			GenericStatement rightStatement;
55 			
56 			this(GenericStatement leftStatement, Glue glue, GenericStatement rightStatement) {
57 				this.leftStatement = leftStatement;
58 				this.glue = glue;
59 				this.rightStatement = rightStatement;
60 			}
61 			
62 		}
63 		
64 		enum Operator {
65 			
66 			isNull,
67 			equals,
68 			notEquals,
69 			greaterThan,
70 			greaterThanOrEquals,
71 			lessThan,
72 			lessThanOrEquals,
73 			
74 		}
75 		
76 		enum Glue {
77 			
78 			and,
79 			or
80 			
81 		}
82 		
83 	}
84 	
85 	/**
86 	 * Order clause.
87 	 * Example:
88 	 * ---
89 	 * Order(Order.Field("a", Order.Field.desc), Order.Field("b", Order.Field.asc));
90 	 * ---
91 	 */
92 	static struct Order {
93 		
94 		/**
95 		 * Random order.
96 		 */
97 		enum random = { Order order; order.rand=true; return order; }();
98 		
99 		bool rand = false;
100 		
101 		Field[] fields;
102 		
103 		this(Field[] fields...) {
104 			this.fields = fields;
105 		}
106 		
107 		this(string[] fields...) {
108 			foreach(field ; fields) this.fields ~= Field(field);
109 		}
110 		
111 		static struct Field {
112 			
113 			enum asc = true;
114 			
115 			enum desc = false;
116 			
117 			string name;
118 			
119 			bool _asc = true;
120 			
121 		}
122 		
123 	}
124 	
125 	/**
126 	 * Indicates the limit of rows to be returned. It can be single
127 	 * using the 1-field constructor or complex (lower and upper limit)
128 	 * using the 2-field constrcutor.
129 	 * Example:
130 	 * ---
131 	 * Limit(1);
132 	 * Limit(10, 20);
133 	 * ---
134 	 */
135 	static struct Limit {
136 		
137 		size_t lower, upper;
138 		
139 		this(size_t lower, size_t upper) {
140 			assert(lower < upper);
141 			this.lower = lower;
142 			this.upper = upper;
143 		}
144 		
145 		this(size_t limit) {
146 			this(0, limit);
147 		}
148 		
149 	}
150 	
151 }
152 
153 struct Var {
154 
155 	string var;
156 
157 	private auto impl(T)(T value, Clause.Where.Operator operator) {
158 		static if(is(T : Var!V, V)) return new Clause.Where.Statement(var, operator, value, true);
159 		else return new Clause.Where.Statement(var, operator, value, false);
160 	}
161 
162 	auto isNull() {
163 		return impl("", Clause.Where.Operator.isNull);
164 	}
165 	
166 	auto equals(T)(T value) {
167 		return impl(value, Clause.Where.Operator.equals);
168 	}
169 	
170 	auto notEquals(T)(T value) {
171 		return impl(value, Clause.Where.Operator.notEquals);
172 	}
173 	
174 	auto greaterThan(T)(T value) {
175 		return impl(value, Clause.Where.Operator.greatherThan);
176 	}
177 	
178 	auto greaterThanOrEquals(T)(T value) {
179 		return impl(value, Clause.Where.Operator.greatherThanOrEquals);
180 	}
181 	
182 	auto lessThan(T)(T value) {
183 		return impl(value, Clause.Where.Operator.lessThan);
184 	}
185 	
186 	auto lessThanOrEquals(T)(T value) {
187 		return impl(value, Clause.Where.Operator.lessThanOrEquals);
188 	}
189 
190 }
191 
192 Var var(string variable) {
193 	return Var(variable);
194 }