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 #include "selectfilter.h"
44 
45 extern "C" char* cplus_demangle_with_style(const char*, int, int);
46 extern "C" void init_demangler(int, int, int);
47 
48 using namespace execplan;
49 
50 class ExecPlanTest : public CppUnit::TestFixture
51 {
52 
53     CPPUNIT_TEST_SUITE( ExecPlanTest );
54 
55     CPPUNIT_TEST( selectExecutionPlan_15 );
56 
57     CPPUNIT_TEST_SUITE_END();
58 
59 private:
60 public:
61 
walkfnString(const ParseTree * n)62     static void walkfnString(const ParseTree* n)
63     {
64         char* r;
65         static bool is_init = false;
66         const char* mname = typeid(*(n->data())).name();
67 
68         if (!is_init)
69         {
70             ::init_demangler(0, 0, 0);
71             is_init = true;
72         }
73 
74         r = ::cplus_demangle_with_style(mname, 7, 27);
75 
76         if (r != 0)
77         {
78             //cout << "mangle: " << mname << " demangle: " << r << endl;
79             ::free(r);
80         }
81 
82         if (typeid(*(n->data())) == typeid(SimpleFilter))
83         {
84             cout << "SimpleFilter: " << endl;
85             const SimpleFilter* sf = dynamic_cast<SimpleFilter*>(n->data());
86             const ReturnedColumn* lhs = sf->lhs();
87             const ReturnedColumn* rhs = sf->rhs();
88             const Operator* op = sf->op();
89             cout << '\t' << lhs->data() << ' ' << op->data() << ' ' << rhs->data();
90             cout << endl << "\t\t";
91 
92             if (typeid(*lhs) == typeid(SimpleColumn))
93             {
94                 cout << "SimpleColumn: " << lhs->data() << " / ";
95             }
96             else if (typeid(*lhs) == typeid(ConstantColumn))
97             {
98                 cout << "ConstantColumn: " << lhs->data() << " / ";
99             }
100             else
101             {
102                 cout << "UNK: " << lhs->data() << " / ";
103             }
104 
105             cout << "Operator: " << op->data() << " / ";
106 
107             if (typeid(*rhs) == typeid(SimpleColumn))
108             {
109                 cout << "SimpleColumn: " << rhs->data();
110             }
111             else if (typeid(*rhs) == typeid(ConstantColumn))
112             {
113                 cout << "ConstantColumn: " << rhs->data();
114             }
115             else
116             {
117                 cout << "UNK: " << rhs->data();
118             }
119         }
120         else if (typeid(*(n->data())) == typeid(Operator))
121         {
122             cout << "Operator: ";
123             const Operator* op = dynamic_cast<Operator*>(n->data());
124             cout << '\t' << op->data();
125         }
126         else
127         {
128             cout << mname << " -x-: ";
129         }
130 
131         cout << endl;
132     }
133 
setUp()134     void setUp()
135     {
136     }
137 
tearDown()138     void tearDown()
139     {
140     }
141 
selectExecutionPlan_15()142     void selectExecutionPlan_15()
143     {
144 
145         cout <<
146              "SQL: \
147 create view revenue:s (supplier_no, total_revenue) as \
148 	select \
149 		l_suppkey, \
150 		sum(l_extendedprice * (1 - l_discount)) \
151 	from \
152 		lineitem \
153 	where \
154 		l_shipdate >= date ':1' \
155 		and l_shipdate < date ':1' + interval '3' month \
156 	group by \
157 		l_suppkey; \
158  \
159 select \
160 	s_suppkey, \
161 	s_name, \
162 	s_address, \
163 	s_phone, \
164 	total_revenue \
165 from \
166 	supplier, \
167 	revenue:s \
168 where \
169 	s_suppkey = supplier_no \
170 	and total_revenue = ( \
171 		select \
172 			max(total_revenue) \
173 		from \
174 			revenue:s \
175 	) \
176 order by \
177 	s_suppkey; \
178  \
179 drop view revenue:s; \
180   " << endl;
181 
182         /* ------------The create view statement is being re-written as an inline view  ----- */
183         /* ------------ (dynamic table) to be used in a from cluase.                    ----- */
184 
185         CalpontSelectExecutionPlan* csep = new CalpontSelectExecutionPlan();
186         CalpontSelectExecutionPlan::ReturnedColumnList colList;
187         CalpontSelectExecutionPlan::GroupByColumnList groupbyList;
188         CalpontSelectExecutionPlan::OrderByColumnList orderbyList;
189         ParseTree* filterList;
190 
191         // returned columns
192         //SimpleColumn l_suppkey("tpch.lineitem.l_suppkey");
193         SimpleColumn* l_suppkey = new SimpleColumn("tpch.lineitem.l_suppkey");
194         AggregateColumn* total_revenue = new AggregateColumn();
195         total_revenue->functionName("sum");
196         total_revenue->alias("total_revenue");
197         ArithmeticColumn* a1 = new ArithmeticColumn ("l_extenedprice * (1 - l_discount)");
198         total_revenue->functionParms(a1);
199 
200         // Create the Projection
201         colList.push_back(l_suppkey);
202         colList.push_back(total_revenue);
203 
204         // Filter columns
205         SimpleColumn l_shipdate("tpch.lineitem.l_shipdate");
206         //SimpleColumn l_shipmode0("tpch.lineitem.l_shipmode");
207         //SimpleColumn l_shipmode1("tpch.lineitem.l_shipmode");
208         //SimpleColumn l_commitdate("tpch.lineitem.l_commitdate");
209         //SimpleColumn l_receiptdate("tpch.lineitem.l_receiptdate");
210         //SimpleColumn l_receiptdate1("tpch.lineitem.l_receiptdate");
211 
212 
213         // filters
214         CalpontSelectExecutionPlan::Parser parser;
215         std::vector<Token> tokens;
216 
217         //tokens.push_back(Token(new Operator("(")));
218         //tokens.push_back(Token(new Operator(")")));
219 
220         tokens.push_back(Token(new SimpleFilter(new Operator(">="),
221                                                 new SimpleColumn(l_shipdate),
222                                                 new ConstantColumn("06/01/2005"))));
223 
224         tokens.push_back(Token(new Operator("and")));
225 
226         tokens.push_back(Token(new SimpleFilter(new Operator("<"),
227                                                 new SimpleColumn(l_shipdate),
228                                                 new ConstantColumn("07/01/2005"))));
229 
230         // old below
231         filterList = parser.parse(tokens.begin(), tokens.end());
232 
233         // draw filterList tree
234         filterList->drawTree("selectExecutionPlan_15sub.dot");
235 
236         // Build Group By List
237         SimpleColumn* l_suppkey2 = new SimpleColumn("tpch.lineitem.l_suppkey");
238         groupbyList.push_back(l_suppkey2);
239 
240         // calpont execution plan
241         csep->returnedCols (colList);
242         csep->filters (filterList);
243 
244         csep->location (CalpontSelectExecutionPlan::FROM);  // Use scope resolution to use enum.
245 
246         cout << "\nCalpont Execution Plan:" << endl;
247         cout << *csep << endl;
248         cout << " --- end of test 15 ---" << endl;
249 
250         /*  ------ This is the begining of the outer query  ---------------------- */
251         /*  ------ This is the begining of the outer query  ---------------------- */
252 
253 
254         CalpontSelectExecutionPlan* csep_parent = new CalpontSelectExecutionPlan();
255         cout << "********* I'm ok to here 01 ***************" << endl;
256         CalpontSelectExecutionPlan::ReturnedColumnList colList2;
257         CalpontSelectExecutionPlan::GroupByColumnList groupbyList2;
258         cout << "********* I'm ok to here 02 ***************" << endl;
259         CalpontSelectExecutionPlan::OrderByColumnList orderbyList2;
260         CalpontSelectExecutionPlan::SelectList  subSelectList2;
261         //`ParseTree* filterList2;
262 
263         cout << "********* I'm ok to here 1 ***************" << endl;
264         // returned columns
265         SimpleColumn* s_suppkey = new SimpleColumn ("tpch.supplier.s_suppkey");
266         SimpleColumn* s_name = new SimpleColumn("tpch.supplier.s_name");
267         SimpleColumn* s_address = new SimpleColumn("tpch.supplier.s_address");
268         SimpleColumn* s_phone = new SimpleColumn("tpch.supplier.s_phone");
269         cout << "********* I'm ok to here 1a ***************" << endl;
270         AggregateColumn* s_total_revenue = new AggregateColumn();
271         cout << "********* I'm ok to here 1b ***************" << endl;
272         s_total_revenue->functionName("sum");
273         ArithmeticColumn* a5 = new ArithmeticColumn ("o_orderpriority = '2-HIGH' THEN 1 ELSE 0  END )");
274         cout << "********* I'm ok to here 1c ***************" << endl;
275         s_total_revenue->functionParms(a5);
276 
277         // Create the Projection
278         cout << "********* I'm ok to here 1d ***************" << endl;
279         colList2.push_back(s_suppkey);
280         colList2.push_back(s_name);
281         colList2.push_back(s_address);
282         colList2.push_back(s_phone);
283         colList2.push_back(s_total_revenue);
284         cout << "********* I'm ok to here 1e ***************" << endl;
285 
286         /*  ------ This is the begining of the query filter ---------------------- */
287         /*  ------ This is the begining of the query filter ---------------------- */
288 
289         //std::vector<Token> tokens_n;
290         CalpontSelectExecutionPlan::FilterTokenList regFilterTokenList;
291         SimpleFilter* f1 = new SimpleFilter ( new Operator("="),
292                                               new SimpleColumn ("tpch.supplier.s_suppkey"),
293                                               new SimpleColumn ("tpch.supplier.s_supplier_no"));
294 
295         regFilterTokenList.push_back(f1);
296         regFilterTokenList.push_back(new Operator("and"));
297 
298 
299         cout << "********* I'm ok to here 1 ***************" << endl;
300         //Sub select filter
301         CalpontSelectExecutionPlan* subcsep =
302             new CalpontSelectExecutionPlan(CalpontSelectExecutionPlan::WHERE);
303 
304         //subselect return column(s)
305         CalpontSelectExecutionPlan::ReturnedColumnList  subColList;
306 
307         ArithmeticColumn* sc1 = new ArithmeticColumn ("max(total_revenue)");
308         //CalpontSelectExecutionPlan::SelectList  subSelectList;
309 
310         subColList.push_back(sc1);
311         subcsep->returnedCols(subColList);
312         cout << "********* I'm ok to here 2 ***************" << endl;
313 
314         //subselect Filters
315         //CalpontSelectExecutionPlan::FilterTokenList subFilterTokenList;
316         SelectFilter* f2 = new SelectFilter (new SimpleColumn ("tpch.revenue.total_revenue"),
317                                              new Operator("="),
318                                              subcsep);
319 
320         regFilterTokenList.push_back(f2);
321 
322 
323         cout << "********* I'm ok to here 3 ***************" << endl;
324         // Filter columns
325         //SimpleColumn l_shipmode0("tpch.lineitem.l_shipmode");
326         // ***  Already creted via regFilterTokenList object ****
327 
328         // filters
329         //CalpontSelectExecutionPlan::Parser parser;
330         //std::vector<Token> tokens;
331         // ***  Already creted via regFilterTokenList object ****
332 
333         //tokens.push_back(Token(new Operator("(")));
334         //tokens.push_back(Token(new Operator(")")));
335 
336         //tokens.push_back(Token(new SimpleFilter(new Operator("="),
337         //			new SimpleColumn(l_shipmode),
338         //			new ConstantColumn("1"))));
339 
340         //tokens.push_back(Token(new Operator("and")));
341 
342         //tokens.push_back(Token(new SimpleFilter(new Operator("="),
343         //			new SimpleColumn(l_shipmode),
344         //			new ConstantColumn("2"))));
345 
346 
347         // old below
348         // filterList = parser.parse(tokens.begin(), tokens.end());
349 
350         // draw filterList tree
351         //filterList->drawTree("selectExecutionPlan_15n.dot");
352 
353         // Build Group By List
354         //SimpleColumn *l_shipmode2 = new SimpleColumn("tpch.lineitem.l_shipmode");
355         //groupbyList.push_back(l_shipmode2);
356 
357         // Build Order By List
358         SimpleColumn* s_suppkey3 = new SimpleColumn("tpch.supplier.s_suppkey");
359         orderbyList.push_back(s_suppkey3);
360 
361         // calpont execution plan
362         csep_parent->returnedCols (colList2);
363         csep_parent->filterTokenList(regFilterTokenList);
364         csep_parent->orderByCols(orderbyList);
365 
366         cout << "********* I'm ok to here 4 ***************" << endl;
367         // draw filterList tree
368         //csep_parent->filterTokenList->drawTree("selectExecutionPlan_15.dot");
369         ParseTree* pt = const_cast<ParseTree*>(csep_parent->filters());
370         pt->drawTree("selectExecutionPlan_15.dot");
371 
372         cout << "\nCalpont Execution Plan:" << endl;
373         cout << csep << endl;
374         cout << " --- end of test 15 ---" << endl;
375 
376         filterList->walk(walkfnString);
377 
378     }
379 
380 };
381 
382 CPPUNIT_TEST_SUITE_REGISTRATION( ExecPlanTest );
383 
384 #include <cppunit/extensions/TestFactoryRegistry.h>
385 #include <cppunit/ui/text/TestRunner.h>
386 
main(int argc,char ** argv)387 int main( int argc, char** argv)
388 {
389     CppUnit::TextUi::TestRunner runner;
390     CppUnit::TestFactoryRegistry& registry = CppUnit::TestFactoryRegistry::getRegistry();
391     runner.addTest( registry.makeTest() );
392     bool wasSuccessful = runner.run( "", false );
393     return (wasSuccessful ? 0 : 1);
394 }
395 
396 
397