InfiniSQL  v0.1.2-alpha
Massive Scale Transaction Processing
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
Larxer.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2013 Mark Travis <mtravis15432+src@gmail.com>
3  * All rights reserved. No warranty, explicit or implicit, provided.
4  *
5  * This file is part of InfiniSQL(tm).
6 
7  * InfiniSQL is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License version 3
9  * as published by the Free Software Foundation.
10  *
11  * InfiniSQL is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with InfiniSQL. If not, see <http://www.gnu.org/licenses/>.
18  */
19 
29 #include "gch.h"
30 #include "Larxer.h"
31 #include <stdint.h>
32 #line 33 "Larxer.cc"
33 
35  class Schema *schemaPtr)
36 {
37  struct perlarxer pld;
38  pld.larxerPtr = this;
39  flexinit(&pld);
40  flexbuffer(instr, strlen(instr), pld.scaninfo);
41 
42  // must clear stack before parsing statement
43  while (!parsedStack.empty())
44  {
45  parsedStack.pop();
46  }
47 
48  if (yyparse(&pld))
49  {
50  statementPtr=NULL;
51  flexdestroy(pld.scaninfo);
52  return;
53  }
54 
55  flexdestroy(pld.scaninfo);
56  eatstack(taPtr, schemaPtr);
57 }
58 
60 {
61 }
62 
64 {
65  stackmember_s m = {type, string()};
66  parsedStack.push(m);
67 }
68 
69 void Larxer::pushstack(stacktypes_e type, int64_t val)
70 {
71  string stackstr(sizeof(val), '0');
72  memcpy(&stackstr[0], &val, sizeof(val));
73  parsedStack.push({type, stackstr});
74 }
75 
76 void Larxer::pushstack(stacktypes_e type, long double val)
77 {
78  printf("%s %i pushstack float %Lf\n", __FILE__, __LINE__, val);
79  string stackstr(sizeof(val), '0');
80  memcpy(&stackstr[0], &val, sizeof(val));
81  parsedStack.push({type, stackstr});
82 }
83 
84 void Larxer::pushstack(stacktypes_e type, const char *val)
85 {
86  parsedStack.push({type, string(val)});
87 }
88 
89 void Larxer::pushstack(stacktypes_e type, string &val)
90 {
91  parsedStack.push({type, val});
92 }
93 
94 void Larxer::pushoperand(char operandtype)
95 {
96  string str(&operandtype, 1);
98 }
99 
100 void Larxer::pushoperand(char operandtype, int64_t val)
101 {
102  string str(1 + sizeof(val), char(0));
103  str[0] = operandtype;
104  memcpy(&str[1], &val, sizeof(val));
106 }
107 
108 void Larxer::pushoperand(char operandtype, long double val)
109 {
110  string str(1 + sizeof(val), char(0));
111  str[0] = operandtype;
112  memcpy(&str[1], &val, sizeof(val));
114 }
115 
116 void Larxer::pushoperand(char operandtype, const char *val)
117 {
118  string str(1 + strlen(val), char(0));
119  str[0] = operandtype;
120  memcpy(&str[1], val, strlen(val));
122 }
123 
124 void Larxer::pushaggregate(char aggregatetype, const char *val)
125 {
126  string str(2 + strlen(val), char(0));
127  str[0] = OPERAND_AGGREGATE;
128  str[1] = aggregatetype;
129  memcpy(&str[2], val, strlen(val));
131 }
132 
134 {
135  stackmember_s item = parsedStack.top();
136  parsedStack.pop();
137  return item;
138 }
139 
140 int64_t Larxer::getintval(string &val)
141 {
142  int64_t rv;
143  memcpy(&rv, &val[0], sizeof(rv));
144  return rv;
145 }
146 
147 long double Larxer::getfloatval(string &val)
148 {
149  long double rv;
150  memcpy(&rv, &val[0], sizeof(rv));
151  return rv;
152 }
153 
154 void Larxer::eatstack(class TransactionAgent *taPtr, class Schema *schemaPtr)
155 {
156  statementPtr = new class Statement(taPtr, schemaPtr);
157  statementPtr->queries.push_back(Statement::query_s {});
159  currentQuery->instance = 0;
160 
161  while (!parsedStack.empty())
162  {
163  stackmember_s item = popstack();
164 
165  switch (item.type)
166  {
167  case TYPE_SELECT:
168  consumeSelect(item.val);
169  break;
170 
171  case TYPE_INSERT:
172  consumeInsert();
173  break;
174 
175  case TYPE_UPDATE:
176  consumeUpdate();
177  break;
178 
179  case TYPE_DELETE:
180  consumeDelete();
181  break;
182 
185  break;
186 
187  case TYPE_COMMIT:
189  break;
190 
191  case TYPE_BEGIN:
193  break;
194 
195  case TYPE_ROLLBACK:
197  break;
198 
199  default:
200  printf("%s %i anomaly %i\n", __FILE__, __LINE__, item.type);
201  }
202  }
203 }
204 
207 {
208  class Ast *rootnode = NULL;
209  class Ast *currentnode = NULL;
210 
211  if (parsedStack.empty())
212  {
213  printf("%s %i anomaly\n", __FILE__, __LINE__);
214  return NULL;
215  }
216 
217  stackmember_s item = popstack();
218 
219  if (item.type==TYPE_EXPRESSION)
220  {
221  /* if called as search_expression, then the next object might be an
222  * expression, which is already being handled ;-)
223  */
224  item = popstack();
225  }
226 
227  switch (item.type)
228  {
229  case TYPE_operator:
230  rootnode = new class Ast(NULL,
231  (operatortypes_e)getintval(item.val));
232  currentnode = rootnode;
233  break;
234 
235  case TYPE_operand:
236  rootnode = new class Ast(NULL, item.val);
237  return rootnode;
238 // break;
239 
240  default:
241  printf("%s %i anomaly %i\n", __FILE__, __LINE__, item.type);
242  parsedStack.push(item);
243  delete rootnode;
244  return NULL;
245  }
246 
247  while (1)
248  {
249  while (currentnode->rightchild != NULL && currentnode->leftchild != NULL)
250  {
251  if (currentnode->parent == NULL)
252  {
253  // no place left to allocate new node, therefore ast is complete
254  return rootnode;
255  }
256 
257  currentnode = currentnode->parent;
258  }
259 
260  if (parsedStack.empty())
261  {
262  printf("%s %i anomaly\n", __FILE__, __LINE__);
263  return NULL;
264  }
265 
266  item = popstack();
267 
268  class Ast *newnode=NULL;
269 
270  switch (item.type)
271  {
272  case TYPE_operator:
273  newnode = new class Ast(currentnode,
274  (operatortypes_e)getintval(item.val));
275  newnode->parent = currentnode;
276 
277  if (currentnode->rightchild == NULL)
278  {
279  currentnode->rightchild = newnode;
280  }
281  else
282  {
283  currentnode->leftchild = newnode;
284  }
285 
286  currentnode = newnode;
287  break;
288 
289  case TYPE_operand:
290  newnode = new class Ast(currentnode, item.val);
291 
292  if (currentnode->rightchild == NULL)
293  {
294  currentnode->rightchild = newnode;
295  }
296  else
297  {
298  currentnode->leftchild = newnode;
299  }
300 
301  if (item.val[0] == OPERAND_SUBQUERY) // subquery
302  {
303  int64_t sq = consumeSubquery();
304  newnode->operand.append(sizeof(sq), char(0));
305  memcpy(&newnode->operand[1], &sq, sizeof(sq));
306  }
307 
308  break;
309 
310  case TYPE_EXPRESSION: // noop, get next item
311  break;
312 
313  case TYPE_inobject:
314  consumeInobject();
315  break;
316 
317  case TYPE_inbegin:
318  // return rootnode;
319  break;
320 
321  default:
322  printf("%s %i anomaly %i\n", __FILE__, __LINE__, item.type);
323  parsedStack.push(item);
324  return rootnode;
325  }
326  }
327 }
328 
329 // return the index in the vector of queries (statementVars)
331 {
332  ssize_t currentQueryInstance = currentQuery->instance;
334  size_t i = statementPtr->queries.size()-1;
336  currentQuery->instance = i;
337 
338  stackmember_s item = popstack();
339 
340  if (item.type != TYPE_SELECT)
341  {
342  printf("%s %i anomaly %i\n", __FILE__, __LINE__, item.type);
343  return -2;
344  }
345 
346  consumeSelect(item.val);
347  currentQuery = &statementPtr->queries[currentQueryInstance];
348 
349  return i;
350 }
351 
353 {
354  if (parsedStack.top().type == TYPE_SUBQUERY)
355  {
356  parsedStack.pop();
359  return;
360  }
361  else
362  {
364 
365  while (parsedStack.top().type == TYPE_EXPRESSION)
366  {
367  parsedStack.pop();
369  }
370  }
371 }
372 
374 {
375  while (!parsedStack.empty())
376  {
377  printf("\tTYPE: %i\n", parsedStack.top().type);
378 
379  switch (parsedStack.top().type)
380  {
381  case TYPE_operator:
382  printf("\n");
383  int64_t arg;
384  memcpy(&arg, &parsedStack.top().val[0], sizeof(arg));
385 
386  switch ((operatortypes_e)arg)
387  {
388  case OPERATOR_NONE:
389  printf("NOOP (anomaly) ");
390  break;
391 
393  printf("CONCATENATION ");
394  break;
395 
396  case OPERATOR_ADDITION:
397  printf("+ ");
398  break;
399 
401  printf("- ");
402  break;
403 
405  printf("* ");
406  break;
407 
408  case OPERATOR_DIVISION:
409  printf("/ ");
410  break;
411 
412  case OPERATOR_NEGATION:
413  printf("NEGATE -");
414  break;
415 
416  case OPERATOR_AND:
417  printf("AND ");
418  break;
419 
420  case OPERATOR_OR:
421  printf("OR ");
422  break;
423 
424  case OPERATOR_NOT:
425  printf("NOT ");
426  break;
427 
428  case OPERATOR_TRUE:
429  printf("TRUE ");
430  break;
431 
432  case OPERATOR_FALSE:
433  printf("FALSE ");
434  break;
435 
436  case OPERATOR_UNKNOWN:
437  printf("UNKNOWN ");
438  break;
439 
440  case OPERATOR_EQ:
441  printf("= ");
442  break;
443 
444  case OPERATOR_NE:
445  printf("<> ");
446  break;
447 
448  case OPERATOR_LT:
449  printf("< ");
450  break;
451 
452  case OPERATOR_GT:
453  printf("> ");
454  break;
455 
456  case OPERATOR_LTE:
457  printf("<= ");
458  break;
459 
460  case OPERATOR_GTE:
461  printf(">= ");
462  break;
463 
464  case OPERATOR_BETWEEN:
465  printf("BETWEEN ");
466  break;
467 
468  case OPERATOR_ISNULL:
469  printf("ISNULL ");
470  break;
471 
472  case OPERATOR_IN:
473  printf("IN ");
474  break;
475 
476  case OPERATOR_LIKE:
477  printf("LIKE ");
478  break;
479 
480  case OPERATOR_EXISTS:
481  printf("EXISTS ");
482  break;
483 
484  case OPERATOR_UNIQUE:
485  printf("UNIQUE ");
486  break;
487 
488  case OPERATOR_BETWEENAND:
489  printf("BETWEENAND ");
490  break;
491 
492  default:
493  ;
494  }
495 
496  break;
497 
498  case TYPE_operand:
499  switch (parsedStack.top().val[0])
500  {
501  case OPERAND_STRING:
502  printf("%s ", parsedStack.top().val.c_str()+1);
503  break;
504 
505  case OPERAND_IDENTIFIER:
506  printf("%s ", parsedStack.top().val.c_str()+1);
507  break;
508 
509  case OPERAND_PARAMETER:
510  {
511  int64_t a;
512  memcpy(&a, &parsedStack.top().val[1], sizeof(a));
513  printf("$%li ", a);
514  }
515  break;
516 
517  case OPERAND_SUBQUERY:
518  printf("subquery, ");
519  break;
520 
521  case OPERAND_INTEGER:
522  {
523  int64_t a;
524  memcpy(&a, &parsedStack.top().val[1], sizeof(a));
525  printf("%li ", a);
526  }
527  break;
528 
529  case OPERAND_BOOLEAN:
530  if (parsedStack.top().val[1]=='t')
531  {
532  printf("boolean true\n");
533  }
534  else
535  {
536  printf("boolean false\n");
537  }
538 
539  break;
540 
541  case OPERAND_FLOAT:
542  {
543  long double a;
544  memcpy(&a, &parsedStack.top().val[1], sizeof(a));
545  printf("$%Lf ", a);
546  }
547  break;
548 
549  default:
550  ;
551  }
552 
553  break;
554 
555  default:
556  ;
557  }
558 
559  parsedStack.pop();
560  }
561 
562  printf("\n");
563 }
564 
565 void Larxer::consumeSelect(string &columns)
566 {
568 
569  while (!parsedStack.empty())
570  {
571  stackmember_s item = popstack();
572 
573  switch (item.type)
574  {
575  case TYPE_COLUMNS:
576  consumeColumns(getintval(columns));
577 
578  if (currentQuery->isforupdate==true)
579  {
581  }
582  else if (currentQuery->hasnolock==true)
583  {
585  }
586 
587  {
589  }
590 
591  return; // end of select statement
592 // break;
593 
594  case TYPE_FROM:
595  consumeFrom();
596  break;
597 
598  case TYPE_WHERE:
599  consumeWhere();
600  break;
601 
602  case TYPE_GROUPBY:
603  consumeGroupby();
604  break;
605 
606  case TYPE_HAVING:
607  consumeHaving();
608  break;
609 
610  case TYPE_FORUPDATE:
612  break;
613 
614  case TYPE_NOLOCK:
615  currentQuery->hasnolock=true;
616 
617  case TYPE_ORDERBY:
618  consumeOrderby();
619  break;
620 
621  default:
622  printf("%s %i anomaly %i\n", __FILE__, __LINE__, item.type);
623  }
624  }
625 }
626 
628 {
631 
632  while (!parsedStack.empty())
633  {
634  stackmember_s item = popstack();
635 
636  if (item.type == TYPE_EXPRESSION)
637  {
639  }
640  else
641  {
642  parsedStack.push(item);
643  consumeFrom();
644  }
645  }
646 }
647 
649 {
652 
653  while (!parsedStack.empty())
654  {
655  stackmember_s item = popstack();
656 
657  if (item.type == TYPE_WHERE)
658  {
659  consumeWhere();
660  }
661  else
662  {
663  if (item.type != TYPE_assignment)
664  {
665  parsedStack.push(item);
666  consumeFrom();
667  return;
668  }
669 
670  item = popstack(); // expression
671  class Ast *expr = consumeExpression();
672  stackmember_s item2 = popstack(); // identifier
673  currentQuery->assignments[item2.val.substr(1, string::npos)] = expr;
674  }
675  }
676 }
677 
679 {
682 
683  while (!parsedStack.empty())
684  {
685  stackmember_s item = popstack();
686 
687  if (item.type == TYPE_WHERE)
688  {
689  consumeWhere();
690  }
691  else
692  {
693  parsedStack.push(item);
694  consumeFrom();
695  }
696  }
697 }
698 
699 void Larxer::consumeColumns(int64_t numcolumns)
700 {
701  for (int64_t n=0; n < numcolumns; n++)
702  {
703  if (parsedStack.empty())
704  {
705  printf("%s %i anomaly parsedStack empty\n", __FILE__, __LINE__);
706  return;
707  }
708 
709  stackmember_s item = popstack();
710 
711  switch (item.type)
712  {
713  case TYPE_ASTERISK:
714  currentQuery->fromColumns.push_back("*");
715  break;
716 
717  case TYPE_operand:
718  currentQuery->fromColumns.push_back(item.val);
719  break;
720 
721  default:
722  printf("%s %i anomaly %i\n", __FILE__, __LINE__, item.type);
723  }
724  }
725 }
726 
728 {
729  if (!parsedStack.empty())
730  {
731  stackmember_s item = popstack();
732 
733  if (item.type==TYPE_operand)
734  {
735  currentQuery->table = item.val.substr(1, string::npos);
736  }
737  else
738  {
739  printf("%s %i anomaly %i\n", __FILE__, __LINE__, item.type);
740  }
741  }
742  else
743  {
744  printf("%s %i anomaly parsedStack empty\n", __FILE__, __LINE__);
745  }
746 }
747 
749 {
750  currentQuery->haswhere = true;
751 
752  if (!parsedStack.empty())
753  {
754  stackmember_s item = popstack();
755 
756  if (item.type==TYPE_search_condition)
757  {
759  }
760  else
761  {
762  printf("%s %i anomaly %i\n", __FILE__, __LINE__, item.type);
763  }
764  }
765  else
766  {
767  printf("%s %i anomaly parsedStack empty\n", __FILE__, __LINE__);
768  }
769 }
770 
772 {
773  currentQuery->hasgroupby = true;
774 
775  while (1)
776  {
777  if (parsedStack.empty())
778  {
779  return;
780  }
781 
782  stackmember_s item = popstack();
783 
784  if (item.type != TYPE_operand)
785  {
786  parsedStack.push(item);
787  return;
788  }
789 
790  if (item.val[0] != OPERAND_IDENTIFIER)
791  {
792  printf("%s %i anomaly %c\n", __FILE__, __LINE__, item.val[0]);
793  return;
794  }
795 
796  currentQuery->groupByList.push_back(item.val.substr(1, string::npos));
797  }
798 }
799 
801 {
802  currentQuery->hashaving = true;
803 
804  if (!parsedStack.empty())
805  {
806  stackmember_s item = popstack();
807 
808  if (item.type==TYPE_search_condition)
809  {
811  }
812  else
813  {
814  printf("%s %i anomaly %i\n", __FILE__, __LINE__, item.type);
815  }
816  }
817  else
818  {
819  printf("%s %i anomaly parsedStack empty\n", __FILE__, __LINE__);
820  }
821 }
822 
824 {
825  currentQuery->hasorderby = true;
826 
827  while (1)
828  {
829  stackmember_s item = popstack();
830 
831  if (item.type != TYPE_SORTSPECIFICATION)
832  {
833  parsedStack.push(item);
834  return;
835  }
836 
837  item = popstack();
838  stackmember_s item2 = popstack();
839 
840  if (item2.type == TYPE_ASC)
841  {
842  currentQuery->orderbylist.push_back({true, item.val});
843  }
844  else
845  {
846  currentQuery->orderbylist.push_back({false, item.val});
847  }
848  }
849 }
850 
852 {
854  stackmember_s item;
855 
856  while (!parsedStack.empty())
857  {
858  item=popstack();
859  currentQuery->storedProcedureArgs.push_back(item.val);
860  }
861 
862  currentQuery->storedProcedureArgs.pop_back();
863  currentQuery->storedProcedure=item.val.substr(1, string::npos);
864  std::reverse(currentQuery->storedProcedureArgs.begin(),
866 
867  return;
868 }