]> git.proxmox.com Git - ceph.git/blob - ceph/src/s3select/include/s3select_oper.h
591e5f9da245514e92e606038895667343fb4052
[ceph.git] / ceph / src / s3select / include / s3select_oper.h
1 #ifndef __S3SELECT_OPER__
2 #define __S3SELECT_OPER__
3
4 #include <string>
5 #include <iostream>
6 #include <list>
7 #include <map>
8 #include <vector>
9 #include <string.h>
10 #include <math.h>
11
12 #include <boost/lexical_cast.hpp>
13 #include <boost/date_time/posix_time/posix_time.hpp>
14 #include <boost/bind.hpp>
15 namespace bsc = BOOST_SPIRIT_CLASSIC_NS;
16
17 namespace s3selectEngine
18 {
19
20 class base_s3select_exception
21 {
22
23 public:
24 enum class s3select_exp_en_t
25 {
26 NONE,
27 ERROR,
28 FATAL
29 } ;
30
31 private:
32 s3select_exp_en_t m_severity;
33
34 public:
35 std::string _msg;
36 base_s3select_exception(const char* n) : m_severity(s3select_exp_en_t::NONE)
37 {
38 _msg.assign(n);
39 }
40 base_s3select_exception(const char* n, s3select_exp_en_t severity) : m_severity(severity)
41 {
42 _msg.assign(n);
43 }
44 base_s3select_exception(std::string n, s3select_exp_en_t severity) : m_severity(severity)
45 {
46 _msg = n;
47 }
48
49 virtual const char* what()
50 {
51 return _msg.c_str();
52 }
53
54 s3select_exp_en_t severity()
55 {
56 return m_severity;
57 }
58
59 virtual ~base_s3select_exception() {}
60 };
61
62
63 // pointer to dynamic allocated buffer , which used for placement new.
64 static __thread char* _s3select_buff_ptr =0;
65
66 class s3select_allocator //s3select is the "owner"
67 {
68 private:
69
70 std::vector<char*> list_of_buff;
71 u_int32_t m_idx;
72
73 public:
74 #define __S3_ALLOCATION_BUFF__ (8*1024)
75 s3select_allocator():m_idx(0)
76 {
77 list_of_buff.push_back((char*)malloc(__S3_ALLOCATION_BUFF__));
78 }
79
80 void set_global_buff()
81 {
82 char* buff = list_of_buff.back();
83 _s3select_buff_ptr = &buff[ m_idx ];
84 }
85
86 void check_capacity(size_t sz)
87 {
88 if (sz>__S3_ALLOCATION_BUFF__)
89 {
90 throw base_s3select_exception("requested size too big", base_s3select_exception::s3select_exp_en_t::FATAL);
91 }
92
93 if ((m_idx + sz) >= __S3_ALLOCATION_BUFF__)
94 {
95 list_of_buff.push_back((char*)malloc(__S3_ALLOCATION_BUFF__));
96 m_idx = 0;
97 }
98 }
99
100 void inc(size_t sz)
101 {
102 m_idx += sz;
103 m_idx += sizeof(char*) - (m_idx % sizeof(char*)); //alignment
104 }
105
106 void zero()
107 {
108 //not a must, its for safty.
109 _s3select_buff_ptr=0;
110 }
111
112 virtual ~s3select_allocator()
113 {
114 for(auto b : list_of_buff)
115 {
116 free(b);
117 }
118 }
119 };
120
121 class __clt_allocator
122 {
123 public:
124 s3select_allocator* m_s3select_allocator;
125
126 public:
127
128 __clt_allocator():m_s3select_allocator(0) {}
129
130 void set(s3select_allocator* a)
131 {
132 m_s3select_allocator = a;
133 }
134 };
135
136 // placement new for allocation of all s3select objects on single(or few) buffers, deallocation of those objects is by releasing the buffer.
137 #define S3SELECT_NEW( type , ... ) [=]() \
138 { \
139 m_s3select_allocator->check_capacity(sizeof( type )); \
140 m_s3select_allocator->set_global_buff(); \
141 auto res=new (_s3select_buff_ptr) type(__VA_ARGS__); \
142 m_s3select_allocator->inc(sizeof( type )); \
143 m_s3select_allocator->zero(); \
144 return res; \
145 }();
146
147 class scratch_area
148 {
149
150 private:
151 std::vector<std::string_view> m_columns{128};
152 int m_upper_bound;
153
154 std::vector<std::pair<std::string, int >> m_column_name_pos;
155
156 public:
157
158 void set_column_pos(const char* n, int pos)//TODO use std::string
159 {
160 m_column_name_pos.push_back( std::pair<const char*, int>(n, pos));
161 }
162
163 void update(std::vector<char*> tokens, size_t num_of_tokens)
164 {
165 size_t i=0;
166 for(auto s : tokens)
167 {
168 if (i>=num_of_tokens)
169 {
170 break;
171 }
172
173 m_columns[i++] = s;
174 }
175 m_upper_bound = i;
176
177 }
178
179 int get_column_pos(const char* n)
180 {
181 //done only upon building the AST , not on "runtime"
182
183 std::vector<std::pair<std::string, int >>::iterator iter;
184
185 for( auto iter : m_column_name_pos)
186 {
187 if (!strcmp(iter.first.c_str(), n))
188 {
189 return iter.second;
190 }
191 }
192
193 return -1;
194 }
195
196 std::string_view get_column_value(int column_pos)
197 {
198
199 if ((column_pos >= m_upper_bound) || column_pos < 0)
200 {
201 throw base_s3select_exception("column_position_is_wrong", base_s3select_exception::s3select_exp_en_t::ERROR);
202 }
203
204 return m_columns[column_pos];
205 }
206
207 int get_num_of_columns()
208 {
209 return m_upper_bound;
210 }
211 };
212
213 class base_statement;
214 class projection_alias
215 {
216 //purpose: mapping between alias-name to base_statement*
217 //those routines are *NOT* intensive, works once per query parse time.
218
219 private:
220 std::vector< std::pair<std::string, base_statement*> > alias_map;
221
222 public:
223 std::vector< std::pair<std::string, base_statement*> >* get()
224 {
225 return &alias_map;
226 }
227
228 bool insert_new_entry(std::string alias_name, base_statement* bs)
229 {
230 //purpose: only unique alias names.
231
232 for(auto alias: alias_map)
233 {
234 if(alias.first.compare(alias_name) == 0)
235 {
236 return false; //alias name already exist
237 }
238
239 }
240 std::pair<std::string, base_statement*> new_alias(alias_name, bs);
241 alias_map.push_back(new_alias);
242
243 return true;
244 }
245
246 base_statement* search_alias(std::string alias_name)
247 {
248 for(auto alias: alias_map)
249 {
250 if(alias.first.compare(alias_name) == 0)
251 {
252 return alias.second; //refernce to execution node
253 }
254 }
255 return 0;
256 }
257 };
258
259 struct binop_plus
260 {
261 double operator()(double a, double b)
262 {
263 return a+b;
264 }
265 };
266
267 struct binop_minus
268 {
269 double operator()(double a, double b)
270 {
271 return a-b;
272 }
273 };
274
275 struct binop_mult
276 {
277 double operator()(double a, double b)
278 {
279 return a * b;
280 }
281 };
282
283 struct binop_div
284 {
285 double operator()(double a, double b)
286 {
287 return a / b;
288 }
289 };
290
291 struct binop_pow
292 {
293 double operator()(double a, double b)
294 {
295 return pow(a, b);
296 }
297 };
298
299 class value
300 {
301
302 public:
303 typedef union
304 {
305 int64_t num;
306 char* str;//TODO consider string_view
307 double dbl;
308 boost::posix_time::ptime* timestamp;
309 } value_t;
310
311 private:
312 value_t __val;
313 std::string m_to_string;
314 std::string m_str_value;
315
316 public:
317 enum class value_En_t
318 {
319 DECIMAL,
320 FLOAT,
321 STRING,
322 TIMESTAMP,
323 NA
324 } ;
325 value_En_t type;
326
327 value(int64_t n) : type(value_En_t::DECIMAL)
328 {
329 __val.num = n;
330 }
331 value(int n) : type(value_En_t::DECIMAL)
332 {
333 __val.num = n;
334 }
335 value(bool b) : type(value_En_t::DECIMAL)
336 {
337 __val.num = (int64_t)b;
338 }
339 value(double d) : type(value_En_t::FLOAT)
340 {
341 __val.dbl = d;
342 }
343 value(boost::posix_time::ptime* timestamp) : type(value_En_t::TIMESTAMP)
344 {
345 __val.timestamp = timestamp;
346 }
347
348 value(const char* s) : type(value_En_t::STRING)
349 {
350 m_str_value.assign(s);
351 __val.str = m_str_value.data();
352 }
353
354 value():type(value_En_t::NA)
355 {
356 __val.num=0;
357 }
358
359 bool is_number() const
360 {
361 if ((type == value_En_t::DECIMAL || type == value_En_t::FLOAT))
362 {
363 return true;
364 }
365
366 return false;
367 }
368
369 bool is_string() const
370 {
371 return type == value_En_t::STRING;
372 }
373 bool is_timestamp() const
374 {
375 return type == value_En_t::TIMESTAMP;
376 }
377
378
379 std::string& to_string() //TODO very intensive , must improve this
380 {
381
382 if (type != value_En_t::STRING)
383 {
384 if (type == value_En_t::DECIMAL)
385 {
386 m_to_string.assign( boost::lexical_cast<std::string>(__val.num) );
387 }
388 else if(type == value_En_t::FLOAT)
389 {
390 m_to_string = boost::lexical_cast<std::string>(__val.dbl);
391 }
392 else
393 {
394 m_to_string = to_simple_string( *__val.timestamp );
395 }
396 }
397 else
398 {
399 m_to_string.assign( __val.str );
400 }
401
402 return m_to_string;
403 }
404
405
406 value& operator=(value& o)
407 {
408 if(this->type == value_En_t::STRING)
409 {
410 m_str_value.assign(o.str());
411 __val.str = m_str_value.data();
412 }
413 else
414 {
415 this->__val = o.__val;
416 }
417
418 this->type = o.type;
419
420 return *this;
421 }
422
423 value& operator=(const char* s)
424 {
425 m_str_value.assign(s);
426 this->__val.str = m_str_value.data();
427 this->type = value_En_t::STRING;
428
429 return *this;
430 }
431
432 value& operator=(int64_t i)
433 {
434 this->__val.num = i;
435 this->type = value_En_t::DECIMAL;
436
437 return *this;
438 }
439
440 value& operator=(double d)
441 {
442 this->__val.dbl = d;
443 this->type = value_En_t::FLOAT;
444
445 return *this;
446 }
447
448 value& operator=(bool b)
449 {
450 this->__val.num = (int64_t)b;
451 this->type = value_En_t::DECIMAL;
452
453 return *this;
454 }
455
456 value& operator=(boost::posix_time::ptime* p)
457 {
458 this->__val.timestamp = p;
459 this->type = value_En_t::TIMESTAMP;
460
461 return *this;
462 }
463
464 int64_t i64()
465 {
466 return __val.num;
467 }
468
469 const char* str()
470 {
471 return __val.str;
472 }
473
474 double dbl()
475 {
476 return __val.dbl;
477 }
478
479 boost::posix_time::ptime* timestamp() const
480 {
481 return __val.timestamp;
482 }
483
484 bool operator<(const value& v)//basic compare operator , most itensive runtime operation
485 {
486 //TODO NA possible?
487 if (is_string() && v.is_string())
488 {
489 return strcmp(__val.str, v.__val.str) < 0;
490 }
491
492 if (is_number() && v.is_number())
493 {
494
495 if(type != v.type) //conversion //TODO find better way
496 {
497 if (type == value_En_t::DECIMAL)
498 {
499 return (double)__val.num < v.__val.dbl;
500 }
501 else
502 {
503 return __val.dbl < (double)v.__val.num;
504 }
505 }
506 else //no conversion
507 {
508 if(type == value_En_t::DECIMAL)
509 {
510 return __val.num < v.__val.num;
511 }
512 else
513 {
514 return __val.dbl < v.__val.dbl;
515 }
516
517 }
518 }
519
520 if(is_timestamp() && v.is_timestamp())
521 {
522 return *timestamp() < *(v.timestamp());
523 }
524
525 throw base_s3select_exception("operands not of the same type(numeric , string), while comparision");
526 }
527
528 bool operator>(const value& v) //basic compare operator , most itensive runtime operation
529 {
530 //TODO NA possible?
531 if (is_string() && v.is_string())
532 {
533 return strcmp(__val.str, v.__val.str) > 0;
534 }
535
536 if (is_number() && v.is_number())
537 {
538
539 if(type != v.type) //conversion //TODO find better way
540 {
541 if (type == value_En_t::DECIMAL)
542 {
543 return (double)__val.num > v.__val.dbl;
544 }
545 else
546 {
547 return __val.dbl > (double)v.__val.num;
548 }
549 }
550 else //no conversion
551 {
552 if(type == value_En_t::DECIMAL)
553 {
554 return __val.num > v.__val.num;
555 }
556 else
557 {
558 return __val.dbl > v.__val.dbl;
559 }
560
561 }
562 }
563
564 if(is_timestamp() && v.is_timestamp())
565 {
566 return *timestamp() > *(v.timestamp());
567 }
568
569 throw base_s3select_exception("operands not of the same type(numeric , string), while comparision");
570 }
571
572 bool operator==(const value& v) //basic compare operator , most itensive runtime operation
573 {
574 //TODO NA possible?
575 if (is_string() && v.is_string())
576 {
577 return strcmp(__val.str, v.__val.str) == 0;
578 }
579
580
581 if (is_number() && v.is_number())
582 {
583
584 if(type != v.type) //conversion //TODO find better way
585 {
586 if (type == value_En_t::DECIMAL)
587 {
588 return (double)__val.num == v.__val.dbl;
589 }
590 else
591 {
592 return __val.dbl == (double)v.__val.num;
593 }
594 }
595 else //no conversion
596 {
597 if(type == value_En_t::DECIMAL)
598 {
599 return __val.num == v.__val.num;
600 }
601 else
602 {
603 return __val.dbl == v.__val.dbl;
604 }
605
606 }
607 }
608
609 if(is_timestamp() && v.is_timestamp())
610 {
611 return *timestamp() == *(v.timestamp());
612 }
613
614 throw base_s3select_exception("operands not of the same type(numeric , string), while comparision");
615 }
616 bool operator<=(const value& v)
617 {
618 return !(*this>v);
619 }
620 bool operator>=(const value& v)
621 {
622 return !(*this<v);
623 }
624 bool operator!=(const value& v)
625 {
626 return !(*this == v);
627 }
628
629 template<typename binop> //conversion rules for arithmetical binary operations
630 value& compute(value& l, const value& r) //left should be this, it contain the result
631 {
632 binop __op;
633
634 if (l.is_string() || r.is_string())
635 {
636 throw base_s3select_exception("illegal binary operation with string");
637 }
638
639 if (l.type != r.type)
640 {
641 //conversion
642
643 if (l.type == value_En_t::DECIMAL)
644 {
645 l.__val.dbl = __op((double)l.__val.num, r.__val.dbl);
646 l.type = value_En_t::FLOAT;
647 }
648 else
649 {
650 l.__val.dbl = __op(l.__val.dbl, (double)r.__val.num);
651 l.type = value_En_t::FLOAT;
652 }
653 }
654 else
655 {
656 //no conversion
657
658 if (l.type == value_En_t::DECIMAL)
659 {
660 l.__val.num = __op(l.__val.num, r.__val.num );
661 l.type = value_En_t::DECIMAL;
662 }
663 else
664 {
665 l.__val.dbl = __op(l.__val.dbl, r.__val.dbl );
666 l.type = value_En_t::FLOAT;
667 }
668 }
669
670 return l;
671 }
672
673 value& operator+(const value& v)
674 {
675 return compute<binop_plus>(*this, v);
676 }
677
678 value& operator-(const value& v)
679 {
680 return compute<binop_minus>(*this, v);
681 }
682
683 value& operator*(const value& v)
684 {
685 return compute<binop_mult>(*this, v);
686 }
687
688 value& operator/(const value& v) // TODO handle division by zero
689 {
690 return compute<binop_div>(*this, v);
691 }
692
693 value& operator^(const value& v)
694 {
695 return compute<binop_pow>(*this, v);
696 }
697
698 };
699
700 class base_statement
701 {
702
703 protected:
704
705 scratch_area* m_scratch;
706 projection_alias* m_aliases;
707 bool is_last_call; //valid only for aggregation functions
708 bool m_is_cache_result;
709 value m_alias_result;
710 base_statement* m_projection_alias;
711 int m_eval_stack_depth;
712
713 public:
714 base_statement():m_scratch(0), is_last_call(false), m_is_cache_result(false), m_projection_alias(0), m_eval_stack_depth(0) {}
715 virtual value& eval() =0;
716 virtual base_statement* left()
717 {
718 return 0;
719 }
720 virtual base_statement* right()
721 {
722 return 0;
723 }
724 virtual std::string print(int ident) =0;//TODO complete it, one option to use level parametr in interface ,
725 virtual bool semantic() =0;//done once , post syntax , traverse all nodes and validate semantics.
726
727 virtual void traverse_and_apply(scratch_area* sa, projection_alias* pa)
728 {
729 m_scratch = sa;
730 m_aliases = pa;
731 if (left())
732 {
733 left()->traverse_and_apply(m_scratch, m_aliases);
734 }
735 if (right())
736 {
737 right()->traverse_and_apply(m_scratch, m_aliases);
738 }
739 }
740
741 virtual bool is_aggregate()
742 {
743 return false;
744 }
745 virtual bool is_column()
746 {
747 return false;
748 }
749
750 bool is_function();
751 bool is_aggregate_exist_in_expression(base_statement* e);//TODO obsolete ?
752 base_statement* get_aggregate();
753 bool is_nested_aggregate(base_statement* e);
754 bool is_binop_aggregate_and_column(base_statement* skip);
755
756 virtual void set_last_call()
757 {
758 is_last_call = true;
759 if(left())
760 {
761 left()->set_last_call();
762 }
763 if(right())
764 {
765 right()->set_last_call();
766 }
767 }
768
769 bool is_set_last_call()
770 {
771 return is_last_call;
772 }
773
774 void invalidate_cache_result()
775 {
776 m_is_cache_result = false;
777 }
778
779 bool is_result_cached()
780 {
781 return m_is_cache_result == true;
782 }
783
784 void set_result_cache(value& eval_result)
785 {
786 m_alias_result = eval_result;
787 m_is_cache_result = true;
788 }
789
790 void dec_call_stack_depth()
791 {
792 m_eval_stack_depth --;
793 }
794
795 value& get_result_cache()
796 {
797 return m_alias_result;
798 }
799
800 int& get_eval_call_depth()
801 {
802 m_eval_stack_depth++;
803 return m_eval_stack_depth;
804 }
805
806 virtual ~base_statement() {}
807
808 };
809
810 class variable : public base_statement
811 {
812
813 public:
814
815 enum class var_t
816 {
817 NA,
818 VAR,//schema column (i.e. age , price , ...)
819 COL_VALUE, //concrete value
820 POS, // CSV column number (i.e. _1 , _2 ... )
821 STAR_OPERATION, //'*'
822 } ;
823 var_t m_var_type;
824
825 private:
826
827 std::string _name;
828 int column_pos;
829 value var_value;
830 std::string m_star_op_result;
831 char m_star_op_result_charc[4096]; //TODO should be dynamic
832
833 const int undefined_column_pos = -1;
834 const int column_alias = -2;
835
836 public:
837 variable():m_var_type(var_t::NA), _name(""), column_pos(-1) {}
838
839 variable(int64_t i) : m_var_type(var_t::COL_VALUE), column_pos(-1), var_value(i) {}
840
841 variable(double d) : m_var_type(var_t::COL_VALUE), _name("#"), column_pos(-1), var_value(d) {}
842
843 variable(int i) : m_var_type(var_t::COL_VALUE), column_pos(-1), var_value(i) {}
844
845 variable(const std::string& n) : m_var_type(var_t::VAR), _name(n), column_pos(-1) {}
846
847 variable(const std::string& n, var_t tp) : m_var_type(var_t::NA)
848 {
849 if(tp == variable::var_t::POS)
850 {
851 _name = n;
852 m_var_type = tp;
853 int pos = atoi( n.c_str() + 1 ); //TODO >0 < (schema definition , semantic analysis)
854 column_pos = pos -1;// _1 is the first column ( zero position )
855 }
856 else if (tp == variable::var_t::COL_VALUE)
857 {
858 _name = "#";
859 m_var_type = tp;
860 column_pos = -1;
861 var_value = n.c_str();
862 }
863 else if (tp ==variable::var_t::STAR_OPERATION)
864 {
865 _name = "#";
866 m_var_type = tp;
867 column_pos = -1;
868 }
869 }
870
871 void operator=(value& v)
872 {
873 var_value = v;
874 }
875
876 void set_value(const char* s)
877 {
878 var_value = s;
879 }
880
881 void set_value(double d)
882 {
883 var_value = d;
884 }
885
886 void set_value(int64_t i)
887 {
888 var_value = i;
889 }
890
891 void set_value(boost::posix_time::ptime* p)
892 {
893 var_value = p;
894 }
895
896 virtual ~variable() {}
897
898 virtual bool is_column() //is reference to column.
899 {
900 if(m_var_type == var_t::VAR || m_var_type == var_t::POS)
901 {
902 return true;
903 }
904 return false;
905 }
906
907 value& get_value()
908 {
909 return var_value; //TODO is it correct
910 }
911 virtual value::value_En_t get_value_type()
912 {
913 return var_value.type;
914 }
915
916
917 value& star_operation() //purpose return content of all columns in a input stream
918 {
919
920
921 int i;
922 size_t pos=0;
923 int num_of_columns = m_scratch->get_num_of_columns();
924 for(i=0; i<num_of_columns-1; i++)
925 {
926 size_t len = m_scratch->get_column_value(i).size();
927 if((pos+len)>sizeof(m_star_op_result_charc))
928 {
929 throw base_s3select_exception("result line too long", base_s3select_exception::s3select_exp_en_t::FATAL);
930 }
931
932 memcpy(&m_star_op_result_charc[pos], m_scratch->get_column_value(i).data(), len);
933 pos += len;
934 m_star_op_result_charc[ pos ] = ',';//TODO need for another abstraction (per file type)
935 pos ++;
936
937 }
938
939 size_t len = m_scratch->get_column_value(i).size();
940 if((pos+len)>sizeof(m_star_op_result_charc))
941 {
942 throw base_s3select_exception("result line too long", base_s3select_exception::s3select_exp_en_t::FATAL);
943 }
944
945 memcpy(&m_star_op_result_charc[pos], m_scratch->get_column_value(i).data(), len);
946 m_star_op_result_charc[ pos + len ] = 0;
947 var_value = (char*)&m_star_op_result_charc[0];
948 return var_value;
949 }
950
951 virtual value& eval()
952 {
953 if (m_var_type == var_t::COL_VALUE)
954 {
955 return var_value; // a literal,could be deciml / float / string
956 }
957 else if(m_var_type == var_t::STAR_OPERATION)
958 {
959 return star_operation();
960 }
961 else if (column_pos == undefined_column_pos)
962 {
963 //done once , for the first time
964 column_pos = m_scratch->get_column_pos(_name.c_str());
965
966 if(column_pos>=0 && m_aliases->search_alias(_name.c_str()))
967 {
968 throw base_s3select_exception(std::string("multiple definition of column {") + _name + "} as schema-column and alias", base_s3select_exception::s3select_exp_en_t::FATAL);
969 }
970
971
972 if (column_pos == undefined_column_pos)
973 {
974 //not belong to schema , should exist in aliases
975 m_projection_alias = m_aliases->search_alias(_name.c_str());
976
977 //not enter this scope again
978 column_pos = column_alias;
979 if(m_projection_alias == 0)
980 {
981 throw base_s3select_exception(std::string("alias {")+_name+std::string("} or column not exist in schema"), base_s3select_exception::s3select_exp_en_t::FATAL);
982 }
983 }
984
985 }
986
987 if (m_projection_alias)
988 {
989 if (m_projection_alias->get_eval_call_depth()>2)
990 {
991 throw base_s3select_exception("number of calls exceed maximum size, probably a cyclic reference to alias", base_s3select_exception::s3select_exp_en_t::FATAL);
992 }
993
994 if (m_projection_alias->is_result_cached() == false)
995 {
996 var_value = m_projection_alias->eval();
997 m_projection_alias->set_result_cache(var_value);
998 }
999 else
1000 {
1001 var_value = m_projection_alias->get_result_cache();
1002 }
1003
1004 m_projection_alias->dec_call_stack_depth();
1005 }
1006 else
1007 {
1008 var_value = (char*)m_scratch->get_column_value(column_pos).data(); //no allocation. returning pointer of allocated space
1009 }
1010
1011 return var_value;
1012 }
1013
1014 virtual std::string print(int ident)
1015 {
1016 //std::string out = std::string(ident,' ') + std::string("var:") + std::to_string(var_value.__val.num);
1017 //return out;
1018 return std::string("#");//TBD
1019 }
1020
1021 virtual bool semantic()
1022 {
1023 return false;
1024 }
1025
1026 };
1027
1028 class arithmetic_operand : public base_statement
1029 {
1030
1031 public:
1032
1033 enum class cmp_t {NA, EQ, LE, LT, GT, GE, NE} ;
1034
1035 private:
1036 base_statement* l;
1037 base_statement* r;
1038
1039 cmp_t _cmp;
1040 value var_value;
1041
1042 public:
1043
1044 virtual bool semantic()
1045 {
1046 return true;
1047 }
1048
1049 virtual base_statement* left()
1050 {
1051 return l;
1052 }
1053 virtual base_statement* right()
1054 {
1055 return r;
1056 }
1057
1058 virtual std::string print(int ident)
1059 {
1060 //std::string out = std::string(ident,' ') + "compare:" += std::to_string(_cmp) + "\n" + l->print(ident-5) +r->print(ident+5);
1061 //return out;
1062 return std::string("#");//TBD
1063 }
1064
1065 virtual value& eval()
1066 {
1067
1068 switch (_cmp)
1069 {
1070 case cmp_t::EQ:
1071 return var_value = (l->eval() == r->eval());
1072 break;
1073
1074 case cmp_t::LE:
1075 return var_value = (l->eval() <= r->eval());
1076 break;
1077
1078 case cmp_t::GE:
1079 return var_value = (l->eval() >= r->eval());
1080 break;
1081
1082 case cmp_t::NE:
1083 return var_value = (l->eval() != r->eval());
1084 break;
1085
1086 case cmp_t::GT:
1087 return var_value = (l->eval() > r->eval());
1088 break;
1089
1090 case cmp_t::LT:
1091 return var_value = (l->eval() < r->eval());
1092 break;
1093
1094 default:
1095 throw base_s3select_exception("internal error");
1096 break;
1097 }
1098 }
1099
1100 arithmetic_operand(base_statement* _l, cmp_t c, base_statement* _r):l(_l), r(_r), _cmp(c) {}
1101
1102 virtual ~arithmetic_operand() {}
1103 };
1104
1105 class logical_operand : public base_statement
1106 {
1107
1108 public:
1109
1110 enum class oplog_t {AND, OR, NA};
1111
1112 private:
1113 base_statement* l;
1114 base_statement* r;
1115
1116 oplog_t _oplog;
1117 value var_value;
1118
1119 public:
1120
1121 virtual base_statement* left()
1122 {
1123 return l;
1124 }
1125 virtual base_statement* right()
1126 {
1127 return r;
1128 }
1129
1130 virtual bool semantic()
1131 {
1132 return true;
1133 }
1134
1135 logical_operand(base_statement* _l, oplog_t _o, base_statement* _r):l(_l), r(_r), _oplog(_o) {}
1136
1137 virtual ~logical_operand() {}
1138
1139 virtual std::string print(int ident)
1140 {
1141 //std::string out = std::string(ident, ' ') + "logical_operand:" += std::to_string(_oplog) + "\n" + l->print(ident - 5) + r->print(ident + 5);
1142 //return out;
1143 return std::string("#");//TBD
1144 }
1145 virtual value& eval()
1146 {
1147 if (_oplog == oplog_t::AND)
1148 {
1149 if (!l || !r)
1150 {
1151 throw base_s3select_exception("missing operand for logical and", base_s3select_exception::s3select_exp_en_t::FATAL);
1152 }
1153 return var_value = (l->eval().i64() && r->eval().i64());
1154 }
1155 else
1156 {
1157 if (!l || !r)
1158 {
1159 throw base_s3select_exception("missing operand for logical or", base_s3select_exception::s3select_exp_en_t::FATAL);
1160 }
1161 return var_value = (l->eval().i64() || r->eval().i64());
1162 }
1163 }
1164
1165 };
1166
1167 class mulldiv_operation : public base_statement
1168 {
1169
1170 public:
1171
1172 enum class muldiv_t {NA, MULL, DIV, POW} ;
1173
1174 private:
1175 base_statement* l;
1176 base_statement* r;
1177
1178 muldiv_t _mulldiv;
1179 value var_value;
1180
1181 public:
1182
1183 virtual base_statement* left()
1184 {
1185 return l;
1186 }
1187 virtual base_statement* right()
1188 {
1189 return r;
1190 }
1191
1192 virtual bool semantic()
1193 {
1194 return true;
1195 }
1196
1197 virtual std::string print(int ident)
1198 {
1199 //std::string out = std::string(ident, ' ') + "mulldiv_operation:" += std::to_string(_mulldiv) + "\n" + l->print(ident - 5) + r->print(ident + 5);
1200 //return out;
1201 return std::string("#");//TBD
1202 }
1203
1204 virtual value& eval()
1205 {
1206 switch (_mulldiv)
1207 {
1208 case muldiv_t::MULL:
1209 return var_value = l->eval() * r->eval();
1210 break;
1211
1212 case muldiv_t::DIV:
1213 return var_value = l->eval() / r->eval();
1214 break;
1215
1216 case muldiv_t::POW:
1217 return var_value = l->eval() ^ r->eval();
1218 break;
1219
1220 default:
1221 throw base_s3select_exception("internal error");
1222 break;
1223 }
1224 }
1225
1226 mulldiv_operation(base_statement* _l, muldiv_t c, base_statement* _r):l(_l), r(_r), _mulldiv(c) {}
1227
1228 virtual ~mulldiv_operation() {}
1229 };
1230
1231 class addsub_operation : public base_statement
1232 {
1233
1234 public:
1235
1236 enum class addsub_op_t {ADD, SUB, NA};
1237
1238 private:
1239 base_statement* l;
1240 base_statement* r;
1241
1242 addsub_op_t _op;
1243 value var_value;
1244
1245 public:
1246
1247 virtual base_statement* left()
1248 {
1249 return l;
1250 }
1251 virtual base_statement* right()
1252 {
1253 return r;
1254 }
1255
1256 virtual bool semantic()
1257 {
1258 return true;
1259 }
1260
1261 addsub_operation(base_statement* _l, addsub_op_t _o, base_statement* _r):l(_l), r(_r), _op(_o) {}
1262
1263 virtual ~addsub_operation() {}
1264
1265 virtual std::string print(int ident)
1266 {
1267 //std::string out = std::string(ident, ' ') + "addsub_operation:" += std::to_string(_op) + "\n" + l->print(ident - 5) + r->print(ident + 5);
1268 return std::string("#");//TBD
1269 }
1270
1271 virtual value& eval()
1272 {
1273 if (_op == addsub_op_t::NA) // -num , +num , unary-operation on number
1274 {
1275 if (l)
1276 {
1277 return var_value = l->eval();
1278 }
1279 else if (r)
1280 {
1281 return var_value = r->eval();
1282 }
1283 }
1284 else if (_op == addsub_op_t::ADD)
1285 {
1286 return var_value = (l->eval() + r->eval());
1287 }
1288 else
1289 {
1290 return var_value = (l->eval() - r->eval());
1291 }
1292
1293 return var_value;
1294 }
1295 };
1296
1297 class base_function
1298 {
1299
1300 protected:
1301 bool aggregate;
1302
1303 public:
1304 //TODO add semantic to base-function , it operate once on function creation
1305 // validate semantic on creation instead on run-time
1306 virtual bool operator()(std::vector<base_statement*>* args, variable* result) = 0;
1307 base_function() : aggregate(false) {}
1308 bool is_aggregate()
1309 {
1310 return aggregate == true;
1311 }
1312 virtual void get_aggregate_result(variable*) {}
1313
1314 virtual ~base_function() {}
1315 };
1316
1317
1318 };//namespace
1319
1320 #endif