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 //#include "conditionfilter.h"
45 //#include "existsfilter.h"
46 
47 extern "C" char* cplus_demangle_with_style(const char*, int, int);
48 extern "C" void init_demangler(int, int, int);
49 
50 using namespace execplan;
51 
52 class ExecPlanTest : public CppUnit::TestFixture
53 {
54 
55     CPPUNIT_TEST_SUITE( ExecPlanTest );
56 
57     CPPUNIT_TEST( selectExecutionPlan_17 );
58 
59     CPPUNIT_TEST_SUITE_END();
60 
61 private:
62 public:
63 
walkfnString(const ParseTree * n)64     static void walkfnString(const ParseTree* n)
65     {
66         char* r;
67         static bool is_init = false;
68         const char* mname = typeid(*(n->data())).name();
69 
70         if (!is_init)
71         {
72             ::init_demangler(0, 0, 0);
73             is_init = true;
74         }
75 
76         r = ::cplus_demangle_with_style(mname, 7, 27);
77 
78         if (r != 0)
79         {
80             //cout << "mangle: " << mname << " demangle: " << r << endl;
81             ::free(r);
82         }
83 
84         if (typeid(*(n->data())) == typeid(SimpleFilter))
85         {
86             cout << "SimpleFilter: " << endl;
87             const SimpleFilter* sf = dynamic_cast<SimpleFilter*>(n->data());
88             const ReturnedColumn* lhs = sf->lhs();
89             const ReturnedColumn* rhs = sf->rhs();
90             const Operator* op = sf->op();
91             cout << '\t' << lhs->data() << ' ' << op->data() << ' ' << rhs->data();
92             cout << endl << "\t\t";
93 
94             if (typeid(*lhs) == typeid(SimpleColumn))
95             {
96                 cout << "SimpleColumn: " << lhs->data() << " / ";
97             }
98             else if (typeid(*lhs) == typeid(ConstantColumn))
99             {
100                 cout << "ConstantColumn: " << lhs->data() << " / ";
101             }
102             else
103             {
104                 cout << "UNK: " << lhs->data() << " / ";
105             }
106 
107             cout << "Operator: " << op->data() << " / ";
108 
109             if (typeid(*rhs) == typeid(SimpleColumn))
110             {
111                 cout << "SimpleColumn: " << rhs->data();
112             }
113             else if (typeid(*rhs) == typeid(ConstantColumn))
114             {
115                 cout << "ConstantColumn: " << rhs->data();
116             }
117             else
118             {
119                 cout << "UNK: " << rhs->data();
120             }
121         }
122         else if (typeid(*(n->data())) == typeid(Operator))
123         {
124             cout << "Operator: ";
125             const Operator* op = dynamic_cast<Operator*>(n->data());
126             cout << '\t' << op->data();
127         }
128         else
129         {
130             cout << mname << " -x-: ";
131         }
132 
133         cout << endl;
134     }
135 
setUp()136     void setUp()
137     {
138     }
139 
tearDown()140     void tearDown()
141     {
142     }
143 
selectExecutionPlan_17()144     void selectExecutionPlan_17()
145     {
146 
147         cout <<
148              "SQL: \
149 select \
150 	sum(l_extendedprice) / 7.0 as avg_yearly \
151 from \
152 	lineitem, \
153 	part \
154 where \
155 	p_partkey = l_partkey \
156 	and p_brand = ':1' \
157 	and p_container = ':2' \
158 	and l_quantity < ( \
159 		select \
160 			0.2 * avg(l_quantity) \
161 		from \
162 			lineitem \
163 		where \
164 			l_partkey = p_partkey \
165 	);"
166              << endl;
167 
168         /* ------------ Start Query Execution --------- */
169 
170         //This is the main query body for query 17
171         CalpontSelectExecutionPlan* csep = new CalpontSelectExecutionPlan();
172 
173         // Create the Projection (returned columns)
174         CalpontSelectExecutionPlan::ReturnedColumnList colList;
175         AggregateColumn* c1 = new AggregateColumn();
176         c1->functionName("sum");
177         c1->alias("avg_yearly");
178         ArithmeticColumn* a1 = new ArithmeticColumn("(l_extendedprice ) / 7.0 ");
179         c1->functionParms(a1);
180         colList.push_back(c1);
181         csep->returnedCols(colList);  // set Projection columns
182 
183         // Filter columns
184         CalpontSelectExecutionPlan::FilterTokenList csep_filterlist;
185 
186         SimpleFilter* f1 = new SimpleFilter ( new Operator("="),
187                                               new SimpleColumn ("tpch.part.p_partkey"),
188                                               new SimpleColumn ("tpch.lineitem.l_partkey"));
189         csep_filterlist.push_back(f1);
190 
191         csep_filterlist.push_back(new Operator("and"));
192 
193         SimpleFilter* f2 = new SimpleFilter ( new Operator("<>"),
194                                               new SimpleColumn ("tpch.part.p_brand"),
195                                               new ConstantColumn(":1"));
196         csep_filterlist.push_back(f2);
197 
198         csep_filterlist.push_back(new Operator("and"));
199 
200         SimpleFilter* f3 = new SimpleFilter ( new Operator("not like"),
201                                               new SimpleColumn ("tpch.part.p_container"),
202                                               new ConstantColumn(":2"));
203         csep_filterlist.push_back(f3);
204 
205         csep_filterlist.push_back(new Operator("and"));
206 
207         /*   --------------- sub select begins here ----------------  */
208         //Sub select filter
209         CalpontSelectExecutionPlan* subcsep =
210             new CalpontSelectExecutionPlan(CalpontSelectExecutionPlan::WHERE);
211 
212         //subselect return column(s)
213         CalpontSelectExecutionPlan::ReturnedColumnList  subColList;
214 
215         ArithmeticColumn* sc1 = new ArithmeticColumn ("0.2 * avg(l_quantity)");
216         subColList.push_back(sc1);
217         // Append returned columns to subselect
218         subcsep->returnedCols(subColList);
219 
220         //subselect Filters
221         CalpontSelectExecutionPlan::FilterTokenList subcsep_filterlist;
222         SimpleFilter* sf1 = new SimpleFilter ( new Operator("="),
223                                                new SimpleColumn ("tpch.lineitem.l_suppkey"),
224                                                new SimpleColumn ("tpch.part.p_partkey"));
225         subcsep_filterlist.push_back(sf1);
226 
227         /*   --------------- sub select ends here ----------------  */
228 
229         //CalpontSelectExecutionPlan::FilterTokenList subFilterTokenList;
230         SelectFilter* f4 = new SelectFilter (new SimpleColumn ("tpch.lineitem.l_quantity"),
231                                              new Operator("<"),
232                                              subcsep);
233 
234         csep_filterlist.push_back(f4);
235 
236         csep->filterTokenList(csep_filterlist); //Set Filter Columns
237 
238         /* *** not used here **
239         // Build Group By List
240                CalpontSelectExecutionPlan::GroupByColumnList csep_groupbyList;
241                SimpleColumn *g1 = new SimpleColumn("tpch.part.p_brand");
242                csep_groupbyList.push_back(g1);
243                csep->groupByCols(csep_groupbyList);  //Set GroupBy columns
244 
245         // Order By List
246                CalpontSelectExecutionPlan::OrderByColumnList csep_orderbyList;
247                SimpleColumn *o0 = new SimpleColumn("supplier_cnt");  // AggregateColumn has no asc/desc order
248                o0->alias("supplier_cnt");
249                o0->asc(false);
250                csep_groupbyList.push_back(o0);
251                csep->orderByCols(csep_orderbyList); //Set OrderBy columns
252              */
253 
254         // Print the parse tree
255         ParseTree* pt = const_cast<ParseTree*>(csep->filters());
256         pt->drawTree("selectExecutionPlan_17.dot");
257 
258         cout << "\nCalpont Execution Plan:" << endl;
259         cout << *csep << endl;
260         cout << " --- end of test 17 ---" << endl;
261 
262     }
263 
264 };
265 
266 CPPUNIT_TEST_SUITE_REGISTRATION( ExecPlanTest );
267 
268 #include <cppunit/extensions/TestFactoryRegistry.h>
269 #include <cppunit/ui/text/TestRunner.h>
270 
main(int argc,char ** argv)271 int main( int argc, char** argv)
272 {
273     CppUnit::TextUi::TestRunner runner;
274     CppUnit::TestFactoryRegistry& registry = CppUnit::TestFactoryRegistry::getRegistry();
275     runner.addTest( registry.makeTest() );
276     bool wasSuccessful = runner.run( "", false );
277     return (wasSuccessful ? 0 : 1);
278 }
279 
280 
281