1 /* Copyright (C) 2014 InfiniDB, Inc.
2
3 This program is free software; you can redistribute it and/or
4 modify it under the terms of the GNU General Public License
5 as published by the Free Software Foundation; version 2 of
6 the License.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program; if not, write to the Free Software
15 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
16 MA 02110-1301, USA. */
17
18 #include <string>
19 #include <stdexcept>
20 #include <typeinfo>
21 using namespace std;
22
23 #include <cppunit/extensions/HelperMacros.h>
24
25 #include<sstream>
26 #include<exception>
27 #include<iostream>
28 #include <unistd.h>
29
30 #include "messagequeue.h"
31 #include "bytestream.h"
32 using namespace messageqcpp;
33
34 #include "calpontselectexecutionplan.h"
35 #include "simplefilter.h"
36 #include "simplecolumn.h"
37 #include "expressionparser.h"
38 #include "constantcolumn.h"
39 #include "treenode.h"
40 #include "operator.h"
41 #include "arithmeticcolumn.h"
42 #include "aggregatecolumn.h"
43
44 extern "C" char* cplus_demangle_with_style(const char*, int, int);
45 extern "C" void init_demangler(int, int, int);
46
47 using namespace execplan;
48
49 class ExecPlanTest : public CppUnit::TestFixture
50 {
51
52 CPPUNIT_TEST_SUITE( ExecPlanTest );
53
54 CPPUNIT_TEST( selectExecutionPlan_12 );
55
56 CPPUNIT_TEST_SUITE_END();
57
58 private:
59 public:
60
walkfnString(const ParseTree * n)61 static void walkfnString(const ParseTree* n)
62 {
63 char* r;
64 static bool is_init = false;
65 const char* mname = typeid(*(n->data())).name();
66
67 if (!is_init)
68 {
69 ::init_demangler(0, 0, 0);
70 is_init = true;
71 }
72
73 r = ::cplus_demangle_with_style(mname, 7, 27);
74
75 if (r != 0)
76 {
77 //cout << "mangle: " << mname << " demangle: " << r << endl;
78 ::free(r);
79 }
80
81 if (typeid(*(n->data())) == typeid(SimpleFilter))
82 {
83 cout << "SimpleFilter: " << endl;
84 const SimpleFilter* sf = dynamic_cast<SimpleFilter*>(n->data());
85 const ReturnedColumn* lhs = sf->lhs();
86 const ReturnedColumn* rhs = sf->rhs();
87 const Operator* op = sf->op();
88 cout << '\t' << lhs->data() << ' ' << op->data() << ' ' << rhs->data();
89 cout << endl << "\t\t";
90
91 if (typeid(*lhs) == typeid(SimpleColumn))
92 {
93 cout << "SimpleColumn: " << lhs->data() << " / ";
94 }
95 else if (typeid(*lhs) == typeid(ConstantColumn))
96 {
97 cout << "ConstantColumn: " << lhs->data() << " / ";
98 }
99 else
100 {
101 cout << "UNK: " << lhs->data() << " / ";
102 }
103
104 cout << "Operator: " << op->data() << " / ";
105
106 if (typeid(*rhs) == typeid(SimpleColumn))
107 {
108 cout << "SimpleColumn: " << rhs->data();
109 }
110 else if (typeid(*rhs) == typeid(ConstantColumn))
111 {
112 cout << "ConstantColumn: " << rhs->data();
113 }
114 else
115 {
116 cout << "UNK: " << rhs->data();
117 }
118 }
119 else if (typeid(*(n->data())) == typeid(Operator))
120 {
121 cout << "Operator: ";
122 const Operator* op = dynamic_cast<Operator*>(n->data());
123 cout << '\t' << op->data();
124 }
125 else
126 {
127 cout << mname << " -x-: ";
128 }
129
130 cout << endl;
131 }
132
setUp()133 void setUp()
134 {
135 }
136
tearDown()137 void tearDown()
138 {
139 }
140
selectExecutionPlan_12()141 void selectExecutionPlan_12()
142 {
143
144 // cout << "SQL: select r_regionkey from region, nation where n_regionkey = r_regionkey and n_regionkey = 2;" << endl;
145 cout <<
146 "SQL: select \
147 l_shipmode, \
148 sum(case \
149 when o_orderpriority = '1-URGENT' \
150 or o_orderpriority = '2-HIGH' \
151 then 1 \
152 else 0 \
153 end ) as high_line_count, \
154 sum(case \
155 when o_orderpriority <> '1-URGENT' \
156 and o_orderpriority <> '2-HIGH' \
157 then 1 \
158 else 0 \
159 end ) as low_line_count \
160 from \
161 orders, \
162 lineitem \
163 where \
164 o_orderkey = l_orderkey \
165 and l_shipmode in (':1', ':2') \
166 and l_commitdate < l_reciptdate \
167 and l_shipdate < l_commitdate \
168 and l_receiptdate >= date ':3' \
169 and l_receiptdate < date ':3' + interval '1' year' \
170 group by \
171 l_shipmode \
172 order by \
173 l_shipmode;" << endl;
174
175
176 CalpontSelectExecutionPlan csep;
177 CalpontSelectExecutionPlan::ReturnedColumnList colList;
178 CalpontSelectExecutionPlan::GroupByColumnList groupbyList;
179 CalpontSelectExecutionPlan::OrderByColumnList orderbyList;
180 ParseTree* filterList;
181
182 // returned columns
183 SimpleColumn l_shipmode("tpch.lineitem.l_shipmode");
184 AggregateColumn* high_line_count = new AggregateColumn();
185 high_line_count->functionName("sum");
186 ArithmeticColumn* a1 = new ArithmeticColumn ("( CASE WHEN o_orderpriority = '1-URGENT' or o_orderpriority = '2-HIGH' THEN 1 ELSE 0 END )");
187 high_line_count->functionParms(a1);
188
189 AggregateColumn* low_line_count = new AggregateColumn();
190 low_line_count->functionName("sum");
191 ArithmeticColumn* a2 = new ArithmeticColumn ("( CASE WHEN o_orderpriority <> '1-URGENT' and o_orderpriority <> '2-HIGH' THEN 1 ELSE 0 END )");
192 low_line_count->functionParms(a2);
193
194
195 // Create the Projection
196 colList.push_back(high_line_count);
197 colList.push_back(low_line_count);
198
199 // Filter columns
200 SimpleColumn l_shipmode0("tpch.lineitem.l_shipmode");
201 SimpleColumn l_shipmode1("tpch.lineitem.l_shipmode");
202 SimpleColumn l_commitdate("tpch.lineitem.l_commitdate");
203 SimpleColumn l_receiptdate("tpch.lineitem.l_receiptdate");
204 SimpleColumn l_receiptdate1("tpch.lineitem.l_receiptdate");
205 SimpleColumn l_shipdate("tpch.lineitem.l_shipdate");
206
207
208 // filters
209 CalpontSelectExecutionPlan::Parser parser;
210 std::vector<Token> tokens;
211
212 //tokens.push_back(Token(new Operator("(")));
213 //tokens.push_back(Token(new Operator(")")));
214
215 tokens.push_back(Token(new SimpleFilter(new Operator("="),
216 new SimpleColumn(l_shipmode),
217 new ConstantColumn("1"))));
218
219 tokens.push_back(Token(new Operator("and")));
220
221 tokens.push_back(Token(new SimpleFilter(new Operator("="),
222 new SimpleColumn(l_shipmode),
223 new ConstantColumn("2"))));
224
225 tokens.push_back(Token(new Operator("and")));
226
227 tokens.push_back(Token(new SimpleFilter(new Operator("<"),
228 new SimpleColumn(l_commitdate),
229 new SimpleColumn(l_receiptdate))));
230
231 tokens.push_back(Token(new Operator("and")));
232
233 tokens.push_back(Token(new SimpleFilter(new Operator("<"),
234 new SimpleColumn(l_shipdate),
235 new SimpleColumn(l_commitdate))));
236
237 tokens.push_back(Token(new Operator("and")));
238
239 tokens.push_back(Token(new SimpleFilter(new Operator(">="),
240 new SimpleColumn(l_receiptdate),
241 new ConstantColumn("06/01/2005"))));
242
243 tokens.push_back(Token(new Operator("and")));
244
245 tokens.push_back(Token(new SimpleFilter(new Operator("<"),
246 new SimpleColumn(l_receiptdate),
247 new ConstantColumn("06/01/2006"))));
248
249 // old below
250 filterList = parser.parse(tokens.begin(), tokens.end());
251
252 // draw filterList tree
253 filterList->drawTree("selectExecutionPlan_12.dot");
254
255 // Build Group By List
256 SimpleColumn* l_shipmode2 = new SimpleColumn("tpch.lineitem.l_shipmode");
257 groupbyList.push_back(l_shipmode2);
258
259 // Build Order By List
260 // SimpleColumn *l_shipmode2 = new SimpleColumn("tpch.lineitem.l_shipmode");
261 orderbyList.push_back(l_shipmode2);
262
263 // calpont execution plan
264 csep.returnedCols (colList);
265 csep.filters (filterList);
266 cout << "\nCalpont Execution Plan:" << endl;
267 cout << csep << endl;
268 cout << " --- end of test 12 ---" << endl;
269
270 filterList->walk(walkfnString);
271
272 }
273
274 };
275
276 CPPUNIT_TEST_SUITE_REGISTRATION( ExecPlanTest );
277
278 #include <cppunit/extensions/TestFactoryRegistry.h>
279 #include <cppunit/ui/text/TestRunner.h>
280
main(int argc,char ** argv)281 int main( int argc, char** argv)
282 {
283 CppUnit::TextUi::TestRunner runner;
284 CppUnit::TestFactoryRegistry& registry = CppUnit::TestFactoryRegistry::getRegistry();
285 runner.addTest( registry.makeTest() );
286 bool wasSuccessful = runner.run( "", false );
287 return (wasSuccessful ? 0 : 1);
288 }
289
290
291