[ Index ]

PHP Cross Reference of vtigercrm-6.1.0

title

Body

[close]

/include/Webservices/ -> VTQL_Parser.php (source)

   1  <?php
   2  /* Driver template for the PHP_VTQL_ParserrGenerator parser generator. (PHP port of LEMON)
   3  */
   4  
   5  /**
   6   * This can be used to store both the string representation of
   7   * a token, and any useful meta-data associated with the token.
   8   *
   9   * meta-data should be stored as an array
  10   */
  11  class VTQL_ParseryyToken implements ArrayAccess
  12  {
  13      public $string = '';
  14      public $metadata = array();
  15  
  16      function __construct($s, $m = array())
  17      {
  18          if ($s instanceof VTQL_ParseryyToken) {
  19              $this->string = $s->string;
  20              $this->metadata = $s->metadata;
  21          } else {
  22              $this->string = (string) $s;
  23              if ($m instanceof VTQL_ParseryyToken) {
  24                  $this->metadata = $m->metadata;
  25              } elseif (is_array($m)) {
  26                  $this->metadata = $m;
  27              }
  28          }
  29      }
  30  
  31      function __toString()
  32      {
  33          return $this->_string;
  34      }
  35  
  36      function offsetExists($offset)
  37      {
  38          return isset($this->metadata[$offset]);
  39      }
  40  
  41      function offsetGet($offset)
  42      {
  43          return $this->metadata[$offset];
  44      }
  45  
  46      function offsetSet($offset, $value)
  47      {
  48          if ($offset === null) {
  49              if (isset($value[0])) {
  50                  $x = ($value instanceof VTQL_ParseryyToken) ?
  51                      $value->metadata : $value;
  52                  $this->metadata = array_merge($this->metadata, $x);
  53                  return;
  54              }
  55              $offset = count($this->metadata);
  56          }
  57          if ($value === null) {
  58              return;
  59          }
  60          if ($value instanceof VTQL_ParseryyToken) {
  61              if ($value->metadata) {
  62                  $this->metadata[$offset] = $value->metadata;
  63              }
  64          } elseif ($value) {
  65              $this->metadata[$offset] = $value;
  66          }
  67      }
  68  
  69      function offsetUnset($offset)
  70      {
  71          unset($this->metadata[$offset]);
  72      }
  73  }
  74  
  75  /** The following structure represents a single element of the
  76   * parser's stack.  Information stored includes:
  77   *
  78   *   +  The state number for the parser at this level of the stack.
  79   *
  80   *   +  The value of the token stored at this level of the stack.
  81   *      (In other words, the "major" token.)
  82   *
  83   *   +  The semantic value stored at this level of the stack.  This is
  84   *      the information used by the action routines in the grammar.
  85   *      It is sometimes called the "minor" token.
  86   */
  87  class VTQL_ParseryyStackEntry
  88  {
  89      public $stateno;       /* The state-number */
  90      public $major;         /* The major token value.  This is the code
  91                       ** number for the token at this stack level */
  92      public $minor; /* The user-supplied minor token value.  This
  93                       ** is the value of the token  */
  94  };
  95  
  96  // code external to the class is included here
  97  
  98  // declare_class is output here
  99  #line 451 "e:\workspace\nonadmin\pkg\vtiger\extensions\Webservices\VTQL_parser.y"
 100  class VTQL_Parser#line 102 "e:\workspace\nonadmin\pkg\vtiger\extensions\Webservices\VTQL_parser.php"
 101  {
 102  /* First off, code is included which follows the "include_class" declaration
 103  ** in the input file. */
 104  #line 199 "e:\workspace\nonadmin\pkg\vtiger\extensions\Webservices\VTQL_parser.y"
 105  
 106  /*
 107  add this rule to add parenthesis support.
 108  condition ::= PARENOPEN expr_set expr(E) PARENCLOSE.
 109  sample format(for contacts) for generated sql object 
 110  Array ( 
 111      [column_list] => c4,c3,c2,c1 
 112      [tableName] => vtiger_crmentity,vtiger_contactdetails,vtiger_contactaddress,vtiger_contactsubdetails,vtiger_contactscf,vtiger_customerdetails 
 113      [where_condition] => Array ( 
 114          [column_operators] => Array ( 
 115              [0] => = 
 116              [1] => = 
 117              [2] => = 
 118              ) 
 119          [column_names] => Array ( 
 120              [0] => c1 
 121              [1] => c2 
 122              [2] => c3 
 123              ) 
 124          [column_values] => Array ( 
 125              [0] => 'llet me' 
 126              [1] => 45 
 127              [2] => -1 
 128              ) 
 129          //TO BE DONE
 130          [grouping] => Array (
 131              [0] => Array (
 132                  [0] => 1
 133                  [1] => 2
 134                  )
 135              )
 136          [operators] => Array ( 
 137              [0] => and 
 138              [1] => or 
 139              )
 140          )
 141      [orderby] => Array ( 
 142          [0] => c4 
 143          [1] => c5 
 144          )
 145      [select] => SELECT 
 146      [from] => from 
 147      [semi_colon] => ; 
 148  )*/
 149      private $out;
 150      public $lex;
 151      private $success ;
 152      private $query ;
 153      private $error_msg;
 154      private $syntax_error;
 155      private $user;
 156  function __construct($user, $lex,$out){
 157      if(!is_array($out)){
 158          $out = array();
 159      }
 160      $this->out = &$out;
 161      $this->lex = $lex;
 162      $this->success = false;
 163      $this->error_msg ='';
 164      $this->query = '';
 165      $this->syntax_error = false;
 166      $this->user = $user;
 167  }
 168  
 169  function __toString(){
 170      return $this->value."";
 171  }
 172  function buildSelectStmt($sqlDump){
 173      $meta = $sqlDump['meta'];
 174      $fieldcol = $meta->getFieldColumnMapping();
 175      $columnTable = $meta->getColumnTableMapping();
 176      $this->query = 'SELECT ';
 177      if(in_array('*', $sqlDump['column_list'])){
 178          $i=0;
 179          foreach($fieldcol as $field=>$col){
 180              if($i===0){
 181                  $this->query = $this->query.$columnTable[$col].'.'.$col;
 182                  $i++;
 183              }else{
 184                  $this->query = $this->query.','.$columnTable[$col].'.'.$col;
 185              }
 186          }
 187      }else if(in_array('count(*)', $sqlDump['column_list'])){
 188          $this->query = $this->query." COUNT(*)";
 189      }else{
 190          $i=0;
 191          foreach($sqlDump['column_list'] as $ind=>$field){
 192              if(!$fieldcol[$field]){
 193                  throw new WebServiceException(WebServiceErrorCode::$ACCESSDENIED, "Permission to access '.$field.' attribute denied.");
 194              }
 195              if($i===0){
 196                  $this->query = $this->query.$columnTable[$fieldcol[$field]].'.'.$fieldcol[$field];
 197                  $i++;
 198              }else{
 199                  $this->query = $this->query.','.$columnTable[$fieldcol[$field]].'.'.$fieldcol[$field];
 200              }
 201          }
 202      }
 203      $this->query = $this->query.' FROM '.$sqlDump['tableName'].$sqlDump['defaultJoinConditions'];
 204      $deletedQuery = $meta->getEntityDeletedQuery();
 205      $accessControlQuery = $meta->getEntityAccessControlQuery();
 206      $this->query = $this->query.' '.$accessControlQuery;
 207      if($sqlDump['where_condition']){
 208          if((sizeof($sqlDump['where_condition']['column_names']) == 
 209          sizeof($sqlDump['where_condition']['column_values'])) && 
 210          (sizeof($sqlDump['where_condition']['column_operators']) == sizeof($sqlDump['where_condition']['operators'])+1)){
 211              $this->query = $this->query.' WHERE (';
 212              $i=0;
 213              $referenceFields = $meta->getReferenceFieldDetails();
 214              $ownerFields = $meta->getOwnerFields();
 215              for(;$i<sizeof($sqlDump['where_condition']['column_values']);++$i){
 216                  if(!$fieldcol[$sqlDump['where_condition']['column_names'][$i]]){
 217                      throw new WebServiceException(WebServiceErrorCode::$ACCESSDENIED, "Permission to access ".$sqlDump['where_condition']['column_names'][$i]." attribute denied.");
 218                  }
 219                  $whereField = $sqlDump['where_condition']['column_names'][$i];
 220                  $whereOperator = $sqlDump['where_condition']['column_operators'][$i];
 221                  $whereValue = $sqlDump['where_condition']['column_values'][$i];
 222                  if(in_array($whereField,array_keys($referenceFields))){
 223                      if(is_array($whereValue)){
 224                          foreach($whereValue as $index=>$value){
 225                              if(strpos($value,'x')===false){
 226                                  throw new WebServiceException(WebServiceErrorCode::$INVALIDID,"Id specified is incorrect");
 227                              }
 228                          }
 229                          $whereValue = array_map(array($this, 'getReferenceValue'),$whereValue);
 230                      }else if(strpos($whereValue,'x')!==false){
 231                          $whereValue = $this->getReferenceValue($whereValue);
 232                          if(strcasecmp($whereOperator,'like')===0){
 233                              $whereValue = "'".$whereValue."'";
 234                          }
 235                      }else{
 236                          throw new WebServiceException(WebServiceErrorCode::$INVALIDID,"Id specified is incorrect");
 237                      }
 238                  }else if(in_array($whereField,$ownerFields)){
 239                      if(is_array($whereValue)){
 240                          $groupId = array_map(array($this, 'getOwner'),$whereValue);
 241                      }else{
 242                          $groupId = $this->getOwner($whereValue);
 243                          if(strcasecmp($whereOperator,'like')===0){
 244                              $groupId = "'$groupId'";
 245                          }
 246                      }
 247                      $whereValue = $groupId;
 248                  }
 249                  if(is_array($whereValue)){
 250                      $whereValue = "(".implode(',',$whereValue).")";
 251                  }elseif(strcasecmp($whereOperator, 'in') === 0){
 252                      $whereValue = "($whereValue)";
 253                  }
 254                  $this->query = $this->query.$columnTable[$fieldcol[$whereField]].'.'.
 255                                      $fieldcol[$whereField]." ".$whereOperator." ".$whereValue;
 256                  if($i <sizeof($sqlDump['where_condition']['column_values'])-1){
 257                      $this->query = $this->query.' ';
 258                      $this->query = $this->query.$sqlDump['where_condition']['operators'][$i].' ';
 259                  }
 260              }
 261          }else{
 262              throw new WebServiceException(WebServiceErrorCode::$QUERYSYNTAX, "columns data inappropriate");
 263          }
 264          $this->query = $this->query.")";
 265          $nextToken = ' AND ';
 266      }else{
 267          if(!empty($deletedQuery)){
 268              $nextToken = " WHERE ";
 269          }
 270      }
 271      if(strcasecmp('calendar',$this->out['moduleName'])===0){
 272          $this->query = $this->query." $nextToken activitytype='Task' AND ";
 273      }elseif(strcasecmp('events',$this->out['moduleName'])===0){
 274          $this->query = $this->query."$nextToken activitytype!='Emails' AND activitytype!='Task' AND ";
 275      }else if(strcasecmp('emails',$this->out['moduleName'])===0){
 276          $this->query = $this->query."$nextToken activitytype='Emails' AND ";
 277      }elseif(!empty($deletedQuery)){
 278          $this->query = $this->query.$nextToken;
 279      }
 280      
 281      $this->query = $this->query.' '.$deletedQuery;
 282      
 283      if($sqlDump['orderby']){
 284          $i=0;
 285          $this->query = $this->query.' ORDER BY ';
 286          foreach($sqlDump['orderby'] as $ind=>$field){
 287              if($i===0){
 288                  $this->query = $this->query.$columnTable[$fieldcol[$field]].".".$fieldcol[$field];
 289                  $i++;
 290              }else{
 291                  $this->query = $this->query.','.$columnTable[$fieldcol[$field]].".".$fieldcol[$field];
 292              }
 293          }
 294          if($sqlDump['sortOrder']) {
 295              $this->query .= ' '.$sqlDump['sortOrder'];
 296          }
 297      }
 298      if($sqlDump['limit']){
 299          $i=0;
 300          $offset =false;
 301          if(sizeof($sqlDump['limit'])>1){
 302              $offset = true;
 303          }
 304          $this->query = $this->query.' LIMIT ';
 305          foreach($sqlDump['limit'] as $ind=>$field){
 306              if(!$offset){
 307                  $field = ($field>100)? 100: $field;
 308              }
 309              if($i===0){
 310                  $this->query = $this->query.$field;
 311                  $i++;
 312                  $offset = false;
 313              }else{
 314                  $this->query = $this->query.','.$field;
 315              }
 316          }
 317      }else{
 318          $this->query = $this->query.' LIMIT 100';
 319      }
 320      $this->query = $this->query.';';
 321  }
 322  function getTables($sqlDump,$columns){
 323      $meta = $sqlDump['meta'];
 324      $coltable = $meta->getColumnTableMapping();
 325      $tables = array();
 326      foreach($columns as $ind=>$col){
 327          $tables[$coltable[$col]] = $coltable[$col];
 328      }
 329      $tables = array_keys($tables);
 330      return ($tables);
 331  }
 332  function getReferenceValue($whereValue){
 333      $whereValue = trim($whereValue,'\'"');
 334      $whereValue = vtws_getIdComponents($whereValue);
 335      $whereValue = $whereValue[1];
 336      return $whereValue;    
 337  }
 338  function getOwner($whereValue){
 339      $whereValue = trim($whereValue,'\'"');
 340      $whereValue = vtws_getIdComponents($whereValue);
 341      $whereValue = $whereValue[1];
 342      return $whereValue;
 343  }
 344  function isSuccess(){
 345      return $this->success;
 346  }
 347  function getErrorMsg(){
 348      return $this->error_msg;
 349  }
 350  function getQuery(){
 351      return $this->query;
 352  }
 353  function getObjectMetaData(){
 354      return $this->out['meta'];
 355  }
 356  #line 359 "e:\workspace\nonadmin\pkg\vtiger\extensions\Webservices\VTQL_parser.php"
 357  
 358  /* Next is all token values, as class constants
 359  */
 360  /* 
 361  ** These constants (all generated automatically by the parser generator)
 362  ** specify the various kinds of tokens (terminals) that the parser
 363  ** understands. 
 364  **
 365  ** Each symbol here is a terminal symbol in the grammar.
 366  */
 367      const SELECT                         =  1;
 368      const FRM                            =  2;
 369      const COLUMNNAME                     =  3;
 370      const ASTERISK                       =  4;
 371      const COUNT                          =  5;
 372      const PARENOPEN                      =  6;
 373      const PARENCLOSE                     =  7;
 374      const COMMA                          =  8;
 375      const TABLENAME                      =  9;
 376      const WHERE                          = 10;
 377      const LOGICAL_AND                    = 11;
 378      const LOGICAL_OR                     = 12;
 379      const VALUE                          = 13;
 380      const EQ                             = 14;
 381      const LT                             = 15;
 382      const GT                             = 16;
 383      const LTE                            = 17;
 384      const GTE                            = 18;
 385      const NE                             = 19;
 386      const IN                             = 20;
 387      const LIKE                           = 21;
 388      const ORDERBY                        = 22;
 389      const ASC                            = 23;
 390      const DESC                           = 24;
 391      const LIMIT                          = 25;
 392      const SEMICOLON                      = 26;
 393      const YY_NO_ACTION = 102;
 394      const YY_ACCEPT_ACTION = 101;
 395      const YY_ERROR_ACTION = 100;
 396  
 397  /* Next are that tables used to determine what action to take based on the
 398  ** current state and lookahead token.  These tables are used to implement
 399  ** functions that take a state number and lookahead value and return an
 400  ** action integer.  
 401  **
 402  ** Suppose the action integer is N.  Then the action is determined as
 403  ** follows
 404  **
 405  **   0 <= N < self::YYNSTATE                              Shift N.  That is,
 406  **                                                        push the lookahead
 407  **                                                        token onto the stack
 408  **                                                        and goto state N.
 409  **
 410  **   self::YYNSTATE <= N < self::YYNSTATE+self::YYNRULE   Reduce by rule N-YYNSTATE.
 411  **
 412  **   N == self::YYNSTATE+self::YYNRULE                    A syntax error has occurred.
 413  **
 414  **   N == self::YYNSTATE+self::YYNRULE+1                  The parser accepts its
 415  **                                                        input. (and concludes parsing)
 416  **
 417  **   N == self::YYNSTATE+self::YYNRULE+2                  No such action.  Denotes unused
 418  **                                                        slots in the yy_action[] table.
 419  **
 420  ** The action table is constructed as a single large static array $yy_action.
 421  ** Given state S and lookahead X, the action is computed as
 422  **
 423  **      self::$yy_action[self::$yy_shift_ofst[S] + X ]
 424  **
 425  ** If the index value self::$yy_shift_ofst[S]+X is out of range or if the value
 426  ** self::$yy_lookahead[self::$yy_shift_ofst[S]+X] is not equal to X or if
 427  ** self::$yy_shift_ofst[S] is equal to self::YY_SHIFT_USE_DFLT, it means that
 428  ** the action is not in the table and that self::$yy_default[S] should be used instead.  
 429  **
 430  ** The formula above is for computing the action when the lookahead is
 431  ** a terminal symbol.  If the lookahead is a non-terminal (as occurs after
 432  ** a reduce action) then the static $yy_reduce_ofst array is used in place of
 433  ** the static $yy_shift_ofst array and self::YY_REDUCE_USE_DFLT is used in place of
 434  ** self::YY_SHIFT_USE_DFLT.
 435  **
 436  ** The following are the tables generated in this section:
 437  **
 438  **  self::$yy_action        A single table containing all actions.
 439  **  self::$yy_lookahead     A table containing the lookahead for each entry in
 440  **                          yy_action.  Used to detect hash collisions.
 441  **  self::$yy_shift_ofst    For each state, the offset into self::$yy_action for
 442  **                          shifting terminals.
 443  **  self::$yy_reduce_ofst   For each state, the offset into self::$yy_action for
 444  **                          shifting non-terminals after a reduce.
 445  **  self::$yy_default       Default action for each state.
 446  */
 447      const YY_SZ_ACTTAB = 60;
 448  static public $yy_action = array(
 449   /*     0 */    36,   29,   28,   30,   31,   38,   39,   37,   41,   26,
 450   /*    10 */    18,   57,    7,   10,   27,   22,   50,   55,   17,   18,
 451   /*    20 */    15,    9,   12,   42,   43,   35,   25,   16,   33,   51,
 452   /*    30 */    52,  101,   56,   21,   47,    2,   19,   46,   52,   44,
 453   /*    40 */     3,   20,   53,   49,   24,   34,   23,    6,   40,   45,
 454   /*    50 */     1,    4,   13,   54,   11,   48,    5,   14,   32,    8,
 455      );
 456      static public $yy_lookahead = array(
 457   /*     0 */    14,   15,   16,   17,   18,   19,   20,   21,   41,   42,
 458   /*    10 */    43,   13,   44,   33,   46,   47,   11,   12,   42,   43,
 459   /*    20 */    37,   38,    2,   23,   24,    4,    5,   30,    8,    7,
 460   /*    30 */     8,   28,   29,   36,   35,   22,    4,   13,    8,    8,
 461   /*    40 */     1,    6,   26,    3,    8,    3,   13,    3,    7,   45,
 462   /*    50 */    40,    6,   34,   39,   31,   48,   10,   32,    9,   25,
 463  );
 464      const YY_SHIFT_USE_DFLT = -15;
 465      const YY_SHIFT_MAX = 27;
 466      static public $yy_shift_ofst = array(
 467   /*     0 */    39,   45,  -15,   21,  -15,  -15,  -14,    0,   33,   44,
 468   /*    10 */    34,   46,   49,   16,   13,    5,   20,   22,   -2,   41,
 469   /*    20 */    32,   42,   40,   36,   24,   35,   30,   31,
 470  );
 471      const YY_REDUCE_USE_DFLT = -34;
 472      const YY_REDUCE_MAX = 14;
 473      static public $yy_reduce_ofst = array(
 474   /*     0 */     3,  -33,  -32,   -3,  -24,  -17,   10,    4,    7,   14,
 475   /*    10 */    18,   25,   23,   -1,  -20,
 476  );
 477      static public $yyExpectedTokens = array(
 478          /* 0 */ array(1, ),
 479          /* 1 */ array(6, ),
 480          /* 2 */ array(),
 481          /* 3 */ array(4, 5, ),
 482          /* 4 */ array(),
 483          /* 5 */ array(),
 484          /* 6 */ array(14, 15, 16, 17, 18, 19, 20, 21, ),
 485          /* 7 */ array(23, 24, ),
 486          /* 8 */ array(13, ),
 487          /* 9 */ array(3, ),
 488          /* 10 */ array(25, ),
 489          /* 11 */ array(10, ),
 490          /* 12 */ array(9, ),
 491          /* 13 */ array(26, ),
 492          /* 14 */ array(22, ),
 493          /* 15 */ array(11, 12, ),
 494          /* 16 */ array(2, 8, ),
 495          /* 17 */ array(7, 8, ),
 496          /* 18 */ array(13, ),
 497          /* 19 */ array(7, ),
 498          /* 20 */ array(4, ),
 499          /* 21 */ array(3, ),
 500          /* 22 */ array(3, ),
 501          /* 23 */ array(8, ),
 502          /* 24 */ array(13, ),
 503          /* 25 */ array(6, ),
 504          /* 26 */ array(8, ),
 505          /* 27 */ array(8, ),
 506          /* 28 */ array(),
 507          /* 29 */ array(),
 508          /* 30 */ array(),
 509          /* 31 */ array(),
 510          /* 32 */ array(),
 511          /* 33 */ array(),
 512          /* 34 */ array(),
 513          /* 35 */ array(),
 514          /* 36 */ array(),
 515          /* 37 */ array(),
 516          /* 38 */ array(),
 517          /* 39 */ array(),
 518          /* 40 */ array(),
 519          /* 41 */ array(),
 520          /* 42 */ array(),
 521          /* 43 */ array(),
 522          /* 44 */ array(),
 523          /* 45 */ array(),
 524          /* 46 */ array(),
 525          /* 47 */ array(),
 526          /* 48 */ array(),
 527          /* 49 */ array(),
 528          /* 50 */ array(),
 529          /* 51 */ array(),
 530          /* 52 */ array(),
 531          /* 53 */ array(),
 532          /* 54 */ array(),
 533          /* 55 */ array(),
 534          /* 56 */ array(),
 535          /* 57 */ array(),
 536  );
 537      static public $yy_default = array(
 538   /*     0 */   100,   77,   91,   64,   77,   71,  100,   94,  100,  100,
 539   /*    10 */    96,   67,  100,  100,   87,   66,  100,  100,  100,  100,
 540   /*    20 */   100,  100,  100,   97,  100,  100,   74,   88,   80,   79,
 541   /*    30 */    81,   82,   65,   63,   60,   61,   78,   85,   83,   84,
 542   /*    40 */    62,   72,   92,   93,   90,   86,   98,   59,   95,   89,
 543   /*    50 */    69,   73,   76,   99,   68,   70,   58,   75,
 544  );
 545  /* The next thing included is series of defines which control
 546  ** various aspects of the generated parser.
 547  **    self::YYNOCODE      is a number which corresponds
 548  **                        to no legal terminal or nonterminal number.  This
 549  **                        number is used to fill in empty slots of the hash 
 550  **                        table.
 551  **    self::YYFALLBACK    If defined, this indicates that one or more tokens
 552  **                        have fall-back values which should be used if the
 553  **                        original value of the token will not parse.
 554  **    self::YYSTACKDEPTH  is the maximum depth of the parser's stack.
 555  **    self::YYNSTATE      the combined number of states.
 556  **    self::YYNRULE       the number of rules in the grammar
 557  **    self::YYERRORSYMBOL is the code number of the error symbol.  If not
 558  **                        defined, then do no error processing.
 559  */
 560      const YYNOCODE = 50;
 561      const YYSTACKDEPTH = 100;
 562      const YYNSTATE = 58;
 563      const YYNRULE = 42;
 564      const YYERRORSYMBOL = 27;
 565      const YYERRSYMDT = 'yy0';
 566      const YYFALLBACK = 0;
 567      /** The next table maps tokens into fallback tokens.  If a construct
 568       * like the following:
 569       * 
 570       *      %fallback ID X Y Z.
 571       *
 572       * appears in the grammer, then ID becomes a fallback token for X, Y,
 573       * and Z.  Whenever one of the tokens X, Y, or Z is input to the parser
 574       * but it does not parse, the type of the token is changed to ID and
 575       * the parse is retried before an error is thrown.
 576       */
 577      static public $yyFallback = array(
 578      );
 579      /**
 580       * Turn parser tracing on by giving a stream to which to write the trace
 581       * and a prompt to preface each trace message.  Tracing is turned off
 582       * by making either argument NULL 
 583       *
 584       * Inputs:
 585       * 
 586       * - A stream resource to which trace output should be written.
 587       *   If NULL, then tracing is turned off.
 588       * - A prefix string written at the beginning of every
 589       *   line of trace output.  If NULL, then tracing is
 590       *   turned off.
 591       *
 592       * Outputs:
 593       * 
 594       * - None.
 595       * @param resource
 596       * @param string
 597       */
 598      static function Trace($TraceFILE, $zTracePrompt)
 599      {
 600          if (!$TraceFILE) {
 601              $zTracePrompt = 0;
 602          } elseif (!$zTracePrompt) {
 603              $TraceFILE = 0;
 604          }
 605          self::$yyTraceFILE = $TraceFILE;
 606          self::$yyTracePrompt = $zTracePrompt;
 607      }
 608  
 609      /**
 610       * Output debug information to output (php://output stream)
 611       */
 612      static function PrintTrace()
 613      {
 614          self::$yyTraceFILE = fopen('php://output', 'w');
 615          self::$yyTracePrompt = '';
 616      }
 617  
 618      /**
 619       * @var resource|0
 620       */
 621      static public $yyTraceFILE;
 622      /**
 623       * String to prepend to debug output
 624       * @var string|0
 625       */
 626      static public $yyTracePrompt;
 627      /**
 628       * @var int
 629       */
 630      public $yyidx;                    /* Index of top element in stack */
 631      /**
 632       * @var int
 633       */
 634      public $yyerrcnt;                 /* Shifts left before out of the error */
 635      /**
 636       * @var array
 637       */
 638      public $yystack = array();  /* The parser's stack */
 639  
 640      /**
 641       * For tracing shifts, the names of all terminals and nonterminals
 642       * are required.  The following table supplies these names
 643       * @var array
 644       */
 645      static public $yyTokenName = array( 
 646    '$',             'SELECT',        'FRM',           'COLUMNNAME',  
 647    'ASTERISK',      'COUNT',         'PARENOPEN',     'PARENCLOSE',  
 648    'COMMA',         'TABLENAME',     'WHERE',         'LOGICAL_AND', 
 649    'LOGICAL_OR',    'VALUE',         'EQ',            'LT',          
 650    'GT',            'LTE',           'GTE',           'NE',          
 651    'IN',            'LIKE',          'ORDERBY',       'ASC',         
 652    'DESC',          'LIMIT',         'SEMICOLON',     'error',       
 653    'sql',           'select_statement',  'selectcol_list',  'table_list',  
 654    'where_condition',  'order_clause',  'limit_clause',  'end_stmt',    
 655    'selectcolumn_exp',  'condition',     'expr_set',      'expr',        
 656    'logical_term',  'valuelist',     'valueref',      'value_exp',   
 657    'column_group',  'clause',        'column_list',   'column_exp',  
 658    'limit_set',   
 659      );
 660  
 661      /**
 662       * For tracing reduce actions, the names of all rules are required.
 663       * @var array
 664       */
 665      static public $yyRuleName = array(
 666   /*   0 */ "sql ::= select_statement",
 667   /*   1 */ "select_statement ::= SELECT selectcol_list FRM table_list where_condition order_clause limit_clause end_stmt",
 668   /*   2 */ "selectcol_list ::= selectcolumn_exp COLUMNNAME",
 669   /*   3 */ "selectcol_list ::= ASTERISK",
 670   /*   4 */ "selectcol_list ::= COUNT PARENOPEN ASTERISK PARENCLOSE",
 671   /*   5 */ "selectcolumn_exp ::= selectcol_list COMMA",
 672   /*   6 */ "selectcolumn_exp ::=",
 673   /*   7 */ "table_list ::= TABLENAME",
 674   /*   8 */ "where_condition ::= WHERE condition",
 675   /*   9 */ "where_condition ::=",
 676   /*  10 */ "condition ::= expr_set expr",
 677   /*  11 */ "expr_set ::= condition LOGICAL_AND",
 678   /*  12 */ "expr_set ::= condition LOGICAL_OR",
 679   /*  13 */ "expr_set ::=",
 680   /*  14 */ "expr ::= COLUMNNAME logical_term valuelist",
 681   /*  15 */ "valuelist ::= PARENOPEN valueref PARENCLOSE",
 682   /*  16 */ "valuelist ::= valueref",
 683   /*  17 */ "valueref ::= value_exp VALUE",
 684   /*  18 */ "value_exp ::= valueref COMMA",
 685   /*  19 */ "value_exp ::=",
 686   /*  20 */ "logical_term ::= EQ",
 687   /*  21 */ "logical_term ::= LT",
 688   /*  22 */ "logical_term ::= GT",
 689   /*  23 */ "logical_term ::= LTE",
 690   /*  24 */ "logical_term ::= GTE",
 691   /*  25 */ "logical_term ::= NE",
 692   /*  26 */ "logical_term ::= IN",
 693   /*  27 */ "logical_term ::= LIKE",
 694   /*  28 */ "order_clause ::= ORDERBY column_group clause",
 695   /*  29 */ "order_clause ::=",
 696   /*  30 */ "column_group ::= column_list",
 697   /*  31 */ "column_list ::= column_exp COLUMNNAME",
 698   /*  32 */ "column_exp ::= column_list COMMA",
 699   /*  33 */ "column_exp ::=",
 700   /*  34 */ "clause ::= ASC",
 701   /*  35 */ "clause ::= DESC",
 702   /*  36 */ "clause ::=",
 703   /*  37 */ "limit_clause ::= LIMIT limit_set",
 704   /*  38 */ "limit_clause ::=",
 705   /*  39 */ "limit_set ::= VALUE",
 706   /*  40 */ "limit_set ::= VALUE COMMA VALUE",
 707   /*  41 */ "end_stmt ::= SEMICOLON",
 708      );
 709  
 710      /**
 711       * This function returns the symbolic name associated with a token
 712       * value.
 713       * @param int
 714       * @return string
 715       */
 716      function tokenName($tokenType)
 717      {
 718          if ($tokenType === 0) {
 719              return 'End of Input';
 720          }
 721          if ($tokenType > 0 && $tokenType < count(self::$yyTokenName)) {
 722              return self::$yyTokenName[$tokenType];
 723          } else {
 724              return "Unknown";
 725          }
 726      }
 727  
 728      /**
 729       * The following function deletes the value associated with a
 730       * symbol.  The symbol can be either a terminal or nonterminal.
 731       * @param int the symbol code
 732       * @param mixed the symbol's value
 733       */
 734      static function yy_destructor($yymajor, $yypminor)
 735      {
 736          switch ($yymajor) {
 737          /* Here is inserted the actions which take place when a
 738          ** terminal or non-terminal is destroyed.  This can happen
 739          ** when the symbol is popped from the stack during a
 740          ** reduce or during error processing or when a parser is 
 741          ** being destroyed before it is finished parsing.
 742          **
 743          ** Note: during a reduce, the only symbols destroyed are those
 744          ** which appear on the RHS of the rule, but which are not used
 745          ** inside the C code.
 746          */
 747              default:  break;   /* If no destructor action specified: do nothing */
 748          }
 749      }
 750  
 751      /**
 752       * Pop the parser's stack once.
 753       *
 754       * If there is a destructor routine associated with the token which
 755       * is popped from the stack, then call it.
 756       *
 757       * Return the major token number for the symbol popped.
 758       * @param VTQL_ParseryyParser
 759       * @return int
 760       */
 761      function yy_pop_parser_stack()
 762      {
 763          if (!count($this->yystack)) {
 764              return;
 765          }
 766          $yytos = array_pop($this->yystack);
 767          if (self::$yyTraceFILE && $this->yyidx >= 0) {
 768              fwrite(self::$yyTraceFILE,
 769                  self::$yyTracePrompt . 'Popping ' . self::$yyTokenName[$yytos->major] .
 770                      "\n");
 771          }
 772          $yymajor = $yytos->major;
 773          self::yy_destructor($yymajor, $yytos->minor);
 774          $this->yyidx--;
 775          return $yymajor;
 776      }
 777  
 778      /**
 779       * Deallocate and destroy a parser.  Destructors are all called for
 780       * all stack elements before shutting the parser down.
 781       */
 782      function __destruct()
 783      {
 784          while ($this->yyidx >= 0) {
 785              $this->yy_pop_parser_stack();
 786          }
 787          if (is_resource(self::$yyTraceFILE)) {
 788              fclose(self::$yyTraceFILE);
 789          }
 790      }
 791  
 792      /**
 793       * Based on the current state and parser stack, get a list of all
 794       * possible lookahead tokens
 795       * @param int
 796       * @return array
 797       */
 798      function yy_get_expected_tokens($token)
 799      {
 800          $state = $this->yystack[$this->yyidx]->stateno;
 801          $expected = self::$yyExpectedTokens[$state];
 802          if (in_array($token, self::$yyExpectedTokens[$state], true)) {
 803              return $expected;
 804          }
 805          $stack = $this->yystack;
 806          $yyidx = $this->yyidx;
 807          do {
 808              $yyact = $this->yy_find_shift_action($token);
 809              if ($yyact >= self::YYNSTATE && $yyact < self::YYNSTATE + self::YYNRULE) {
 810                  // reduce action
 811                  $done = 0;
 812                  do {
 813                      if ($done++ == 100) {
 814                          $this->yyidx = $yyidx;
 815                          $this->yystack = $stack;
 816                          // too much recursion prevents proper detection
 817                          // so give up
 818                          return array_unique($expected);
 819                      }
 820                      $yyruleno = $yyact - self::YYNSTATE;
 821                      $this->yyidx -= self::$yyRuleInfo[$yyruleno]['rhs'];
 822                      $nextstate = $this->yy_find_reduce_action(
 823                          $this->yystack[$this->yyidx]->stateno,
 824                          self::$yyRuleInfo[$yyruleno]['lhs']);
 825                      if (isset(self::$yyExpectedTokens[$nextstate])) {
 826                          $expected += self::$yyExpectedTokens[$nextstate];
 827                              if (in_array($token,
 828                                    self::$yyExpectedTokens[$nextstate], true)) {
 829                              $this->yyidx = $yyidx;
 830                              $this->yystack = $stack;
 831                              return array_unique($expected);
 832                          }
 833                      }
 834                      if ($nextstate < self::YYNSTATE) {
 835                          // we need to shift a non-terminal
 836                          $this->yyidx++;
 837                          $x = new VTQL_ParseryyStackEntry;
 838                          $x->stateno = $nextstate;
 839                          $x->major = self::$yyRuleInfo[$yyruleno]['lhs'];
 840                          $this->yystack[$this->yyidx] = $x;
 841                          continue 2;
 842                      } elseif ($nextstate == self::YYNSTATE + self::YYNRULE + 1) {
 843                          $this->yyidx = $yyidx;
 844                          $this->yystack = $stack;
 845                          // the last token was just ignored, we can't accept
 846                          // by ignoring input, this is in essence ignoring a
 847                          // syntax error!
 848                          return array_unique($expected);
 849                      } elseif ($nextstate === self::YY_NO_ACTION) {
 850                          $this->yyidx = $yyidx;
 851                          $this->yystack = $stack;
 852                          // input accepted, but not shifted (I guess)
 853                          return $expected;
 854                      } else {
 855                          $yyact = $nextstate;
 856                      }
 857                  } while (true);
 858              }
 859              break;
 860          } while (true);
 861          return array_unique($expected);
 862      }
 863  
 864      /**
 865       * Based on the parser state and current parser stack, determine whether
 866       * the lookahead token is possible.
 867       * 
 868       * The parser will convert the token value to an error token if not.  This
 869       * catches some unusual edge cases where the parser would fail.
 870       * @param int
 871       * @return bool
 872       */
 873      function yy_is_expected_token($token)
 874      {
 875          if ($token === 0) {
 876              return true; // 0 is not part of this
 877          }
 878          $state = $this->yystack[$this->yyidx]->stateno;
 879          if (in_array($token, self::$yyExpectedTokens[$state], true)) {
 880              return true;
 881          }
 882          $stack = $this->yystack;
 883          $yyidx = $this->yyidx;
 884          do {
 885              $yyact = $this->yy_find_shift_action($token);
 886              if ($yyact >= self::YYNSTATE && $yyact < self::YYNSTATE + self::YYNRULE) {
 887                  // reduce action
 888                  $done = 0;
 889                  do {
 890                      if ($done++ == 100) {
 891                          $this->yyidx = $yyidx;
 892                          $this->yystack = $stack;
 893                          // too much recursion prevents proper detection
 894                          // so give up
 895                          return true;
 896                      }
 897                      $yyruleno = $yyact - self::YYNSTATE;
 898                      $this->yyidx -= self::$yyRuleInfo[$yyruleno]['rhs'];
 899                      $nextstate = $this->yy_find_reduce_action(
 900                          $this->yystack[$this->yyidx]->stateno,
 901                          self::$yyRuleInfo[$yyruleno]['lhs']);
 902                      if (isset(self::$yyExpectedTokens[$nextstate]) &&
 903                            in_array($token, self::$yyExpectedTokens[$nextstate], true)) {
 904                          $this->yyidx = $yyidx;
 905                          $this->yystack = $stack;
 906                          return true;
 907                      }
 908                      if ($nextstate < self::YYNSTATE) {
 909                          // we need to shift a non-terminal
 910                          $this->yyidx++;
 911                          $x = new VTQL_ParseryyStackEntry;
 912                          $x->stateno = $nextstate;
 913                          $x->major = self::$yyRuleInfo[$yyruleno]['lhs'];
 914                          $this->yystack[$this->yyidx] = $x;
 915                          continue 2;
 916                      } elseif ($nextstate == self::YYNSTATE + self::YYNRULE + 1) {
 917                          $this->yyidx = $yyidx;
 918                          $this->yystack = $stack;
 919                          if (!$token) {
 920                              // end of input: this is valid
 921                              return true;
 922                          }
 923                          // the last token was just ignored, we can't accept
 924                          // by ignoring input, this is in essence ignoring a
 925                          // syntax error!
 926                          return false;
 927                      } elseif ($nextstate === self::YY_NO_ACTION) {
 928                          $this->yyidx = $yyidx;
 929                          $this->yystack = $stack;
 930                          // input accepted, but not shifted (I guess)
 931                          return true;
 932                      } else {
 933                          $yyact = $nextstate;
 934                      }
 935                  } while (true);
 936              }
 937              break;
 938          } while (true);
 939          return true;
 940      }
 941  
 942      /**
 943       * Find the appropriate action for a parser given the terminal
 944       * look-ahead token iLookAhead.
 945       *
 946       * If the look-ahead token is YYNOCODE, then check to see if the action is
 947       * independent of the look-ahead.  If it is, return the action, otherwise
 948       * return YY_NO_ACTION.
 949       * @param int The look-ahead token
 950       */
 951      function yy_find_shift_action($iLookAhead)
 952      {
 953          $stateno = $this->yystack[$this->yyidx]->stateno;
 954       
 955          /* if ($this->yyidx < 0) return self::YY_NO_ACTION;  */
 956          if (!isset(self::$yy_shift_ofst[$stateno])) {
 957              // no shift actions
 958              return self::$yy_default[$stateno];
 959          }
 960          $i = self::$yy_shift_ofst[$stateno];
 961          if ($i === self::YY_SHIFT_USE_DFLT) {
 962              return self::$yy_default[$stateno];
 963          }
 964          if ($iLookAhead == self::YYNOCODE) {
 965              return self::YY_NO_ACTION;
 966          }
 967          $i += $iLookAhead;
 968          if ($i < 0 || $i >= self::YY_SZ_ACTTAB ||
 969                self::$yy_lookahead[$i] != $iLookAhead) {
 970              if (count(self::$yyFallback) && $iLookAhead < count(self::$yyFallback)
 971                     && ($iFallback = self::$yyFallback[$iLookAhead]) != 0) {
 972                  if (self::$yyTraceFILE) {
 973                      fwrite(self::$yyTraceFILE, self::$yyTracePrompt . "FALLBACK " .
 974                          self::$yyTokenName[$iLookAhead] . " => " .
 975                          self::$yyTokenName[$iFallback] . "\n");
 976                  }
 977                  return $this->yy_find_shift_action($iFallback);
 978              }
 979              return self::$yy_default[$stateno];
 980          } else {
 981              return self::$yy_action[$i];
 982          }
 983      }
 984  
 985      /**
 986       * Find the appropriate action for a parser given the non-terminal
 987       * look-ahead token $iLookAhead.
 988       *
 989       * If the look-ahead token is self::YYNOCODE, then check to see if the action is
 990       * independent of the look-ahead.  If it is, return the action, otherwise
 991       * return self::YY_NO_ACTION.
 992       * @param int Current state number
 993       * @param int The look-ahead token
 994       */
 995      function yy_find_reduce_action($stateno, $iLookAhead)
 996      {
 997          /* $stateno = $this->yystack[$this->yyidx]->stateno; */
 998  
 999          if (!isset(self::$yy_reduce_ofst[$stateno])) {
1000              return self::$yy_default[$stateno];
1001          }
1002          $i = self::$yy_reduce_ofst[$stateno];
1003          if ($i == self::YY_REDUCE_USE_DFLT) {
1004              return self::$yy_default[$stateno];
1005          }
1006          if ($iLookAhead == self::YYNOCODE) {
1007              return self::YY_NO_ACTION;
1008          }
1009          $i += $iLookAhead;
1010          if ($i < 0 || $i >= self::YY_SZ_ACTTAB ||
1011                self::$yy_lookahead[$i] != $iLookAhead) {
1012              return self::$yy_default[$stateno];
1013          } else {
1014              return self::$yy_action[$i];
1015          }
1016      }
1017  
1018      /**
1019       * Perform a shift action.
1020       * @param int The new state to shift in
1021       * @param int The major token to shift in
1022       * @param mixed the minor token to shift in
1023       */
1024      function yy_shift($yyNewState, $yyMajor, $yypMinor)
1025      {
1026          $this->yyidx++;
1027          if ($this->yyidx >= self::YYSTACKDEPTH) {
1028              $this->yyidx--;
1029              if (self::$yyTraceFILE) {
1030                  fprintf(self::$yyTraceFILE, "%sStack Overflow!\n", self::$yyTracePrompt);
1031              }
1032              while ($this->yyidx >= 0) {
1033                  $this->yy_pop_parser_stack();
1034              }
1035              /* Here code is inserted which will execute if the parser
1036              ** stack ever overflows */
1037  #line 462 "e:\workspace\nonadmin\pkg\vtiger\extensions\Webservices\VTQL_parser.y"
1038  
1039      throw new WebServiceException(WebServiceErrorCode::$QUERYSYNTAX, "Parser stack overflow");
1040  #line 1046 "e:\workspace\nonadmin\pkg\vtiger\extensions\Webservices\VTQL_parser.php"
1041              return;
1042          }
1043          $yytos = new VTQL_ParseryyStackEntry;
1044          $yytos->stateno = $yyNewState;
1045          $yytos->major = $yyMajor;
1046          $yytos->minor = $yypMinor;
1047          array_push($this->yystack, $yytos);
1048          if (self::$yyTraceFILE && $this->yyidx > 0) {
1049              fprintf(self::$yyTraceFILE, "%sShift %d\n", self::$yyTracePrompt,
1050                  $yyNewState);
1051              fprintf(self::$yyTraceFILE, "%sStack:", self::$yyTracePrompt);
1052              for($i = 1; $i <= $this->yyidx; $i++) {
1053                  fprintf(self::$yyTraceFILE, " %s",
1054                      self::$yyTokenName[$this->yystack[$i]->major]);
1055              }
1056              fwrite(self::$yyTraceFILE,"\n");
1057          }
1058      }
1059  
1060      /**
1061       * The following table contains information about every rule that
1062       * is used during the reduce.
1063       *
1064       * <pre>
1065       * array(
1066       *  array(
1067       *   int $lhs;         Symbol on the left-hand side of the rule
1068       *   int $nrhs;     Number of right-hand side symbols in the rule
1069       *  ),...
1070       * );
1071       * </pre>
1072       */
1073      static public $yyRuleInfo = array(
1074    array( 'lhs' => 28, 'rhs' => 1 ),
1075    array( 'lhs' => 29, 'rhs' => 8 ),
1076    array( 'lhs' => 30, 'rhs' => 2 ),
1077    array( 'lhs' => 30, 'rhs' => 1 ),
1078    array( 'lhs' => 30, 'rhs' => 4 ),
1079    array( 'lhs' => 36, 'rhs' => 2 ),
1080    array( 'lhs' => 36, 'rhs' => 0 ),
1081    array( 'lhs' => 31, 'rhs' => 1 ),
1082    array( 'lhs' => 32, 'rhs' => 2 ),
1083    array( 'lhs' => 32, 'rhs' => 0 ),
1084    array( 'lhs' => 37, 'rhs' => 2 ),
1085    array( 'lhs' => 38, 'rhs' => 2 ),
1086    array( 'lhs' => 38, 'rhs' => 2 ),
1087    array( 'lhs' => 38, 'rhs' => 0 ),
1088    array( 'lhs' => 39, 'rhs' => 3 ),
1089    array( 'lhs' => 41, 'rhs' => 3 ),
1090    array( 'lhs' => 41, 'rhs' => 1 ),
1091    array( 'lhs' => 42, 'rhs' => 2 ),
1092    array( 'lhs' => 43, 'rhs' => 2 ),
1093    array( 'lhs' => 43, 'rhs' => 0 ),
1094    array( 'lhs' => 40, 'rhs' => 1 ),
1095    array( 'lhs' => 40, 'rhs' => 1 ),
1096    array( 'lhs' => 40, 'rhs' => 1 ),
1097    array( 'lhs' => 40, 'rhs' => 1 ),
1098    array( 'lhs' => 40, 'rhs' => 1 ),
1099    array( 'lhs' => 40, 'rhs' => 1 ),
1100    array( 'lhs' => 40, 'rhs' => 1 ),
1101    array( 'lhs' => 40, 'rhs' => 1 ),
1102    array( 'lhs' => 33, 'rhs' => 3 ),
1103    array( 'lhs' => 33, 'rhs' => 0 ),
1104    array( 'lhs' => 44, 'rhs' => 1 ),
1105    array( 'lhs' => 46, 'rhs' => 2 ),
1106    array( 'lhs' => 47, 'rhs' => 2 ),
1107    array( 'lhs' => 47, 'rhs' => 0 ),
1108    array( 'lhs' => 45, 'rhs' => 1 ),
1109    array( 'lhs' => 45, 'rhs' => 1 ),
1110    array( 'lhs' => 45, 'rhs' => 0 ),
1111    array( 'lhs' => 34, 'rhs' => 2 ),
1112    array( 'lhs' => 34, 'rhs' => 0 ),
1113    array( 'lhs' => 48, 'rhs' => 1 ),
1114    array( 'lhs' => 48, 'rhs' => 3 ),
1115    array( 'lhs' => 35, 'rhs' => 1 ),
1116      );
1117  
1118      /**
1119       * The following table contains a mapping of reduce action to method name
1120       * that handles the reduction.
1121       * 
1122       * If a rule is not set, it has no handler.
1123       */
1124      static public $yyReduceMap = array(
1125          1 => 1,
1126          2 => 2,
1127          3 => 3,
1128          4 => 4,
1129          7 => 7,
1130          11 => 11,
1131          12 => 11,
1132          14 => 14,
1133          17 => 17,
1134          20 => 20,
1135          21 => 21,
1136          22 => 22,
1137          23 => 23,
1138          24 => 24,
1139          25 => 25,
1140          26 => 26,
1141          27 => 27,
1142          31 => 31,
1143          34 => 34,
1144          35 => 35,
1145          39 => 39,
1146          40 => 40,
1147          41 => 41,
1148      );
1149      /* Beginning here are the reduction cases.  A typical example
1150      ** follows:
1151      **  #line <lineno> <grammarfile>
1152      **   function yy_r0($yymsp){ ... }           // User supplied code
1153      **  #line <lineno> <thisfile>
1154      */
1155  #line 5 "e:\workspace\nonadmin\pkg\vtiger\extensions\Webservices\VTQL_parser.y"
1156      function yy_r1(){ 
1157  if($this->yystack[$this->yyidx + -7]->minor){
1158  $this->out['select'] = $this->yystack[$this->yyidx + -7]->minor;
1159  }
1160  if($this->yystack[$this->yyidx + -5]->minor){
1161  $this->out['from'] = $this->yystack[$this->yyidx + -5]->minor ;
1162  }
1163  if(SEMI){
1164  $this->out['semi_colon'] = SEMI;
1165  }
1166  if($this->out['select']){
1167  $this->buildSelectStmt($this->out);
1168  }
1169      }
1170  #line 1176 "e:\workspace\nonadmin\pkg\vtiger\extensions\Webservices\VTQL_parser.php"
1171  #line 19 "e:\workspace\nonadmin\pkg\vtiger\extensions\Webservices\VTQL_parser.y"
1172      function yy_r2(){ 
1173  $this->out['column_list'][] = $this->yystack[$this->yyidx + 0]->minor;
1174      }
1175  #line 1181 "e:\workspace\nonadmin\pkg\vtiger\extensions\Webservices\VTQL_parser.php"
1176  #line 22 "e:\workspace\nonadmin\pkg\vtiger\extensions\Webservices\VTQL_parser.y"
1177      function yy_r3(){
1178  $this->out['column_list'][] = $this->yystack[$this->yyidx + 0]->minor;
1179      }
1180  #line 1186 "e:\workspace\nonadmin\pkg\vtiger\extensions\Webservices\VTQL_parser.php"
1181  #line 25 "e:\workspace\nonadmin\pkg\vtiger\extensions\Webservices\VTQL_parser.y"
1182      function yy_r4(){
1183  $this->out['column_list'][] = 'count(*)';
1184      }
1185  #line 1191 "e:\workspace\nonadmin\pkg\vtiger\extensions\Webservices\VTQL_parser.php"
1186  #line 30 "e:\workspace\nonadmin\pkg\vtiger\extensions\Webservices\VTQL_parser.y"
1187      function yy_r7(){
1188  if(!in_array("*", $this->out["column_list"]) && !in_array("count(*)", array_map(strtolower, $this->out["column_list"]))){
1189  if(!in_array("id",$this->out["column_list"])){
1190      $this->out["column_list"][] = "id";
1191  }
1192  }
1193  $moduleName = $this->yystack[$this->yyidx + 0]->minor;
1194  if(!$moduleName){
1195      $this->syntax_error = true;
1196      throw new WebServiceException(WebServiceErrorCode::$QUERYSYNTAX, "There is an syntax error in query");
1197  }
1198  global $adb;
1199  $handler = vtws_getModuleHandlerFromName($moduleName,$this->user);
1200  $objectMeta = $handler->getMeta();
1201  $this->out['moduleName'] = $moduleName;
1202  $this->out['tableName'] = implode(',',$objectMeta->getEntityTableList());
1203      }
1204  #line 1210 "e:\workspace\nonadmin\pkg\vtiger\extensions\Webservices\VTQL_parser.php"
1205  #line 50 "e:\workspace\nonadmin\pkg\vtiger\extensions\Webservices\VTQL_parser.y"
1206      function yy_r11(){
1207  $this->out['where_condition']['operators'][] = $this->yystack[$this->yyidx + 0]->minor;
1208      }
1209  #line 1215 "e:\workspace\nonadmin\pkg\vtiger\extensions\Webservices\VTQL_parser.php"
1210  #line 57 "e:\workspace\nonadmin\pkg\vtiger\extensions\Webservices\VTQL_parser.y"
1211      function yy_r14(){
1212  $this->out['columnDone']=true;
1213  $this->out['where_condition']['column_names'][] = $this->yystack[$this->yyidx + -2]->minor;
1214  if(strcmp($this->yystack[$this->yyidx + -2]->minor, 'id')===0){
1215  $prev = $this->out['where_condition']['column_values'][sizeof($this->out['where_condition']['column_values'])-1];
1216  if(is_array($prev)){
1217  $new = array();
1218  foreach($prev as $ind=>$val){
1219  $val = trim($val,'\'"');
1220  $value = vtws_getIdComponents($val);
1221  $new[] = $value[1];
1222  }
1223  $this->out['where_condition']['column_values'][sizeof($this->out['where_condition']['column_values'])-1] = $new;
1224  }else{
1225  $prev = trim($prev,'\'"');
1226  $value = vtws_getIdComponents($prev);
1227  if(strcasecmp($this->out['where_condition']['column_operators'][sizeof($this->out['where_condition']['column_operators'])-1],'like')===0){
1228  $value[1] = "'".$value[1]."'";
1229  }
1230  $this->out['where_condition']['column_values'][sizeof($this->out['where_condition']['column_values'])-1] = $value[1];
1231  }
1232  }
1233      }
1234  #line 1240 "e:\workspace\nonadmin\pkg\vtiger\extensions\Webservices\VTQL_parser.php"
1235  #line 82 "e:\workspace\nonadmin\pkg\vtiger\extensions\Webservices\VTQL_parser.y"
1236      function yy_r17(){
1237  $length = sizeof($this->out['where_condition']['column_values']);
1238  $pos = $length - 1;
1239  if($pos < 0){
1240  $pos = 0;
1241  }
1242  if(strcasecmp($this->out['where_condition']['column_operators'][$pos],"in")===0 && 
1243      !empty($this->out['where_condition']['column_values'][$pos]) && !$this->out['columnDone']){
1244  if(!is_array($this->out['where_condition']['column_values'][$pos])){
1245  $prev = $this->out['where_condition']['column_values'][$pos];
1246  $this->out['where_condition']['column_values'][$pos] = array();
1247  $this->out['where_condition']['column_values'][$pos][] = $prev;
1248  }
1249  $this->out['where_condition']['column_values'][$pos][] = $this->yystack[$this->yyidx + 0]->minor;
1250  }else{
1251  $this->out['columnDone'] = false;
1252  $this->out['where_condition']['column_values'][] = $this->yystack[$this->yyidx + 0]->minor;
1253  }
1254      }
1255  #line 1261 "e:\workspace\nonadmin\pkg\vtiger\extensions\Webservices\VTQL_parser.php"
1256  #line 103 "e:\workspace\nonadmin\pkg\vtiger\extensions\Webservices\VTQL_parser.y"
1257      function yy_r20(){
1258  $this->out['where_condition']['column_operators'][] = '=';
1259      }
1260  #line 1266 "e:\workspace\nonadmin\pkg\vtiger\extensions\Webservices\VTQL_parser.php"
1261  #line 106 "e:\workspace\nonadmin\pkg\vtiger\extensions\Webservices\VTQL_parser.y"
1262      function yy_r21(){
1263  $this->out['where_condition']['column_operators'][] = '<';
1264      }
1265  #line 1271 "e:\workspace\nonadmin\pkg\vtiger\extensions\Webservices\VTQL_parser.php"
1266  #line 109 "e:\workspace\nonadmin\pkg\vtiger\extensions\Webservices\VTQL_parser.y"
1267      function yy_r22(){
1268  $this->out['where_condition']['column_operators'][] = '>';
1269      }
1270  #line 1276 "e:\workspace\nonadmin\pkg\vtiger\extensions\Webservices\VTQL_parser.php"
1271  #line 112 "e:\workspace\nonadmin\pkg\vtiger\extensions\Webservices\VTQL_parser.y"
1272      function yy_r23(){
1273  $this->out['where_condition']['column_operators'][] = '<=';
1274      }
1275  #line 1281 "e:\workspace\nonadmin\pkg\vtiger\extensions\Webservices\VTQL_parser.php"
1276  #line 115 "e:\workspace\nonadmin\pkg\vtiger\extensions\Webservices\VTQL_parser.y"
1277      function yy_r24(){
1278  $this->out['where_condition']['column_operators'][] = '>=';
1279      }
1280  #line 1286 "e:\workspace\nonadmin\pkg\vtiger\extensions\Webservices\VTQL_parser.php"
1281  #line 118 "e:\workspace\nonadmin\pkg\vtiger\extensions\Webservices\VTQL_parser.y"
1282      function yy_r25(){
1283  $this->out['where_condition']['column_operators'][] = '!=';
1284      }
1285  #line 1291 "e:\workspace\nonadmin\pkg\vtiger\extensions\Webservices\VTQL_parser.php"
1286  #line 121 "e:\workspace\nonadmin\pkg\vtiger\extensions\Webservices\VTQL_parser.y"
1287      function yy_r26(){
1288  $this->out['where_condition']['column_operators'][] = 'IN';
1289      }
1290  #line 1296 "e:\workspace\nonadmin\pkg\vtiger\extensions\Webservices\VTQL_parser.php"
1291  #line 124 "e:\workspace\nonadmin\pkg\vtiger\extensions\Webservices\VTQL_parser.y"
1292      function yy_r27(){
1293  $this->out['where_condition']['column_operators'][] = 'LIKE';
1294      }
1295  #line 1301 "e:\workspace\nonadmin\pkg\vtiger\extensions\Webservices\VTQL_parser.php"
1296  #line 130 "e:\workspace\nonadmin\pkg\vtiger\extensions\Webservices\VTQL_parser.y"
1297      function yy_r31(){
1298  $this->out['orderby'][] = $this->yystack[$this->yyidx + 0]->minor;
1299      }
1300  #line 1306 "e:\workspace\nonadmin\pkg\vtiger\extensions\Webservices\VTQL_parser.php"
1301  #line 135 "e:\workspace\nonadmin\pkg\vtiger\extensions\Webservices\VTQL_parser.y"
1302      function yy_r34(){
1303  $this->out['sortOrder'] = 'ASC';
1304      }
1305  #line 1311 "e:\workspace\nonadmin\pkg\vtiger\extensions\Webservices\VTQL_parser.php"
1306  #line 138 "e:\workspace\nonadmin\pkg\vtiger\extensions\Webservices\VTQL_parser.y"
1307      function yy_r35(){
1308  $this->out['sortOrder'] = 'DESC';
1309      }
1310  #line 1316 "e:\workspace\nonadmin\pkg\vtiger\extensions\Webservices\VTQL_parser.php"
1311  #line 144 "e:\workspace\nonadmin\pkg\vtiger\extensions\Webservices\VTQL_parser.y"
1312      function yy_r39(){
1313  $this->out['limit'][] = $this->yystack[$this->yyidx + 0]->minor;
1314      }
1315  #line 1321 "e:\workspace\nonadmin\pkg\vtiger\extensions\Webservices\VTQL_parser.php"
1316  #line 147 "e:\workspace\nonadmin\pkg\vtiger\extensions\Webservices\VTQL_parser.y"
1317      function yy_r40(){
1318  $this->out['limit'][] = $this->yystack[$this->yyidx + -2]->minor;
1319  $this->out['limit'][] = $this->yystack[$this->yyidx + 0]->minor;
1320      }
1321  #line 1327 "e:\workspace\nonadmin\pkg\vtiger\extensions\Webservices\VTQL_parser.php"
1322  #line 151 "e:\workspace\nonadmin\pkg\vtiger\extensions\Webservices\VTQL_parser.y"
1323      function yy_r41(){
1324  global $adb;
1325  if(!$this->out['meta']){
1326  $module = $this->out['moduleName'];
1327  $handler = vtws_getModuleHandlerFromName($module,$this->user);
1328  $objectMeta = $handler->getMeta();
1329  $this->out['meta'] = $objectMeta;
1330  $meta = $this->out['meta'];
1331  $fieldcol = $meta->getFieldColumnMapping();
1332  $columns = array();
1333  if(in_array('*', $this->out['column_list'])){
1334  $columns = array_values($fieldcol);
1335  }elseif( !in_array('count(*)', array_map(strtolower, $this->out['column_list']))){
1336  foreach($this->out['column_list'] as $ind=>$field){
1337  $columns[] = $fieldcol[$field];
1338  }
1339  }
1340  if($this->out['where_condition']){
1341  foreach($this->out['where_condition']['column_names'] as $ind=>$field){
1342  $columns[] = $fieldcol[$field];
1343  }
1344  }
1345  $tables = $this->getTables($this->out, $columns);
1346  if(!in_array($objectMeta->getEntityBaseTable(), $tables)){
1347  $tables[] = $objectMeta->getEntityBaseTable();
1348  }
1349  $defaultTableList = $objectMeta->getEntityDefaultTableList();
1350  foreach($defaultTableList as $tableName){
1351  if(!in_array($tableName,$tables)){
1352  array_push($tables,$tableName);
1353  }
1354  }
1355  $firstTable = $objectMeta->getEntityBaseTable();
1356  $tabNameIndex = $objectMeta->getEntityTableIndexList();
1357  $firstIndex = $tabNameIndex[$firstTable];
1358  foreach($tables as $ind=>$table){
1359  if($firstTable!=$table){
1360      if(!isset($tabNameIndex[$table]) && $table == "vtiger_crmentity"){
1361          $this->out['defaultJoinConditions'] = $this->out['defaultJoinConditions']." LEFT JOIN $table ON $firstTable.$firstIndex=$table.crmid";
1362      }else{
1363          $this->out['defaultJoinConditions'] = $this->out['defaultJoinConditions']." LEFT JOIN $table ON $firstTable.$firstIndex=$table.{$tabNameIndex[$table]}";
1364      }
1365  }else{
1366      $this->out['tableName'] = $table;
1367  }
1368  }
1369  }
1370      }
1371  #line 1377 "e:\workspace\nonadmin\pkg\vtiger\extensions\Webservices\VTQL_parser.php"
1372  
1373      /**
1374       * placeholder for the left hand side in a reduce operation.
1375       * 
1376       * For a parser with a rule like this:
1377       * <pre>
1378       * rule(A) ::= B. { A = 1; }
1379       * </pre>
1380       * 
1381       * The parser will translate to something like:
1382       * 
1383       * <code>
1384       * function yy_r0(){$this->_retvalue = 1;}
1385       * </code>
1386       */
1387      private $_retvalue;
1388  
1389      /**
1390       * Perform a reduce action and the shift that must immediately
1391       * follow the reduce.
1392       * 
1393       * For a rule such as:
1394       * 
1395       * <pre>
1396       * A ::= B blah C. { dosomething(); }
1397       * </pre>
1398       * 
1399       * This function will first call the action, if any, ("dosomething();" in our
1400       * example), and then it will pop three states from the stack,
1401       * one for each entry on the right-hand side of the expression
1402       * (B, blah, and C in our example rule), and then push the result of the action
1403       * back on to the stack with the resulting state reduced to (as described in the .out
1404       * file)
1405       * @param int Number of the rule by which to reduce
1406       */
1407      function yy_reduce($yyruleno)
1408      {
1409          //int $yygoto;                     /* The next state */
1410          //int $yyact;                      /* The next action */
1411          //mixed $yygotominor;        /* The LHS of the rule reduced */
1412          //VTQL_ParseryyStackEntry $yymsp;            /* The top of the parser's stack */
1413          //int $yysize;                     /* Amount to pop the stack */
1414          $yymsp = $this->yystack[$this->yyidx];
1415          if (self::$yyTraceFILE && $yyruleno >= 0 
1416                && $yyruleno < count(self::$yyRuleName)) {
1417              fprintf(self::$yyTraceFILE, "%sReduce (%d) [%s].\n",
1418                  self::$yyTracePrompt, $yyruleno,
1419                  self::$yyRuleName[$yyruleno]);
1420          }
1421  
1422          $this->_retvalue = $yy_lefthand_side = null;
1423          if (array_key_exists($yyruleno, self::$yyReduceMap)) {
1424              // call the action
1425              $this->_retvalue = null;
1426              $this->{'yy_r' . self::$yyReduceMap[$yyruleno]}();
1427              $yy_lefthand_side = $this->_retvalue;
1428          }
1429          $yygoto = self::$yyRuleInfo[$yyruleno]['lhs'];
1430          $yysize = self::$yyRuleInfo[$yyruleno]['rhs'];
1431          $this->yyidx -= $yysize;
1432          for($i = $yysize; $i; $i--) {
1433              // pop all of the right-hand side parameters
1434              array_pop($this->yystack);
1435          }
1436          $yyact = $this->yy_find_reduce_action($this->yystack[$this->yyidx]->stateno, $yygoto);
1437          if ($yyact < self::YYNSTATE) {
1438              /* If we are not debugging and the reduce action popped at least
1439              ** one element off the stack, then we can push the new element back
1440              ** onto the stack here, and skip the stack overflow test in yy_shift().
1441              ** That gives a significant speed improvement. */
1442              if (!self::$yyTraceFILE && $yysize) {
1443                  $this->yyidx++;
1444                  $x = new VTQL_ParseryyStackEntry;
1445                  $x->stateno = $yyact;
1446                  $x->major = $yygoto;
1447                  $x->minor = $yy_lefthand_side;
1448                  $this->yystack[$this->yyidx] = $x;
1449              } else {
1450                  $this->yy_shift($yyact, $yygoto, $yy_lefthand_side);
1451              }
1452          } elseif ($yyact == self::YYNSTATE + self::YYNRULE + 1) {
1453              $this->yy_accept();
1454          }
1455      }
1456  
1457      /**
1458       * The following code executes when the parse fails
1459       * 
1460       * Code from %parse_fail is inserted here
1461       */
1462      function yy_parse_failed()
1463      {
1464          if (self::$yyTraceFILE) {
1465              fprintf(self::$yyTraceFILE, "%sFail!\n", self::$yyTracePrompt);
1466          }
1467          while ($this->yyidx >= 0) {
1468              $this->yy_pop_parser_stack();
1469          }
1470          /* Here code is inserted which will be executed whenever the
1471          ** parser fails */
1472  #line 456 "e:\workspace\nonadmin\pkg\vtiger\extensions\Webservices\VTQL_parser.y"
1473  
1474      if(!$this->syntax_error){
1475          throw new WebServiceException(WebServiceErrorCode::$QUERYSYNTAX, "Parsing failed");
1476      }
1477  #line 1484 "e:\workspace\nonadmin\pkg\vtiger\extensions\Webservices\VTQL_parser.php"
1478      }
1479  
1480      /**
1481       * The following code executes when a syntax error first occurs.
1482       * 
1483       * %syntax_error code is inserted here
1484       * @param int The major type of the error token
1485       * @param mixed The minor type of the error token
1486       */
1487      function yy_syntax_error($yymajor, $TOKEN)
1488      {
1489  #line 466 "e:\workspace\nonadmin\pkg\vtiger\extensions\Webservices\VTQL_parser.y"
1490  
1491      $synMsg = "Syntax Error on line " . $this->lex->linenum . ": token '" .$this->lex->value."' ";
1492      $expect = array();
1493      foreach ($this->yy_get_expected_tokens($yymajor) as $token) {
1494          $expect[] = self::$yyTokenName[$token];
1495      }
1496      $synMsg =$synMsg.('Unexpected ' . $this->tokenName($yymajor) . '(' . $TOKEN
1497          . '), expected one of: ' . implode(',', $expect));
1498      
1499      throw new WebServiceException(WebServiceErrorCode::$QUERYSYNTAX, $synMsg);
1500  #line 1508 "e:\workspace\nonadmin\pkg\vtiger\extensions\Webservices\VTQL_parser.php"
1501      }
1502  
1503      /**
1504       * The following is executed when the parser accepts
1505       * 
1506       * %parse_accept code is inserted here
1507       */
1508      function yy_accept()
1509      {
1510          if (self::$yyTraceFILE) {
1511              fprintf(self::$yyTraceFILE, "%sAccept!\n", self::$yyTracePrompt);
1512          }
1513          while ($this->yyidx >= 0) {
1514              $stack = $this->yy_pop_parser_stack();
1515          }
1516          /* Here code is inserted which will be executed whenever the
1517          ** parser accepts */
1518  #line 452 "e:\workspace\nonadmin\pkg\vtiger\extensions\Webservices\VTQL_parser.y"
1519  
1520          $this->success = true;
1521      #line 1530 "e:\workspace\nonadmin\pkg\vtiger\extensions\Webservices\VTQL_parser.php"
1522      }
1523  
1524      /**
1525       * The main parser program.
1526       * 
1527       * The first argument is the major token number.  The second is
1528       * the token value string as scanned from the input.
1529       *
1530       * @param int the token number
1531       * @param mixed the token value
1532       * @param mixed any extra arguments that should be passed to handlers
1533       */
1534      function doParse($yymajor, $yytokenvalue)
1535      {
1536  //        $yyact;            /* The parser action. */
1537  //        $yyendofinput;     /* True if we are at the end of input */
1538          $yyerrorhit = 0;   /* True if yymajor has invoked an error */
1539          
1540          /* (re)initialize the parser, if necessary */
1541          if ($this->yyidx === null || $this->yyidx < 0) {
1542              /* if ($yymajor == 0) return; // not sure why this was here... */
1543              $this->yyidx = 0;
1544              $this->yyerrcnt = -1;
1545              $x = new VTQL_ParseryyStackEntry;
1546              $x->stateno = 0;
1547              $x->major = 0;
1548              $this->yystack = array();
1549              array_push($this->yystack, $x);
1550          }
1551          $yyendofinput = ($yymajor==0);
1552          
1553          if (self::$yyTraceFILE) {
1554              fprintf(self::$yyTraceFILE, "%sInput %s\n",
1555                  self::$yyTracePrompt, self::$yyTokenName[$yymajor]);
1556          }
1557          
1558          do {
1559              $yyact = $this->yy_find_shift_action($yymajor);
1560              if ($yymajor < self::YYERRORSYMBOL &&
1561                    !$this->yy_is_expected_token($yymajor)) {
1562                  // force a syntax error
1563                  $yyact = self::YY_ERROR_ACTION;
1564              }
1565              if ($yyact < self::YYNSTATE) {
1566                  $this->yy_shift($yyact, $yymajor, $yytokenvalue);
1567                  $this->yyerrcnt--;
1568                  if ($yyendofinput && $this->yyidx >= 0) {
1569                      $yymajor = 0;
1570                  } else {
1571                      $yymajor = self::YYNOCODE;
1572                  }
1573              } elseif ($yyact < self::YYNSTATE + self::YYNRULE) {
1574                  $this->yy_reduce($yyact - self::YYNSTATE);
1575              } elseif ($yyact == self::YY_ERROR_ACTION) {
1576                  if (self::$yyTraceFILE) {
1577                      fprintf(self::$yyTraceFILE, "%sSyntax Error!\n",
1578                          self::$yyTracePrompt);
1579                  }
1580                  if (self::YYERRORSYMBOL) {
1581                      /* A syntax error has occurred.
1582                      ** The response to an error depends upon whether or not the
1583                      ** grammar defines an error token "ERROR".  
1584                      **
1585                      ** This is what we do if the grammar does define ERROR:
1586                      **
1587                      **  * Call the %syntax_error function.
1588                      **
1589                      **  * Begin popping the stack until we enter a state where
1590                      **    it is legal to shift the error symbol, then shift
1591                      **    the error symbol.
1592                      **
1593                      **  * Set the error count to three.
1594                      **
1595                      **  * Begin accepting and shifting new tokens.  No new error
1596                      **    processing will occur until three tokens have been
1597                      **    shifted successfully.
1598                      **
1599                      */
1600                      if ($this->yyerrcnt < 0) {
1601                          $this->yy_syntax_error($yymajor, $yytokenvalue);
1602                      }
1603                      $yymx = $this->yystack[$this->yyidx]->major;
1604                      if ($yymx == self::YYERRORSYMBOL || $yyerrorhit ){
1605                          if (self::$yyTraceFILE) {
1606                              fprintf(self::$yyTraceFILE, "%sDiscard input token %s\n",
1607                                  self::$yyTracePrompt, self::$yyTokenName[$yymajor]);
1608                          }
1609                          $this->yy_destructor($yymajor, $yytokenvalue);
1610                          $yymajor = self::YYNOCODE;
1611                      } else {
1612                          while ($this->yyidx >= 0 &&
1613                                   $yymx != self::YYERRORSYMBOL &&
1614          ($yyact = $this->yy_find_shift_action(self::YYERRORSYMBOL)) >= self::YYNSTATE
1615                                ){
1616                              $this->yy_pop_parser_stack();
1617                          }
1618                          if ($this->yyidx < 0 || $yymajor==0) {
1619                              $this->yy_destructor($yymajor, $yytokenvalue);
1620                              $this->yy_parse_failed();
1621                              $yymajor = self::YYNOCODE;
1622                          } elseif ($yymx != self::YYERRORSYMBOL) {
1623                              $u2 = 0;
1624                              $this->yy_shift($yyact, self::YYERRORSYMBOL, $u2);
1625                          }
1626                      }
1627                      $this->yyerrcnt = 3;
1628                      $yyerrorhit = 1;
1629                  } else {
1630                      /* YYERRORSYMBOL is not defined */
1631                      /* This is what we do if the grammar does not define ERROR:
1632                      **
1633                      **  * Report an error message, and throw away the input token.
1634                      **
1635                      **  * If the input token is $, then fail the parse.
1636                      **
1637                      ** As before, subsequent error messages are suppressed until
1638                      ** three input tokens have been successfully shifted.
1639                      */
1640                      if ($this->yyerrcnt <= 0) {
1641                          $this->yy_syntax_error($yymajor, $yytokenvalue);
1642                      }
1643                      $this->yyerrcnt = 3;
1644                      $this->yy_destructor($yymajor, $yytokenvalue);
1645                      if ($yyendofinput) {
1646                          $this->yy_parse_failed();
1647                      }
1648                      $yymajor = self::YYNOCODE;
1649                  }
1650              } else {
1651                  $this->yy_accept();
1652                  $yymajor = self::YYNOCODE;
1653              }            
1654          } while ($yymajor != self::YYNOCODE && $this->yyidx >= 0);
1655      }
1656  }


Generated: Fri Nov 28 20:08:37 2014 Cross-referenced by PHPXref 0.7.1