PageRenderTime 71ms CodeModel.GetById 22ms RepoModel.GetById 1ms app.codeStats 0ms

/tools/parser_sql/processors/FromProcessor.php

https://gitlab.com/staging06/myproject
PHP | 237 lines | 164 code | 30 blank | 43 comment | 23 complexity | f00b090e78d1b20877f6c5b03eca45e5 MD5 | raw file
  1. <?php
  2. /**
  3. * FromProcessor.php
  4. *
  5. * This file implements the processor for the FROM statements.
  6. *
  7. * Copyright (c) 2010-2013, Justin Swanhart
  8. * with contributions by André Rothe <arothe@phosco.info, phosco@gmx.de>
  9. *
  10. * All rights reserved.
  11. *
  12. * Redistribution and use in source and binary forms, with or without modification,
  13. * are permitted provided that the following conditions are met:
  14. *
  15. * * Redistributions of source code must retain the above copyright notice,
  16. * this list of conditions and the following disclaimer.
  17. * * Redistributions in binary form must reproduce the above copyright notice,
  18. * this list of conditions and the following disclaimer in the documentation
  19. * and/or other materials provided with the distribution.
  20. *
  21. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
  22. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  23. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
  24. * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  25. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
  26. * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
  27. * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  28. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  29. * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
  30. * DAMAGE.
  31. */
  32. require_once(dirname(__FILE__) . '/AbstractProcessor.php');
  33. require_once(dirname(__FILE__) . '/ExpressionListProcessor.php');
  34. require_once(dirname(__FILE__) . '/DefaultProcessor.php');
  35. require_once(dirname(__FILE__) . '/../utils/ExpressionType.php');
  36. /**
  37. *
  38. * This class processes the FROM statements.
  39. *
  40. * @author arothe
  41. *
  42. */
  43. class FromProcessor extends AbstractProcessor {
  44. protected function initParseInfo($parseInfo = false) {
  45. // first init
  46. if ($parseInfo === false) {
  47. $parseInfo = array('join_type' => "", 'saved_join_type' => "JOIN");
  48. }
  49. // loop init
  50. return array('expression' => "", 'token_count' => 0, 'table' => "", 'no_quotes' => "", 'alias' => false,
  51. 'join_type' => "", 'next_join_type' => "", 'saved_join_type' => $parseInfo['saved_join_type'],
  52. 'ref_type' => false, 'ref_expr' => false, 'base_expr' => false, 'sub_tree' => false,
  53. 'subquery' => "");
  54. }
  55. protected function processFromExpression(&$parseInfo) {
  56. $res = array();
  57. // exchange the join types (join_type is save now, saved_join_type holds the next one)
  58. $parseInfo['join_type'] = $parseInfo['saved_join_type']; // initialized with JOIN
  59. $parseInfo['saved_join_type'] = ($parseInfo['next_join_type'] ? $parseInfo['next_join_type'] : 'JOIN');
  60. // we have a reg_expr, so we have to parse it
  61. if ($parseInfo['ref_expr'] !== false) {
  62. $unparsed = $this->splitSQLIntoTokens($this->removeParenthesisFromStart($parseInfo['ref_expr']));
  63. // here we can get a comma separated list
  64. foreach ($unparsed as $k => $v) {
  65. if ($this->isCommaToken($v)) {
  66. $unparsed[$k] = "";
  67. }
  68. }
  69. $processor = new ExpressionListProcessor();
  70. $parseInfo['ref_expr'] = $processor->process($unparsed);
  71. }
  72. // there is an expression, we have to parse it
  73. if (substr(trim($parseInfo['table']), 0, 1) == '(') {
  74. $parseInfo['expression'] = $this->removeParenthesisFromStart($parseInfo['table']);
  75. if (preg_match("/^\\s*select/i", $parseInfo['expression'])) {
  76. $processor = new DefaultProcessor();
  77. $parseInfo['sub_tree'] = $processor->process($parseInfo['expression']);
  78. $res['expr_type'] = ExpressionType::SUBQUERY;
  79. } else {
  80. $tmp = $this->splitSQLIntoTokens($parseInfo['expression']);
  81. $parseInfo['sub_tree'] = $this->process($tmp);
  82. $res['expr_type'] = ExpressionType::TABLE_EXPRESSION;
  83. }
  84. } else {
  85. $res['expr_type'] = ExpressionType::TABLE;
  86. $res['table'] = $parseInfo['table'];
  87. $res['no_quotes'] = $this->revokeQuotation($parseInfo['table']);
  88. }
  89. $res['alias'] = $parseInfo['alias'];
  90. $res['join_type'] = $parseInfo['join_type'];
  91. $res['ref_type'] = $parseInfo['ref_type'];
  92. $res['ref_clause'] = $parseInfo['ref_expr'];
  93. $res['base_expr'] = trim($parseInfo['expression']);
  94. $res['sub_tree'] = $parseInfo['sub_tree'];
  95. return $res;
  96. }
  97. public function process($tokens) {
  98. $parseInfo = $this->initParseInfo();
  99. $expr = array();
  100. $skip_next = false;
  101. $i = 0;
  102. foreach ($tokens as $token) {
  103. $upper = strtoupper(trim($token));
  104. if ($skip_next && $token !== "") {
  105. $parseInfo['token_count']++;
  106. $skip_next = false;
  107. continue;
  108. } else {
  109. if ($skip_next) {
  110. continue;
  111. }
  112. }
  113. switch ($upper) {
  114. case 'OUTER':
  115. case 'LEFT':
  116. case 'RIGHT':
  117. case 'NATURAL':
  118. case 'CROSS':
  119. case ',':
  120. case 'JOIN':
  121. case 'INNER':
  122. break;
  123. default:
  124. $parseInfo['expression'] .= $token;
  125. if ($parseInfo['ref_type'] !== false) { // all after ON / USING
  126. $parseInfo['ref_expr'] .= $token;
  127. }
  128. break;
  129. }
  130. switch ($upper) {
  131. case 'AS':
  132. $parseInfo['alias'] = array('as' => true, 'name' => "", 'base_expr' => $token);
  133. $parseInfo['token_count']++;
  134. $n = 1;
  135. $str = "";
  136. while ($str == "") {
  137. $parseInfo['alias']['base_expr'] .= ($tokens[$i + $n] === "" ? " " : $tokens[$i + $n]);
  138. $str = trim($tokens[$i + $n]);
  139. ++$n;
  140. }
  141. $parseInfo['alias']['name'] = $str;
  142. $parseInfo['alias']['no_quotes'] = $this->revokeQuotation($str);
  143. $parseInfo['alias']['base_expr'] = trim($parseInfo['alias']['base_expr']);
  144. continue;
  145. case 'INDEX':
  146. if ($token_category == 'CREATE') {
  147. $token_category = $upper;
  148. continue 2;
  149. }
  150. break;
  151. case 'USING':
  152. case 'ON':
  153. $parseInfo['ref_type'] = $upper;
  154. $parseInfo['ref_expr'] = "";
  155. case 'CROSS':
  156. case 'USE':
  157. case 'FORCE':
  158. case 'IGNORE':
  159. case 'INNER':
  160. case 'OUTER':
  161. $parseInfo['token_count']++;
  162. continue;
  163. break;
  164. case 'FOR':
  165. $parseInfo['token_count']++;
  166. $skip_next = true;
  167. continue;
  168. break;
  169. case 'LEFT':
  170. case 'RIGHT':
  171. case 'STRAIGHT_JOIN':
  172. $parseInfo['next_join_type'] = $upper;
  173. break;
  174. case ',':
  175. $parseInfo['next_join_type'] = 'CROSS';
  176. case 'JOIN':
  177. if ($parseInfo['subquery']) {
  178. $parseInfo['sub_tree'] = $this->parse($this->removeParenthesisFromStart($parseInfo['subquery']));
  179. $parseInfo['expression'] = $parseInfo['subquery'];
  180. }
  181. $expr[] = $this->processFromExpression($parseInfo);
  182. $parseInfo = $this->initParseInfo($parseInfo);
  183. break;
  184. default:
  185. if ($upper === "") {
  186. continue; // ends the switch statement!
  187. }
  188. if ($parseInfo['token_count'] === 0) {
  189. if ($parseInfo['table'] === "") {
  190. $parseInfo['table'] = $token;
  191. $parseInfo['no_quotes'] = $this->revokeQuotation($token);
  192. }
  193. } elseif ($parseInfo['token_count'] === 1) {
  194. $parseInfo['alias'] = array('as' => false, 'name' => trim($token),
  195. 'no_quotes' => $this->revokeQuotation($token),
  196. 'base_expr' => trim($token));
  197. }
  198. $parseInfo['token_count']++;
  199. break;
  200. }
  201. ++$i;
  202. }
  203. $expr[] = $this->processFromExpression($parseInfo);
  204. return $expr;
  205. }
  206. }
  207. ?>