├── .gitignore ├── README.md ├── ROADMAP.md ├── composer.json ├── composer.lock ├── src └── Zebra │ └── MergeTable │ ├── Exception │ └── DBCallbackIllegalMergeTableException.php │ ├── MergeTable.php │ └── ResultMerge.php ├── tests ├── composer.json ├── composer.lock ├── sql_parser_test.php └── vendor │ ├── autoload.php │ ├── composer │ ├── ClassLoader.php │ ├── autoload_classmap.php │ ├── autoload_namespaces.php │ ├── autoload_psr4.php │ ├── autoload_real.php │ └── installed.json │ └── soundintheory │ └── php-sql-parser │ ├── README.md │ ├── composer.json │ └── src │ └── PHPSQL │ ├── Creator.php │ ├── Exception │ ├── Exception.php │ ├── InvalidParameter.php │ ├── UnableToCalculatePosition.php │ ├── UnableToCreateSQL.php │ └── UnsupportedFeature.php │ ├── Expression │ ├── Token.php │ └── Type.php │ ├── Parser.php │ └── Parser │ ├── Constants.php │ ├── Lexer.php │ ├── Lexer │ └── Splitter.php │ ├── PositionCalculator.php │ └── Utils.php └── vendor ├── autoload.php ├── composer ├── ClassLoader.php ├── autoload_classmap.php ├── autoload_namespaces.php ├── autoload_psr4.php ├── autoload_real.php └── installed.json └── soundintheory └── php-sql-parser ├── README.md ├── composer.json └── src └── PHPSQL ├── Creator.php ├── Exception ├── Exception.php ├── InvalidParameter.php ├── UnableToCalculatePosition.php ├── UnableToCreateSQL.php └── UnsupportedFeature.php ├── Expression ├── Token.php └── Type.php ├── Parser.php └── Parser ├── Constants.php ├── Lexer.php ├── Lexer └── Splitter.php ├── PositionCalculator.php └── Utils.php /.gitignore: -------------------------------------------------------------------------------- 1 | vendor/ 2 | composer.lock -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Zebra-MergeTable 2 | ================ 3 | 4 | 基于PHP实现的大表水平拆分,类似mysql合并表 5 | 一种不是很中肯的说法是,mysql能支持千万级别的数据,oracle能支持上亿级别的数据,超过这个级别,可能会出现性能瓶颈。 6 | 7 | 但实际应用场景中,我们经常会遇到如下情况: 8 | * 时间积累,表体积变大,业务要求不能迁移历史数据,查询性能下降 9 | * 表记录数不多,但体积很大,查询性能不好,例如文章、帖子表等 10 | * 表体积过大,索引过多,造成写入成本很高 11 | 12 | 以上只是举几个简单的例子,这几个场景下,都是不允许删除数据的。 13 | 14 | Zebra-MergeTable希望能够通过对表进行水平拆分的方式解决这些问题 15 | -------------- 16 | 目标: 17 | * 灵活的配置化拆表 18 | * 透明的拆表逻辑,在上层看来,仍然在操作一张表 19 | * 常用函数支持 20 | * 高效结果合并、排序、运算 21 | 22 | 哪些是我们暂时不会考虑的: 23 | * 独立于语言(暂时只支持PHP) 24 | * 复杂运算,例如去重、平均数等(分布式运算难题) -------------------------------------------------------------------------------- /ROADMAP.md: -------------------------------------------------------------------------------- 1 | Zebra-MergeTable线路图 2 | ============== 3 | 4 | ### 0.1:框架搭建 5 | * SQL语句分析构造器 6 | * 结果集合并工具 7 | * SUM、AVERAGE、COUNT、MAX、MIN等常用函数实现 8 | * GROUP BY、ORDER BY实现 9 | * 数据库驱动抽象层 10 | * 拆表配置化管理实现 11 | 12 | ### 0.3:功能补充及优化 13 | * 算法优化 14 | * 代码重构 -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "zebra/merge_table", 3 | "description": "database merge table", 4 | "license": "MIT", 5 | "keywords": ["mysql", "sql", "merge table"], 6 | "version": "v0.0.1", 7 | "authors": [ 8 | { 9 | "name": "Jenner, xufeng", 10 | "email": "hypxm@qq.com", 11 | "homepage" : "http://www.huyanping.cn" 12 | } 13 | ], 14 | "require": { 15 | "php": ">=5.3.0", 16 | "soundintheory/php-sql-parser": "1.0" 17 | }, 18 | 19 | "autoload": { 20 | "psr-0": { 21 | "Zebra\\MergeTable": "src/" 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /composer.lock: -------------------------------------------------------------------------------- 1 | { 2 | "_readme": [ 3 | "This file locks the dependencies of your project to a known state", 4 | "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", 5 | "This file is @generated automatically" 6 | ], 7 | "hash": "c9ad558d543a86f5fabcd4fe648255d4", 8 | "packages": [ 9 | { 10 | "name": "soundintheory/php-sql-parser", 11 | "version": "1.0", 12 | "source": { 13 | "type": "git", 14 | "url": "https://github.com/soundintheory/php-sql-parser.git", 15 | "reference": "dcb81216a13be124d21711b8fefb6e80db7af472" 16 | }, 17 | "dist": { 18 | "type": "zip", 19 | "url": "https://api.github.com/repos/soundintheory/php-sql-parser/zipball/dcb81216a13be124d21711b8fefb6e80db7af472", 20 | "reference": "dcb81216a13be124d21711b8fefb6e80db7af472", 21 | "shasum": "" 22 | }, 23 | "require": { 24 | "php": ">=5.3.3" 25 | }, 26 | "type": "library", 27 | "autoload": { 28 | "psr-0": { 29 | "PHPSQL": "src/" 30 | } 31 | }, 32 | "notification-url": "https://packagist.org/downloads/", 33 | "license": [ 34 | "BSD-2-Clause" 35 | ], 36 | "authors": [ 37 | { 38 | "name": "André Rothe", 39 | "email": "phosco@gmx.de", 40 | "homepage": "https://www.phosco.info", 41 | "role": "Committer" 42 | }, 43 | { 44 | "name": "Justin Swanhart", 45 | "email": "greenlion@gmail.com", 46 | "homepage": "http://code.google.com/u/greenlion@gmail.com/", 47 | "role": "Owner" 48 | }, 49 | { 50 | "name": "Andy White", 51 | "homepage": "https://github.com/soundintheory", 52 | "role": "maintainer" 53 | }, 54 | { 55 | "name": "Dan Vande More", 56 | "homepage": "https://github.com/fimbulvetr", 57 | "role": "contributor" 58 | } 59 | ], 60 | "description": "SQL parsing tools for PHP", 61 | "time": "2013-08-09 21:16:50" 62 | } 63 | ], 64 | "packages-dev": [], 65 | "aliases": [], 66 | "minimum-stability": "stable", 67 | "stability-flags": [], 68 | "prefer-stable": false, 69 | "platform": { 70 | "php": ">=5.3.0" 71 | }, 72 | "platform-dev": [] 73 | } 74 | -------------------------------------------------------------------------------- /src/Zebra/MergeTable/Exception/DBCallbackIllegalMergeTableException.php: -------------------------------------------------------------------------------- 1 | database_callback = $database_callback; 45 | 46 | if (!is_callable($sql_error_handle)) { 47 | throw new SQLExecuteErrorException; 48 | } 49 | $this->sql_error_handle = $sql_error_handle; 50 | } 51 | 52 | /** 53 | * @param $table_name 添加合并表 54 | */ 55 | public function addTable($table_name) 56 | { 57 | $this->tables[] = $table_name; 58 | } 59 | 60 | /** 61 | * @param $query 执行查询,返回结果 62 | */ 63 | public function fetchAll($query) 64 | { 65 | //获取查询结果 66 | $parser = new \PHPSQL\Parser($query); 67 | $parsed_query = $parser->parsed; 68 | 69 | $result = $this->getAllTableResult($parsed_query); 70 | //合并结果 71 | $result_merge_model = new ResultMerge(); 72 | $merge_result = $result_merge_model->merge($result, $parsed_query); 73 | //返回结果 74 | return $merge_result; 75 | } 76 | 77 | protected function getAllTableResult($parsed_query) 78 | { 79 | $creator = new \PHPSQL\Creator(); 80 | try { 81 | foreach ($this->tables as $table) { 82 | $parsed = $parsed_query; 83 | $parsed['FROM'][0]['table'] = $table; 84 | $query = $creator->create($parsed); 85 | $temp_result = $this->database_callback($query); 86 | if ($temp_result === false) { 87 | return false; 88 | } 89 | 90 | $result[$table] = $temp_result; 91 | } 92 | } catch (\Exception $e) { 93 | if (!empty($this->error_callback)) { 94 | $this->sql_error_handle($query); 95 | } else { 96 | throw $e; 97 | } 98 | } 99 | 100 | return $result; 101 | } 102 | } -------------------------------------------------------------------------------- /src/Zebra/MergeTable/ResultMerge.php: -------------------------------------------------------------------------------- 1 | initFieldFunction($parsed_query); 23 | $this->initGroup($parsed_query); 24 | $this->initOrder($parsed_query); 25 | 26 | if(!empty($this->group)){ 27 | $merge_result = $this->groupResult($data); 28 | } 29 | if(!empty($this->order)){ 30 | $merge_result = $this->orderResult($data); 31 | } 32 | return $merge_result; 33 | } 34 | 35 | protected function orderResult(array $data){ 36 | $params[] = $data; 37 | foreach($this->order as $order){ 38 | $params[] = $order['field']; 39 | if(strtolower($order['direction'])=='desc'){ 40 | $paras[] = SORT_DESC; 41 | }else{ 42 | $params[] = SORT_ASC; 43 | } 44 | } 45 | return call_user_func_array([$this, 'arrayOrderby'], $params); 46 | } 47 | 48 | 49 | protected function groupResult(array $data){ 50 | $options = []; 51 | foreach($this->field_function as $function_name=>$column){ 52 | $options[$function_name] = implode(',', $column); 53 | } 54 | $group_result = $this->arrayGroupBy($data, $this->group, $options); 55 | return $group_result; 56 | } 57 | 58 | protected function initOrder($parsed_query){ 59 | $order = $parsed_query['ORDER']; 60 | foreach($order as $value){ 61 | $temp_order['field'] = $value['base_expr']; 62 | $temp_order['direction'] = $value['direction']; 63 | $this->order[] = $temp_order; 64 | } 65 | } 66 | 67 | protected function initGroup($parsed_query){ 68 | $group = $parsed_query['GROUP']; 69 | 70 | foreach($group as $value){ 71 | $this->group[] = $value['base_expr']; 72 | } 73 | } 74 | 75 | protected function initFieldFunction($parsed_query){ 76 | $select_fields = $parsed_query['SELECT']; 77 | 78 | foreach($select_fields as $field){ 79 | if($field['expr_type'] === 'colref') continue; 80 | elseif($field['expr_type'] === 'aggregate_function'){ 81 | $column = $this->getFieldAsName($field); 82 | $func = strtolower($field['base_expr']); 83 | $this->field_function[$func] = $column; 84 | } 85 | } 86 | } 87 | 88 | protected function getFieldAsName($field){ 89 | if(isset($field['alias']) && !empty($field['alias'])){ 90 | return $field['alias']['name']; 91 | }elseif(!isset($field['sub_tree']) && !empty($field['base_expr'])){ 92 | return $field['base_expr']; 93 | } 94 | return false; 95 | } 96 | 97 | protected function arrayGroupBy(array $arrs,$groupBy,$option){ 98 | $temp = array(); 99 | foreach($arrs as $index=>$arr){ 100 | $groupKey = ''; 101 | foreach($groupBy as $v){ 102 | $groupKey .= $arr[$v].'-'; 103 | } 104 | $groupKey = trim($groupKey,'-'); 105 | if(isset($temp[$groupKey])) 106 | array_push($temp[$groupKey],$index); 107 | else 108 | $temp[$groupKey][]=$index; 109 | } 110 | 111 | $result = array(); 112 | foreach($temp as $key=>$value){ 113 | foreach($option as $k=>$f){ 114 | $parts = explode(',',$f); 115 | $distinct = array(); 116 | foreach($parts as $part){ 117 | $exarr = explode('|',$part); 118 | $filed = $exarr[0]; 119 | $aliasKey = isset($exarr[1]) ? $exarr[1] : ''; 120 | $aliasKey = !empty($aliasKey)?$aliasKey:$k.'_'.$filed; 121 | if($k=='sum'){ 122 | $aliasValue = 0; 123 | foreach($value as $v){ 124 | $aliasValue += $arrs[$v][$filed]; 125 | } 126 | }elseif($k=='average'){ 127 | $aliasValue = 0; 128 | foreach($value as $v){ 129 | $aliasValue += $arrs[$v][$filed]; 130 | } 131 | $aliasValue = (float)$aliasValue/count($temp[$key]); 132 | }elseif($k=='count'){ 133 | $aliasValue = count($value); 134 | }elseif($k=='group_concat'){ 135 | if(strpos($filed,':')){ 136 | $distinct = explode(':', $filed); 137 | $filed = $distinct[1]; 138 | } 139 | $aliasValue = array(); 140 | foreach($value as $v){ 141 | $aliasValue[] = $arrs[$v][$filed]; 142 | } 143 | 144 | $aliasValue = !empty($distinct) ? implode(',',array_unique($aliasValue)) : implode(',',$aliasValue); 145 | } 146 | $result[$key][$aliasKey] = $aliasValue; 147 | } 148 | 149 | } 150 | } 151 | foreach ($result as $key => &$value) { 152 | $key = explode('-', $key); 153 | for ($i = 0; $i < count($groupBy); $i++) { 154 | $value[$groupBy[$i]] = $key[$i]; 155 | } 156 | } 157 | return array_values($result); 158 | } 159 | 160 | /** 161 | * 类似SQL ORDER BY 的多为数组排序函数 162 | * example: $sorted = arrayOrderby($data, 'volume', SORT_DESC, 'edition', SORT_ASC); 163 | * 164 | * @return mixed 165 | */ 166 | public static function arrayOrderby() 167 | { 168 | $args = \func_get_args(); 169 | $data = \array_shift($args); 170 | foreach ($args as $n => $field) { 171 | if (\is_string($field)) { 172 | $tmp = array(); 173 | foreach ($data as $key => $row) 174 | $tmp[$key] = $row[$field]; 175 | $args[$n] = $tmp; 176 | } 177 | } 178 | $args[] = & $data; 179 | \call_user_func_array('array_multisort', $args); 180 | return \array_pop($args); 181 | } 182 | } -------------------------------------------------------------------------------- /tests/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | { 4 | "name": "Jenner", 5 | "email": "hypxm@qq.com", 6 | "homepage" : "http://www.huyanping.cn" 7 | } 8 | ], 9 | "require": { 10 | "zebra/merge_table": "dev-master", 11 | "php": ">=5.3.0" 12 | } 13 | } -------------------------------------------------------------------------------- /tests/composer.lock: -------------------------------------------------------------------------------- 1 | { 2 | "_readme": [ 3 | "This file locks the dependencies of your project to a known state", 4 | "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", 5 | "This file is @generated automatically" 6 | ], 7 | "hash": "3650c35bb4849ada9a6aa739caf93e71", 8 | "packages": [ 9 | { 10 | "name": "soundintheory/php-sql-parser", 11 | "version": "1.0", 12 | "source": { 13 | "type": "git", 14 | "url": "https://github.com/soundintheory/php-sql-parser.git", 15 | "reference": "dcb81216a13be124d21711b8fefb6e80db7af472" 16 | }, 17 | "dist": { 18 | "type": "zip", 19 | "url": "https://api.github.com/repos/soundintheory/php-sql-parser/zipball/dcb81216a13be124d21711b8fefb6e80db7af472", 20 | "reference": "dcb81216a13be124d21711b8fefb6e80db7af472", 21 | "shasum": "" 22 | }, 23 | "require": { 24 | "php": ">=5.3.3" 25 | }, 26 | "type": "library", 27 | "autoload": { 28 | "psr-0": { 29 | "PHPSQL": "src/" 30 | } 31 | }, 32 | "notification-url": "https://packagist.org/downloads/", 33 | "license": [ 34 | "BSD-2-Clause" 35 | ], 36 | "authors": [ 37 | { 38 | "name": "André Rothe", 39 | "email": "phosco@gmx.de", 40 | "homepage": "https://www.phosco.info", 41 | "role": "Committer" 42 | }, 43 | { 44 | "name": "Justin Swanhart", 45 | "email": "greenlion@gmail.com", 46 | "homepage": "http://code.google.com/u/greenlion@gmail.com/", 47 | "role": "Owner" 48 | }, 49 | { 50 | "name": "Andy White", 51 | "homepage": "https://github.com/soundintheory", 52 | "role": "maintainer" 53 | }, 54 | { 55 | "name": "Dan Vande More", 56 | "homepage": "https://github.com/fimbulvetr", 57 | "role": "contributor" 58 | } 59 | ], 60 | "description": "SQL parsing tools for PHP", 61 | "time": "2013-08-09 21:16:50" 62 | }, 63 | { 64 | "name": "zebra/merge_table", 65 | "version": "dev-master", 66 | "source": { 67 | "type": "git", 68 | "url": "https://github.com/PHP-Zebra/Zebra-MergeTable.git", 69 | "reference": "fcdd19f58d11ebd5bfc084e0e9c82f42d69eef75" 70 | }, 71 | "dist": { 72 | "type": "zip", 73 | "url": "https://api.github.com/repos/PHP-Zebra/Zebra-MergeTable/zipball/fcdd19f58d11ebd5bfc084e0e9c82f42d69eef75", 74 | "reference": "fcdd19f58d11ebd5bfc084e0e9c82f42d69eef75", 75 | "shasum": "" 76 | }, 77 | "require": { 78 | "php": ">=5.3.0", 79 | "soundintheory/php-sql-parser": "1.0" 80 | }, 81 | "type": "library", 82 | "autoload": { 83 | "psr-0": { 84 | "Zebra\\MergeTable": "src/" 85 | } 86 | }, 87 | "notification-url": "https://packagist.org/downloads/", 88 | "license": [ 89 | "MIT" 90 | ], 91 | "authors": [ 92 | { 93 | "name": "Jenner, xufeng", 94 | "email": "hypxm@qq.com", 95 | "homepage": "http://www.huyanping.cn" 96 | } 97 | ], 98 | "description": "database merge table", 99 | "keywords": [ 100 | "merge table", 101 | "mysql", 102 | "sql" 103 | ], 104 | "time": "2014-11-28 13:27:53" 105 | } 106 | ], 107 | "packages-dev": [], 108 | "aliases": [], 109 | "minimum-stability": "stable", 110 | "stability-flags": { 111 | "zebra/merge_table": 20 112 | }, 113 | "prefer-stable": false, 114 | "platform": { 115 | "php": ">=5.3.0" 116 | }, 117 | "platform-dev": [] 118 | } 119 | -------------------------------------------------------------------------------- /tests/sql_parser_test.php: -------------------------------------------------------------------------------- 1 | parsed); -------------------------------------------------------------------------------- /tests/vendor/autoload.php: -------------------------------------------------------------------------------- 1 | 7 | * Jordi Boggiano 8 | * 9 | * For the full copyright and license information, please view the LICENSE 10 | * file that was distributed with this source code. 11 | */ 12 | 13 | namespace Composer\Autoload; 14 | 15 | /** 16 | * ClassLoader implements a PSR-0 class loader 17 | * 18 | * See https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md 19 | * 20 | * $loader = new \Composer\Autoload\ClassLoader(); 21 | * 22 | * // register classes with namespaces 23 | * $loader->add('Symfony\Component', __DIR__.'/component'); 24 | * $loader->add('Symfony', __DIR__.'/framework'); 25 | * 26 | * // activate the autoloader 27 | * $loader->register(); 28 | * 29 | * // to enable searching the include path (eg. for PEAR packages) 30 | * $loader->setUseIncludePath(true); 31 | * 32 | * In this example, if you try to use a class in the Symfony\Component 33 | * namespace or one of its children (Symfony\Component\Console for instance), 34 | * the autoloader will first look for the class under the component/ 35 | * directory, and it will then fallback to the framework/ directory if not 36 | * found before giving up. 37 | * 38 | * This class is loosely based on the Symfony UniversalClassLoader. 39 | * 40 | * @author Fabien Potencier 41 | * @author Jordi Boggiano 42 | */ 43 | class ClassLoader 44 | { 45 | // PSR-4 46 | private $prefixLengthsPsr4 = array(); 47 | private $prefixDirsPsr4 = array(); 48 | private $fallbackDirsPsr4 = array(); 49 | 50 | // PSR-0 51 | private $prefixesPsr0 = array(); 52 | private $fallbackDirsPsr0 = array(); 53 | 54 | private $useIncludePath = false; 55 | private $classMap = array(); 56 | 57 | public function getPrefixes() 58 | { 59 | return call_user_func_array('array_merge', $this->prefixesPsr0); 60 | } 61 | 62 | public function getPrefixesPsr4() 63 | { 64 | return $this->prefixDirsPsr4; 65 | } 66 | 67 | public function getFallbackDirs() 68 | { 69 | return $this->fallbackDirsPsr0; 70 | } 71 | 72 | public function getFallbackDirsPsr4() 73 | { 74 | return $this->fallbackDirsPsr4; 75 | } 76 | 77 | public function getClassMap() 78 | { 79 | return $this->classMap; 80 | } 81 | 82 | /** 83 | * @param array $classMap Class to filename map 84 | */ 85 | public function addClassMap(array $classMap) 86 | { 87 | if ($this->classMap) { 88 | $this->classMap = array_merge($this->classMap, $classMap); 89 | } else { 90 | $this->classMap = $classMap; 91 | } 92 | } 93 | 94 | /** 95 | * Registers a set of PSR-0 directories for a given prefix, either 96 | * appending or prepending to the ones previously set for this prefix. 97 | * 98 | * @param string $prefix The prefix 99 | * @param array|string $paths The PSR-0 root directories 100 | * @param bool $prepend Whether to prepend the directories 101 | */ 102 | public function add($prefix, $paths, $prepend = false) 103 | { 104 | if (!$prefix) { 105 | if ($prepend) { 106 | $this->fallbackDirsPsr0 = array_merge( 107 | (array) $paths, 108 | $this->fallbackDirsPsr0 109 | ); 110 | } else { 111 | $this->fallbackDirsPsr0 = array_merge( 112 | $this->fallbackDirsPsr0, 113 | (array) $paths 114 | ); 115 | } 116 | 117 | return; 118 | } 119 | 120 | $first = $prefix[0]; 121 | if (!isset($this->prefixesPsr0[$first][$prefix])) { 122 | $this->prefixesPsr0[$first][$prefix] = (array) $paths; 123 | 124 | return; 125 | } 126 | if ($prepend) { 127 | $this->prefixesPsr0[$first][$prefix] = array_merge( 128 | (array) $paths, 129 | $this->prefixesPsr0[$first][$prefix] 130 | ); 131 | } else { 132 | $this->prefixesPsr0[$first][$prefix] = array_merge( 133 | $this->prefixesPsr0[$first][$prefix], 134 | (array) $paths 135 | ); 136 | } 137 | } 138 | 139 | /** 140 | * Registers a set of PSR-4 directories for a given namespace, either 141 | * appending or prepending to the ones previously set for this namespace. 142 | * 143 | * @param string $prefix The prefix/namespace, with trailing '\\' 144 | * @param array|string $paths The PSR-0 base directories 145 | * @param bool $prepend Whether to prepend the directories 146 | * 147 | * @throws \InvalidArgumentException 148 | */ 149 | public function addPsr4($prefix, $paths, $prepend = false) 150 | { 151 | if (!$prefix) { 152 | // Register directories for the root namespace. 153 | if ($prepend) { 154 | $this->fallbackDirsPsr4 = array_merge( 155 | (array) $paths, 156 | $this->fallbackDirsPsr4 157 | ); 158 | } else { 159 | $this->fallbackDirsPsr4 = array_merge( 160 | $this->fallbackDirsPsr4, 161 | (array) $paths 162 | ); 163 | } 164 | } elseif (!isset($this->prefixDirsPsr4[$prefix])) { 165 | // Register directories for a new namespace. 166 | $length = strlen($prefix); 167 | if ('\\' !== $prefix[$length - 1]) { 168 | throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); 169 | } 170 | $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; 171 | $this->prefixDirsPsr4[$prefix] = (array) $paths; 172 | } elseif ($prepend) { 173 | // Prepend directories for an already registered namespace. 174 | $this->prefixDirsPsr4[$prefix] = array_merge( 175 | (array) $paths, 176 | $this->prefixDirsPsr4[$prefix] 177 | ); 178 | } else { 179 | // Append directories for an already registered namespace. 180 | $this->prefixDirsPsr4[$prefix] = array_merge( 181 | $this->prefixDirsPsr4[$prefix], 182 | (array) $paths 183 | ); 184 | } 185 | } 186 | 187 | /** 188 | * Registers a set of PSR-0 directories for a given prefix, 189 | * replacing any others previously set for this prefix. 190 | * 191 | * @param string $prefix The prefix 192 | * @param array|string $paths The PSR-0 base directories 193 | */ 194 | public function set($prefix, $paths) 195 | { 196 | if (!$prefix) { 197 | $this->fallbackDirsPsr0 = (array) $paths; 198 | } else { 199 | $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths; 200 | } 201 | } 202 | 203 | /** 204 | * Registers a set of PSR-4 directories for a given namespace, 205 | * replacing any others previously set for this namespace. 206 | * 207 | * @param string $prefix The prefix/namespace, with trailing '\\' 208 | * @param array|string $paths The PSR-4 base directories 209 | * 210 | * @throws \InvalidArgumentException 211 | */ 212 | public function setPsr4($prefix, $paths) 213 | { 214 | if (!$prefix) { 215 | $this->fallbackDirsPsr4 = (array) $paths; 216 | } else { 217 | $length = strlen($prefix); 218 | if ('\\' !== $prefix[$length - 1]) { 219 | throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); 220 | } 221 | $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; 222 | $this->prefixDirsPsr4[$prefix] = (array) $paths; 223 | } 224 | } 225 | 226 | /** 227 | * Turns on searching the include path for class files. 228 | * 229 | * @param bool $useIncludePath 230 | */ 231 | public function setUseIncludePath($useIncludePath) 232 | { 233 | $this->useIncludePath = $useIncludePath; 234 | } 235 | 236 | /** 237 | * Can be used to check if the autoloader uses the include path to check 238 | * for classes. 239 | * 240 | * @return bool 241 | */ 242 | public function getUseIncludePath() 243 | { 244 | return $this->useIncludePath; 245 | } 246 | 247 | /** 248 | * Registers this instance as an autoloader. 249 | * 250 | * @param bool $prepend Whether to prepend the autoloader or not 251 | */ 252 | public function register($prepend = false) 253 | { 254 | spl_autoload_register(array($this, 'loadClass'), true, $prepend); 255 | } 256 | 257 | /** 258 | * Unregisters this instance as an autoloader. 259 | */ 260 | public function unregister() 261 | { 262 | spl_autoload_unregister(array($this, 'loadClass')); 263 | } 264 | 265 | /** 266 | * Loads the given class or interface. 267 | * 268 | * @param string $class The name of the class 269 | * @return bool|null True if loaded, null otherwise 270 | */ 271 | public function loadClass($class) 272 | { 273 | if ($file = $this->findFile($class)) { 274 | includeFile($file); 275 | 276 | return true; 277 | } 278 | } 279 | 280 | /** 281 | * Finds the path to the file where the class is defined. 282 | * 283 | * @param string $class The name of the class 284 | * 285 | * @return string|false The path if found, false otherwise 286 | */ 287 | public function findFile($class) 288 | { 289 | // work around for PHP 5.3.0 - 5.3.2 https://bugs.php.net/50731 290 | if ('\\' == $class[0]) { 291 | $class = substr($class, 1); 292 | } 293 | 294 | // class map lookup 295 | if (isset($this->classMap[$class])) { 296 | return $this->classMap[$class]; 297 | } 298 | 299 | $file = $this->findFileWithExtension($class, '.php'); 300 | 301 | // Search for Hack files if we are running on HHVM 302 | if ($file === null && defined('HHVM_VERSION')) { 303 | $file = $this->findFileWithExtension($class, '.hh'); 304 | } 305 | 306 | if ($file === null) { 307 | // Remember that this class does not exist. 308 | return $this->classMap[$class] = false; 309 | } 310 | 311 | return $file; 312 | } 313 | 314 | private function findFileWithExtension($class, $ext) 315 | { 316 | // PSR-4 lookup 317 | $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext; 318 | 319 | $first = $class[0]; 320 | if (isset($this->prefixLengthsPsr4[$first])) { 321 | foreach ($this->prefixLengthsPsr4[$first] as $prefix => $length) { 322 | if (0 === strpos($class, $prefix)) { 323 | foreach ($this->prefixDirsPsr4[$prefix] as $dir) { 324 | if (file_exists($file = $dir . DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $length))) { 325 | return $file; 326 | } 327 | } 328 | } 329 | } 330 | } 331 | 332 | // PSR-4 fallback dirs 333 | foreach ($this->fallbackDirsPsr4 as $dir) { 334 | if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) { 335 | return $file; 336 | } 337 | } 338 | 339 | // PSR-0 lookup 340 | if (false !== $pos = strrpos($class, '\\')) { 341 | // namespaced class name 342 | $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1) 343 | . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR); 344 | } else { 345 | // PEAR-like class name 346 | $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext; 347 | } 348 | 349 | if (isset($this->prefixesPsr0[$first])) { 350 | foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) { 351 | if (0 === strpos($class, $prefix)) { 352 | foreach ($dirs as $dir) { 353 | if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { 354 | return $file; 355 | } 356 | } 357 | } 358 | } 359 | } 360 | 361 | // PSR-0 fallback dirs 362 | foreach ($this->fallbackDirsPsr0 as $dir) { 363 | if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { 364 | return $file; 365 | } 366 | } 367 | 368 | // PSR-0 include paths. 369 | if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) { 370 | return $file; 371 | } 372 | } 373 | } 374 | 375 | /** 376 | * Scope isolated include. 377 | * 378 | * Prevents access to $this/self from included files. 379 | */ 380 | function includeFile($file) 381 | { 382 | include $file; 383 | } 384 | -------------------------------------------------------------------------------- /tests/vendor/composer/autoload_classmap.php: -------------------------------------------------------------------------------- 1 | array($vendorDir . '/zebra/merge_table/src'), 10 | 'PHPSQL' => array($vendorDir . '/soundintheory/php-sql-parser/src'), 11 | ); 12 | -------------------------------------------------------------------------------- /tests/vendor/composer/autoload_psr4.php: -------------------------------------------------------------------------------- 1 | $path) { 28 | $loader->set($namespace, $path); 29 | } 30 | 31 | $map = require __DIR__ . '/autoload_psr4.php'; 32 | foreach ($map as $namespace => $path) { 33 | $loader->setPsr4($namespace, $path); 34 | } 35 | 36 | $classMap = require __DIR__ . '/autoload_classmap.php'; 37 | if ($classMap) { 38 | $loader->addClassMap($classMap); 39 | } 40 | 41 | $loader->register(true); 42 | 43 | return $loader; 44 | } 45 | } 46 | 47 | function composerRequire600d81621366d6682d16d39cfa2e3e15($file) 48 | { 49 | require $file; 50 | } 51 | -------------------------------------------------------------------------------- /tests/vendor/composer/installed.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "soundintheory/php-sql-parser", 4 | "version": "1.0", 5 | "version_normalized": "1.0.0.0", 6 | "source": { 7 | "type": "git", 8 | "url": "https://github.com/soundintheory/php-sql-parser.git", 9 | "reference": "dcb81216a13be124d21711b8fefb6e80db7af472" 10 | }, 11 | "dist": { 12 | "type": "zip", 13 | "url": "https://api.github.com/repos/soundintheory/php-sql-parser/zipball/dcb81216a13be124d21711b8fefb6e80db7af472", 14 | "reference": "dcb81216a13be124d21711b8fefb6e80db7af472", 15 | "shasum": "" 16 | }, 17 | "require": { 18 | "php": ">=5.3.3" 19 | }, 20 | "time": "2013-08-09 21:16:50", 21 | "type": "library", 22 | "installation-source": "dist", 23 | "autoload": { 24 | "psr-0": { 25 | "PHPSQL": "src/" 26 | } 27 | }, 28 | "notification-url": "https://packagist.org/downloads/", 29 | "license": [ 30 | "BSD-2-Clause" 31 | ], 32 | "authors": [ 33 | { 34 | "name": "André Rothe", 35 | "email": "phosco@gmx.de", 36 | "homepage": "https://www.phosco.info", 37 | "role": "Committer" 38 | }, 39 | { 40 | "name": "Justin Swanhart", 41 | "email": "greenlion@gmail.com", 42 | "homepage": "http://code.google.com/u/greenlion@gmail.com/", 43 | "role": "Owner" 44 | }, 45 | { 46 | "name": "Andy White", 47 | "homepage": "https://github.com/soundintheory", 48 | "role": "maintainer" 49 | }, 50 | { 51 | "name": "Dan Vande More", 52 | "homepage": "https://github.com/fimbulvetr", 53 | "role": "contributor" 54 | } 55 | ], 56 | "description": "SQL parsing tools for PHP" 57 | }, 58 | { 59 | "name": "zebra/merge_table", 60 | "version": "dev-master", 61 | "version_normalized": "9999999-dev", 62 | "source": { 63 | "type": "git", 64 | "url": "https://github.com/PHP-Zebra/Zebra-MergeTable.git", 65 | "reference": "fcdd19f58d11ebd5bfc084e0e9c82f42d69eef75" 66 | }, 67 | "dist": { 68 | "type": "zip", 69 | "url": "https://api.github.com/repos/PHP-Zebra/Zebra-MergeTable/zipball/fcdd19f58d11ebd5bfc084e0e9c82f42d69eef75", 70 | "reference": "fcdd19f58d11ebd5bfc084e0e9c82f42d69eef75", 71 | "shasum": "" 72 | }, 73 | "require": { 74 | "php": ">=5.3.0", 75 | "soundintheory/php-sql-parser": "1.0" 76 | }, 77 | "time": "2014-11-28 13:27:53", 78 | "type": "library", 79 | "installation-source": "source", 80 | "autoload": { 81 | "psr-0": { 82 | "Zebra\\MergeTable": "src/" 83 | } 84 | }, 85 | "notification-url": "https://packagist.org/downloads/", 86 | "license": [ 87 | "MIT" 88 | ], 89 | "authors": [ 90 | { 91 | "name": "Jenner, xufeng", 92 | "email": "hypxm@qq.com", 93 | "homepage": "http://www.huyanping.cn" 94 | } 95 | ], 96 | "description": "database merge table", 97 | "keywords": [ 98 | "merge table", 99 | "mysql", 100 | "sql" 101 | ] 102 | } 103 | ] 104 | -------------------------------------------------------------------------------- /tests/vendor/soundintheory/php-sql-parser/README.md: -------------------------------------------------------------------------------- 1 | PHP SQL Parser 2 | -------------- 3 | 4 | A fork of https://code.google.com/p/php-sql-parser/ 5 | 6 | A Parser for mysql-ish queries that can represent a query as an array. 7 | 8 | # Goals: 9 | 1. A PSR-0 Compatible implementation 10 | 2. Improvements 11 | 3. Profit!!! 12 | 13 | ## Usage 14 | 15 | ### Use your PSR-0 Compatible Autoloader or the sample one provided in example.php 16 | 17 | 18 | ## Improvements/Feedback. 19 | 20 | Please send them to me, or send a pull request. I will honor every reasonable request, where reasonable usually means elegance, simplicity and bug fixes. Suggestions for improvement are welcome, though you'll see them sooner if you write them. 21 | I will take unit tests as well! 22 | 23 | ## License 24 | 25 | PHPSQLParser is licensed under The BSD 2-Clause License, available online here: http://opensource.org/licenses/bsd-license.php 26 | 27 | /** 28 | * A pure PHP SQL (non validating) parser w/ focus on MySQL dialect of SQL 29 | * 30 | * Copyright (c) 2010-2012, Justin Swanhart 31 | * with contributions by André Rothe 32 | * with contributions by Dan Vande More 33 | * 34 | * All rights reserved. 35 | * 36 | * Redistribution and use in source and binary forms, with or without modification, 37 | * are permitted provided that the following conditions are met: 38 | * 39 | * * Redistributions of source code must retain the above copyright notice, 40 | * this list of conditions and the following disclaimer. 41 | * * Redistributions in binary form must reproduce the above copyright notice, 42 | * this list of conditions and the following disclaimer in the documentation 43 | * and/or other materials provided with the distribution. 44 | * 45 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 46 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 47 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 48 | * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 49 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 50 | * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 51 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 52 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 53 | * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 54 | * DAMAGE. 55 | */ -------------------------------------------------------------------------------- /tests/vendor/soundintheory/php-sql-parser/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "soundintheory/php-sql-parser", 3 | "type": "library", 4 | "description": "SQL parsing tools for PHP", 5 | "license": "BSD-2-Clause", 6 | "require": { 7 | "php": ">=5.3.3" 8 | }, 9 | "autoload": { 10 | "psr-0": { "PHPSQL": "src/" } 11 | }, 12 | "authors": [ 13 | { "name": "Justin Swanhart", "email": "greenlion@gmail.com" }, 14 | { "name": "André Rothe", "email": "phosco@gmx.de" }, 15 | { "name": "Dan Vande More", "homepage": "https://github.com/fimbulvetr", "role": "contributor" }, 16 | { "name": "Andy White", "homepage": "https://github.com/soundintheory", "role": "maintainer" } 17 | ], 18 | "minimum-stability": "stable" 19 | } -------------------------------------------------------------------------------- /tests/vendor/soundintheory/php-sql-parser/src/PHPSQL/Exception/Exception.php: -------------------------------------------------------------------------------- 1 | 7 | * with contributions by Dan Vande More 8 | * 9 | * All rights reserved. 10 | * 11 | * Redistribution and use in source and binary forms, with or without modification, 12 | * are permitted provided that the following conditions are met: 13 | * 14 | * * Redistributions of source code must retain the above copyright notice, 15 | * this list of conditions and the following disclaimer. 16 | * * Redistributions in binary form must reproduce the above copyright notice, 17 | * this list of conditions and the following disclaimer in the documentation 18 | * and/or other materials provided with the distribution. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 21 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 22 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 23 | * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 24 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 25 | * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 26 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 28 | * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 29 | * DAMAGE. 30 | */ 31 | 32 | namespace PHPSQL\Exception; 33 | 34 | class InvalidParameter extends \InvalidArgumentException { 35 | 36 | protected $argument; 37 | 38 | public function __construct($argument) { 39 | $this->argument = $argument; 40 | parent::__construct("no SQL string to parse: \n" . $argument, 10); 41 | } 42 | 43 | public function getArgument() { 44 | return $this->argument; 45 | } 46 | } -------------------------------------------------------------------------------- /tests/vendor/soundintheory/php-sql-parser/src/PHPSQL/Exception/UnableToCalculatePosition.php: -------------------------------------------------------------------------------- 1 | 7 | * with contributions by Dan Vande More 8 | * 9 | * All rights reserved. 10 | * 11 | * Redistribution and use in source and binary forms, with or without modification, 12 | * are permitted provided that the following conditions are met: 13 | * 14 | * * Redistributions of source code must retain the above copyright notice, 15 | * this list of conditions and the following disclaimer. 16 | * * Redistributions in binary form must reproduce the above copyright notice, 17 | * this list of conditions and the following disclaimer in the documentation 18 | * and/or other materials provided with the distribution. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 21 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 22 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 23 | * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 24 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 25 | * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 26 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 28 | * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 29 | * DAMAGE. 30 | */ 31 | 32 | namespace PHPSQL\Exception; 33 | 34 | class UnableToCalculatePosition extends \PHPSQL\Exception\Exception { 35 | 36 | protected $needle; 37 | protected $haystack; 38 | 39 | public function __construct($needle, $haystack) { 40 | $this->needle = $needle; 41 | $this->haystack = $haystack; 42 | parent::__construct("cannot calculate position of " . $needle . " within " . $haystack, 5); 43 | } 44 | 45 | public function getNeedle() { 46 | return $this->needle; 47 | } 48 | 49 | public function getHaystack() { 50 | return $this->haystack; 51 | } 52 | } -------------------------------------------------------------------------------- /tests/vendor/soundintheory/php-sql-parser/src/PHPSQL/Exception/UnableToCreateSQL.php: -------------------------------------------------------------------------------- 1 | 7 | * with contributions by Dan Vande More 8 | * 9 | * All rights reserved. 10 | * 11 | * Redistribution and use in source and binary forms, with or without modification, 12 | * are permitted provided that the following conditions are met: 13 | * 14 | * * Redistributions of source code must retain the above copyright notice, 15 | * this list of conditions and the following disclaimer. 16 | * * Redistributions in binary form must reproduce the above copyright notice, 17 | * this list of conditions and the following disclaimer in the documentation 18 | * and/or other materials provided with the distribution. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 21 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 22 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 23 | * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 24 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 25 | * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 26 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 28 | * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 29 | * DAMAGE. 30 | */ 31 | 32 | namespace PHPSQL\Exception; 33 | 34 | class UnableToCreateSQL extends \PHPSQL\Exception\Exception { 35 | 36 | protected $part; 37 | protected $partkey; 38 | protected $entry; 39 | protected $entrykey; 40 | 41 | public function __construct($part, $partkey, $entry, $entrykey) { 42 | $this->part = $part; 43 | $this->partkey = $partkey; 44 | $this->entry = $entry; 45 | $this->entrykey = $entrykey; 46 | parent::__construct("unknown " . $entrykey . " in " . $part . "[" . $partkey . "] " . $entry[$entrykey], 15); 47 | } 48 | 49 | public function getEntry() { 50 | return $this->entry; 51 | } 52 | 53 | public function getEntryKey() { 54 | return $this->entrykey; 55 | } 56 | 57 | public function getSQLPart() { 58 | return $this->part; 59 | } 60 | 61 | public function getSQLPartKey() { 62 | return $this->partkey; 63 | } 64 | } -------------------------------------------------------------------------------- /tests/vendor/soundintheory/php-sql-parser/src/PHPSQL/Exception/UnsupportedFeature.php: -------------------------------------------------------------------------------- 1 | 7 | * with contributions by Dan Vande More 8 | * 9 | * All rights reserved. 10 | * 11 | * Redistribution and use in source and binary forms, with or without modification, 12 | * are permitted provided that the following conditions are met: 13 | * 14 | * * Redistributions of source code must retain the above copyright notice, 15 | * this list of conditions and the following disclaimer. 16 | * * Redistributions in binary form must reproduce the above copyright notice, 17 | * this list of conditions and the following disclaimer in the documentation 18 | * and/or other materials provided with the distribution. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 21 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 22 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 23 | * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 24 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 25 | * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 26 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 28 | * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 29 | * DAMAGE. 30 | */ 31 | 32 | namespace PHPSQL\Exception; 33 | 34 | class UnsupportedFeature extends \PHPSQL\Exception\Exception { 35 | 36 | protected $key; 37 | 38 | public function __construct($key) { 39 | $this->key = $key; 40 | parent::__construct($key . " not implemented.", 20); 41 | } 42 | 43 | public function getKey() { 44 | return $this->key; 45 | } 46 | } -------------------------------------------------------------------------------- /tests/vendor/soundintheory/php-sql-parser/src/PHPSQL/Expression/Token.php: -------------------------------------------------------------------------------- 1 | 10 | * with contributions by Dan Vande More 11 | * 12 | * All rights reserved. 13 | * 14 | * Redistribution and use in source and binary forms, with or without modification, 15 | * are permitted provided that the following conditions are met: 16 | * 17 | * * Redistributions of source code must retain the above copyright notice, 18 | * this list of conditions and the following disclaimer. 19 | * * Redistributions in binary form must reproduce the above copyright notice, 20 | * this list of conditions and the following disclaimer in the documentation 21 | * and/or other materials provided with the distribution. 22 | * 23 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 24 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 25 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 26 | * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 27 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 28 | * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 29 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 30 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 31 | * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 32 | * DAMAGE. 33 | */ 34 | 35 | namespace PHPSQL\Expression; 36 | 37 | class Token { 38 | 39 | private $subTree; 40 | private $expression; 41 | private $key; 42 | private $token; 43 | private $tokenType; 44 | private $trim; 45 | private $upper; 46 | 47 | public function __construct($key = "", $token = "") { 48 | $this->subTree = false; 49 | $this->expression = ""; 50 | $this->key = $key; 51 | $this->token = $token; 52 | $this->tokenType = false; 53 | $this->trim = trim($token); 54 | $this->upper = strtoupper($this->trim); 55 | } 56 | 57 | # TODO: we could replace it with a constructor new \PHPSQL\Expression\Token(this, "*") 58 | public function addToken($string) { 59 | $this->token .= $string; 60 | } 61 | 62 | public function isEnclosedWithinParenthesis() { 63 | return ($this->upper[0] === '(' && substr($this->upper, -1) === ')'); 64 | } 65 | 66 | public function setSubTree($tree) { 67 | $this->subTree = $tree; 68 | } 69 | 70 | public function getSubTree() { 71 | return $this->subTree; 72 | } 73 | 74 | public function getUpper($idx = false) { 75 | return $idx !== false ? $this->upper[$idx] : $this->upper; 76 | } 77 | 78 | public function getTrim($idx = false) { 79 | return $idx !== false ? $this->trim[$idx] : $this->trim; 80 | } 81 | 82 | public function getToken($idx = false) { 83 | return $idx !== false ? $this->token[$idx] : $this->token; 84 | } 85 | 86 | public function setTokenType($type) { 87 | $this->tokenType = $type; 88 | } 89 | 90 | public function endsWith($needle) { 91 | $length = strlen($needle); 92 | if ($length == 0) { 93 | return true; 94 | } 95 | 96 | $start = $length * -1; 97 | return (substr($this->token, $start) === $needle); 98 | } 99 | 100 | public function isWhitespaceToken() { 101 | return ($this->trim === ""); 102 | } 103 | 104 | public function isCommaToken() { 105 | return ($this->trim === ","); 106 | } 107 | 108 | public function isVariableToken() { 109 | return $this->upper[0] === '@'; 110 | } 111 | 112 | public function isSubQueryToken() { 113 | return preg_match("/^\\(\\s*SELECT/i", $this->trim); 114 | } 115 | 116 | public function isExpression() { 117 | return $this->tokenType === \PHPSQL\Expression\Type::EXPRESSION; 118 | } 119 | 120 | public function isBracketExpression() { 121 | return $this->tokenType === \PHPSQL\Expression\Type::BRACKET_EXPRESSION; 122 | } 123 | 124 | public function isOperator() { 125 | return $this->tokenType === \PHPSQL\Expression\Type::OPERATOR; 126 | } 127 | 128 | public function isInList() { 129 | return $this->tokenType === \PHPSQL\Expression\Type::IN_LIST; 130 | } 131 | 132 | public function isFunction() { 133 | return $this->tokenType === \PHPSQL\Expression\Type::SIMPLE_FUNCTION; 134 | } 135 | 136 | public function isUnspecified() { 137 | return ($this->tokenType === false); 138 | } 139 | 140 | public function isAggregateFunction() { 141 | return $this->tokenType === \PHPSQL\Expression\Type::AGGREGATE_FUNCTION; 142 | } 143 | 144 | public function isColumnReference() { 145 | return $this->tokenType === \PHPSQL\Expression\Type::COLREF; 146 | } 147 | 148 | public function isConstant() { 149 | return $this->tokenType === \PHPSQL\Expression\Type::CONSTANT; 150 | } 151 | 152 | public function isSign() { 153 | return $this->tokenType === \PHPSQL\Expression\Type::SIGN; 154 | } 155 | 156 | public function isSubQuery() { 157 | return $this->tokenType === \PHPSQL\Expression\Type::SUBQUERY; 158 | } 159 | 160 | public function toArray() { 161 | return array('expr_type' => $this->tokenType, 'base_expr' => $this->token, 'sub_tree' => $this->subTree); 162 | } 163 | } 164 | -------------------------------------------------------------------------------- /tests/vendor/soundintheory/php-sql-parser/src/PHPSQL/Expression/Type.php: -------------------------------------------------------------------------------- 1 | 10 | * with contributions by Dan Vande More 11 | * 12 | * All rights reserved. 13 | * 14 | * Redistribution and use in source and binary forms, with or without modification, 15 | * are permitted provided that the following conditions are met: 16 | * 17 | * * Redistributions of source code must retain the above copyright notice, 18 | * this list of conditions and the following disclaimer. 19 | * * Redistributions in binary form must reproduce the above copyright notice, 20 | * this list of conditions and the following disclaimer in the documentation 21 | * and/or other materials provided with the distribution. 22 | * 23 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 24 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 25 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 26 | * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 27 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 28 | * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 29 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 30 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 31 | * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 32 | * DAMAGE. 33 | */ 34 | 35 | namespace PHPSQL\Expression; 36 | 37 | class Type { 38 | 39 | const USER_VARIABLE = "user_variable"; 40 | const SESSION_VARIABLE = "session_variable"; 41 | const GLOBAL_VARIABLE = "global_variable"; 42 | const LOCAL_VARIABLE = "local_variable"; 43 | 44 | const COLREF = "colref"; 45 | const RESERVED = "reserved"; 46 | const CONSTANT = "const"; 47 | 48 | const AGGREGATE_FUNCTION = "aggregate_function"; 49 | const SIMPLE_FUNCTION = "function"; 50 | 51 | const EXPRESSION = "expression"; 52 | const BRACKET_EXPRESSION = "bracket_expression"; 53 | const TABLE_EXPRESSION = "table_expression"; 54 | 55 | const SUBQUERY = "subquery"; 56 | const IN_LIST = "in-list"; 57 | const OPERATOR = "operator"; 58 | const SIGN = "sign"; 59 | const RECORD = "record"; 60 | 61 | const MATCH_ARGUMENTS = "match-arguments"; 62 | const MATCH_MODE = "match-mode"; 63 | 64 | const ALIAS = "alias"; 65 | const POSITION = "pos"; 66 | 67 | const TEMPORARY_TABLE = "temporary_table"; 68 | const TABLE = "table"; 69 | const VIEW = "view"; 70 | const DATABASE = "database"; 71 | const SCHEMA = "schema"; 72 | } 73 | -------------------------------------------------------------------------------- /tests/vendor/soundintheory/php-sql-parser/src/PHPSQL/Parser/Constants.php: -------------------------------------------------------------------------------- 1 | 9 | * with contributions by Dan Vande More 10 | * 11 | * All rights reserved. 12 | * 13 | * Redistribution and use in source and binary forms, with or without modification, 14 | * are permitted provided that the following conditions are met: 15 | * 16 | * * Redistributions of source code must retain the above copyright notice, 17 | * this list of conditions and the following disclaimer. 18 | * * Redistributions in binary form must reproduce the above copyright notice, 19 | * this list of conditions and the following disclaimer in the documentation 20 | * and/or other materials provided with the distribution. 21 | * 22 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 23 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 24 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 25 | * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 26 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 27 | * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 28 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 29 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 30 | * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 31 | * DAMAGE. 32 | */ 33 | 34 | namespace PHPSQL\Parser; 35 | 36 | class Constants { 37 | 38 | protected static $reserved = array('ABS', 'ACOS', 'ADDDATE', 'ADDTIME', 'AES_ENCRYPT', 'AES_DECRYPT', 'AGAINST', 39 | 'ASCII', 'ASIN', 'ATAN', 'AVG', 'BENCHMARK', 'BIN', 'BIT_AND', 'BIT_OR', 40 | 'BITCOUNT', 'BITLENGTH', 'CAST', 'CEILING', 'CHAR', 'CHAR_LENGTH', 41 | 'CHARACTER_LENGTH', 'CHARSET', 'COALESCE', 'COERCIBILITY', 'COLLATION', 42 | 'COMPRESS', 'CONCAT', 'CONCAT_WS', 'CONNECTION_ID', 'CONV', 'CONVERT', 43 | 'CONVERT_TZ', 'COS', 'COT', 'COUNT', 'CRC32', 'CURDATE', 'CURRENT_USER', 44 | 'CURRVAL', 'CURTIME', 'DATABASE', 'DATETIME', 'DATE_ADD', 'DATE_DIFF', 45 | 'DATE_FORMAT', 'DATE_SUB', 'DAY', 'DAYNAME', 'DAYOFMONTH', 'DAYOFWEEK', 46 | 'DAYOFYEAR', 'DECODE', 'DEFAULT', 'DEGREES', 'DES_DECRYPT', 'DES_ENCRYPT', 47 | 'ELT', 'ENCODE', 'ENCRYPT', 'EXP', 'EXPORT_SET', 'EXTRACT', 'FIELD', 48 | 'FIND_IN_SET', 'FLOOR', 'FORMAT', 'FOUND_ROWS', 'FROM_DAYS', 'FROM_UNIXTIME', 49 | 'GET_FORMAT', 'GET_LOCK', 'GROUP_CONCAT', 'GREATEST', 'HEX', 'HOUR', 'IF', 50 | 'IFNULL', 'IN', 'INET_ATON', 'INET_NTOA', 'INSERT', 'INSTR', 'INTERVAL', 51 | 'IS_FREE_LOCK', 'IS_USED_LOCK', 'LAST_DAY', 'LAST_INSERT_ID', 'LCASE', 'LEAST', 52 | 'LEFT', 'LENGTH', 'LN', 'LOAD_FILE', 'LOCALTIME', 'LOCALTIMESTAMP', 'LOCATE', 53 | 'LOG', 'LOG2', 'LOG10', 'LOWER', 'LPAD', 'LTRIM', 'MAKE_SET', 'MAKEDATE', 54 | 'MAKETIME', 'MASTER_POS_WAIT', 'MATCH', 'MAX', 'MD5', 'MICROSECOND', 'MID', 55 | 'MIN', 'MINUTE', 'MOD', 'MONTH', 'MONTHNAME', 'NEXTVAL', 'NOW', 'NULLIF', 'OCT', 56 | 'OCTET_LENGTH', 'OLD_PASSWORD', 'ORD', 'PASSWORD', 'PERIOD_ADD', 'PERIOD_DIFF', 57 | 'PI', 'POSITION', 'POW', 'POWER', 'QUARTER', 'QUOTE', 'RADIANS', 'RAND', 58 | 'RELEASE_LOCK', 'REPEAT', 'REPLACE', 'REVERSE', 'RIGHT', 'ROUND', 'ROW_COUNT', 59 | 'RPAD', 'RTRIM', 'SEC_TO_TIME', 'SECOND', 'SESSION_USER', 'SHA', 'SHA1', 'SIGN', 60 | 'SOUNDEX', 'SPACE', 'SQRT', 'STD', 'STDDEV', 'STDDEV_POP', 'STDDEV_SAMP', 61 | 'STRCMP', 'STR_TO_DATE', 'SUBDATE', 'SUBSTRING', 'SUBSTRING_INDEX', 'SUBTIME', 62 | 'SUM', 'SYSDATE', 'SYSTEM_USER', 'TAN', 'TIME', 'TIMEDIFF', 'TIMESTAMP', 63 | 'TIMESTAMPADD', 'TIMESTAMPDIFF', 'TIME_FORMAT', 'TIME_TO_SEC', 'TO_DAYS', 64 | 'TRIM', 'TRUNCATE', 'UCASE', 'UNCOMPRESS', 'UNCOMPRESSED_LENGTH', 'UNHEX', 65 | 'UNIX_TIMESTAMP', 'UPPER', 'USER', 'UTC_DATE', 'UTC_TIME', 'UTC_TIMESTAMP', 66 | 'UUID', 'VAR_POP', 'VAR_SAMP', 'VARIANCE', 'VERSION', 'WEEK', 'WEEKDAY', 67 | 'WEEKOFYEAR', 'YEAR', 'YEARWEEK', 'ADD', 'ALL', 'ALTER', 'ANALYZE', 'AND', 'AS', 68 | 'ASC', 'ASENSITIVE', 'AUTO_INCREMENT', 'BDB', 'BEFORE', 'BERKELEYDB', 'BETWEEN', 69 | 'BIGINT', 'BINARY', 'BLOB', 'BOTH', 'BY', 'CALL', 'CASCADE', 'CASE', 'CHANGE', 70 | 'CHAR', 'CHARACTER', 'CHECK', 'COLLATE', 'COLUMN', 'COLUMNS', 'CONDITION', 71 | 'CONNECTION', 'CONSTRAINT', 'CONTINUE', 'CREATE', 'CROSS', 'CURRENT_DATE', 72 | 'CURRENT_TIME', 'CURRENT_TIMESTAMP', 'CURSOR', 'DATABASE', 'DATABASES', 73 | 'DAY_HOUR', 'DAY_MICROSECOND', 'DAY_MINUTE', 'DAY_SECOND', 'DEC', 'DECIMAL', 74 | 'DECLARE', 'DEFAULT', 'DELAYED', 'DELETE', 'DESC', 'DESCRIBE', 'DETERMINISTIC', 75 | 'DISTINCT', 'DISTINCTROW', 'DIV', 'DOUBLE', 'DROP', 'ELSE', 'ELSEIF', 'END', 76 | 'ENCLOSED', 'ESCAPED', 'EXISTS', 'EXIT', 'EXPLAIN', 'FALSE', 'FETCH', 'FIELDS', 77 | 'FLOAT', 'FOR', 'FORCE', 'FOREIGN', 'FOUND', 'FRAC_SECOND', 'FROM', 'FULLTEXT', 78 | 'GRANT', 'GROUP', 'HAVING', 'HIGH_PRIORITY', 'HOUR_MICROSECOND', 'HOUR_MINUTE', 79 | 'HOUR_SECOND', 'IF', 'IGNORE', 'IN', 'INDEX', 'INFILE', 'INNER', 'INNODB', 80 | 'INOUT', 'INSENSITIVE', 'INSERT', 'INT', 'INTEGER', 'INTERVAL', 'INTO', 81 | 'IO_THREAD', 'IS', 'ITERATE', 'JOIN', 'KEY', 'KEYS', 'KILL', 'LEADING', 'LEAVE', 82 | 'LEFT', 'LIKE', 'LIMIT', 'LINES', 'LOAD', 'LOCALTIME', 'LOCALTIMESTAMP', 'LOCK', 83 | 'LONG', 'LONGBLOB', 'LONGTEXT', 'LOOP', 'LOW_PRIORITY', 'MASTER_SERVER_ID', 84 | 'MATCH', 'MEDIUMBLOB', 'MEDIUMINT', 'MEDIUMTEXT', 'MIDDLEINT', 85 | 'MINUTE_MICROSECOND', 'MINUTE_SECOND', 'MOD', 'NATURAL', 'NOT', 86 | 'NO_WRITE_TO_BINLOG', 'NULL', 'NUMERIC', 'ON', 'OPTIMIZE', 'OPTION', 87 | 'OPTIONALLY', 'OR', 'ORDER', 'OUT', 'OUTER', 'OUTFILE', 'PRECISION', 'PRIMARY', 88 | 'PRIVILEGES', 'PROCEDURE', 'PURGE', 'READ', 'REAL', 'REFERENCES', 'REGEXP', 89 | 'RENAME', 'REPEAT', 'REPLACE', 'REQUIRE', 'RESTRICT', 'RETURN', 'REVOKE', 90 | 'RIGHT', 'RLIKE', 'SECOND_MICROSECOND', 'SELECT', 'SENSITIVE', 'SEPARATOR', 91 | 'SET', 'SHOW', 'SMALLINT', 'SOME', 'SONAME', 'SPATIAL', 'SPECIFIC', 'SQL', 92 | 'SQLEXCEPTION', 'SQLSTATE', 'SQLWARNING', 'SQL_BIG_RESULT', 93 | 'SQL_CALC_FOUND_ROWS', 'SQL_SMALL_RESULT', 'SQL_TSI_DAY', 'SQL_TSI_FRAC_SECOND', 94 | 'SQL_TSI_HOUR', 'SQL_TSI_MINUTE', 'SQL_TSI_MONTH', 'SQL_TSI_QUARTER', 95 | 'SQL_TSI_SECOND', 'SQL_TSI_WEEK', 'SQL_TSI_YEAR', 'SSL', 'STARTING', 96 | 'STRAIGHT_JOIN', 'STRIPED', 'TABLE', 'TABLES', 'TERMINATED', 'THEN', 97 | 'TIMESTAMPADD', 'TIMESTAMPDIFF', 'TINYBLOB', 'TINYINT', 'TINYTEXT', 'TO', 98 | 'TRAILING', 'TRUE', 'UNDO', 'UNION', 'UNIQUE', 'UNLOCK', 'UNSIGNED', 'UPDATE', 99 | 'USAGE', 'USE', 'USER_RESOURCES', 'USING', 'UTC_DATE', 'UTC_TIME', 100 | 'UTC_TIMESTAMP', 'VALUES', 'VARBINARY', 'VARCHAR', 'VARCHARACTER', 'VARYING', 101 | 'WHEN', 'WHERE', 'WHILE', 'WITH', 'WRITE', 'XOR', 'YEAR_MONTH', 'ZEROFILL'); 102 | 103 | protected static $parameterizedFunctions = array('ABS', 'ACOS', 'ADDDATE', 'ADDTIME', 'AES_ENCRYPT', 'AES_DECRYPT', 104 | 'AGAINST', 'ASCII', 'ASIN', 'ATAN', 'AVG', 'BENCHMARK', 'BIN', 105 | 'BIT_AND', 'BIT_OR', 'BITCOUNT', 'BITLENGTH', 'CAST', 'CEILING', 106 | 'CHAR', 'CHAR_LENGTH', 'CHARACTER_LENGTH', 'CHARSET', 'COALESCE', 107 | 'COERCIBILITY', 'COLLATION', 'COMPRESS', 'CONCAT', 'CONCAT_WS', 108 | 'CONV', 'CONVERT', 'CONVERT_TZ', 'COS', 'COT', 'COUNT', 'CRC32', 109 | 'CURRVAL', 'DATE_ADD', 'DATE_DIFF', 'DATE_FORMAT', 'DATE_SUB', 110 | 'DAY', 'DAYNAME', 'DAYOFMONTH', 'DAYOFWEEK', 'DAYOFYEAR', 111 | 'DECODE', 'DEFAULT', 'DEGREES', 'DES_DECRYPT', 'DES_ENCRYPT', 112 | 'ELT', 'ENCODE', 'ENCRYPT', 'EXP', 'EXPORT_SET', 'EXTRACT', 113 | 'FIELD', 'FIND_IN_SET', 'FLOOR', 'FORMAT', 'FROM_DAYS', 114 | 'FROM_UNIXTIME', 'GET_FORMAT', 'GET_LOCK', 'GROUP_CONCAT', 115 | 'GREATEST', 'HEX', 'HOUR', 'IF', 'IFNULL', 'IN', 'INET_ATON', 116 | 'INET_NTOA', 'INSERT', 'INSTR', 'INTERVAL', 'IS_FREE_LOCK', 117 | 'IS_USED_LOCK', 'LAST_DAY', 'LCASE', 'LEAST', 'LEFT', 'LENGTH', 118 | 'LN', 'LOAD_FILE', 'LOCATE', 'LOG', 'LOG2', 'LOG10', 'LOWER', 119 | 'LPAD', 'LTRIM', 'MAKE_SET', 'MAKEDATE', 'MAKETIME', 120 | 'MASTER_POS_WAIT', 'MATCH', 'MAX', 'MD5', 'MICROSECOND', 'MID', 121 | 'MIN', 'MINUTE', 'MOD', 'MONTH', 'MONTHNAME', 'NEXTVAL', 'NULLIF', 122 | 'OCT', 'OCTET_LENGTH', 'OLD_PASSWORD', 'ORD', 'PASSWORD', 123 | 'PERIOD_ADD', 'PERIOD_DIFF', 'PI', 'POSITION', 'POW', 'POWER', 124 | 'QUARTER', 'QUOTE', 'RADIANS', 'RELEASE_LOCK', 'REPEAT', 125 | 'REPLACE', 'REVERSE', 'RIGHT', 'ROUND', 'RPAD', 'RTRIM', 126 | 'SEC_TO_TIME', 'SECOND', 'SHA', 'SHA1', 'SIGN', 'SOUNDEX', 127 | 'SPACE', 'SQRT', 'STD', 'STDDEV', 'STDDEV_POP', 'STDDEV_SAMP', 128 | 'STRCMP', 'STR_TO_DATE', 'SUBDATE', 'SUBSTRING', 129 | 'SUBSTRING_INDEX', 'SUBTIME', 'SUM', 'TAN', 'TIME', 'TIMEDIFF', 130 | 'TIMESTAMP', 'TIMESTAMPADD', 'TIMESTAMPDIFF', 'TIME_FORMAT', 131 | 'TIME_TO_SEC', 'TO_DAYS', 'TRIM', 'TRUNCATE', 'UCASE', 132 | 'UNCOMPRESS', 'UNCOMPRESSED_LENGTH', 'UNHEX', 'UPPER', 'VAR_POP', 133 | 'VAR_SAMP', 'VARIANCE', 'WEEK', 'WEEKDAY', 'WEEKOFYEAR', 'YEAR', 134 | 'YEARWEEK'); 135 | 136 | protected static $functions = array('ABS', 'ACOS', 'ADDDATE', 'ADDTIME', 'AES_ENCRYPT', 'AES_DECRYPT', 'AGAINST', 137 | 'ASCII', 'ASIN', 'ATAN', 'AVG', 'BENCHMARK', 'BIN', 'BIT_AND', 'BIT_OR', 138 | 'BITCOUNT', 'BITLENGTH', 'CAST', 'CEILING', 'CHAR', 'CHAR_LENGTH', 139 | 'CHARACTER_LENGTH', 'CHARSET', 'COALESCE', 'COERCIBILITY', 'COLLATION', 140 | 'COMPRESS', 'CONCAT', 'CONCAT_WS', 'CONNECTION_ID', 'CONV', 'CONVERT', 141 | 'CONVERT_TZ', 'COS', 'COT', 'COUNT', 'CRC32', 'CURDATE', 'CURRENT_USER', 142 | 'CURRVAL', 'CURTIME', 'DATABASE', 'DATE_ADD', 'DATE_DIFF', 'DATE_FORMAT', 143 | 'DATE_SUB', 'DAY', 'DAYNAME', 'DAYOFMONTH', 'DAYOFWEEK', 'DAYOFYEAR', 'DECODE', 144 | 'DEFAULT', 'DEGREES', 'DES_DECRYPT', 'DES_ENCRYPT', 'ELT', 'ENCODE', 'ENCRYPT', 145 | 'EXP', 'EXPORT_SET', 'EXTRACT', 'FIELD', 'FIND_IN_SET', 'FLOOR', 'FORMAT', 146 | 'FOUND_ROWS', 'FROM_DAYS', 'FROM_UNIXTIME', 'GET_FORMAT', 'GET_LOCK', 147 | 'GROUP_CONCAT', 'GREATEST', 'HEX', 'HOUR', 'IF', 'IFNULL', 'IN', 'INET_ATON', 148 | 'INET_NTOA', 'INSERT', 'INSTR', 'INTERVAL', 'IS_FREE_LOCK', 'IS_USED_LOCK', 149 | 'LAST_DAY', 'LAST_INSERT_ID', 'LCASE', 'LEAST', 'LEFT', 'LENGTH', 'LN', 150 | 'LOAD_FILE', 'LOCALTIME', 'LOCALTIMESTAMP', 'LOCATE', 'LOG', 'LOG2', 'LOG10', 151 | 'LOWER', 'LPAD', 'LTRIM', 'MAKE_SET', 'MAKEDATE', 'MAKETIME', 152 | 'MASTER_POS_WAIT', 'MATCH', 'MAX', 'MD5', 'MICROSECOND', 'MID', 'MIN', 153 | 'MINUTE', 'MOD', 'MONTH', 'MONTHNAME', 'NEXTVAL', 'NOW', 'NULLIF', 'OCT', 154 | 'OCTET_LENGTH', 'OLD_PASSWORD', 'ORD', 'PASSWORD', 'PERIOD_ADD', 'PERIOD_DIFF', 155 | 'PI', 'POSITION', 'POW', 'POWER', 'QUARTER', 'QUOTE', 'RADIANS', 'RAND', 156 | 'RELEASE_LOCK', 'REPEAT', 'REPLACE', 'REVERSE', 'RIGHT', 'ROUND', 'ROW_COUNT', 157 | 'RPAD', 'RTRIM', 'SEC_TO_TIME', 'SECOND', 'SESSION_USER', 'SHA', 'SHA1', 158 | 'SIGN', 'SOUNDEX', 'SPACE', 'SQRT', 'STD', 'STDDEV', 'STDDEV_POP', 159 | 'STDDEV_SAMP', 'STRCMP', 'STR_TO_DATE', 'SUBDATE', 'SUBSTRING', 160 | 'SUBSTRING_INDEX', 'SUBTIME', 'SUM', 'SYSDATE', 'SYSTEM_USER', 'TAN', 'TIME', 161 | 'TIMEDIFF', 'TIMESTAMP', 'TIMESTAMPADD', 'TIMESTAMPDIFF', 'TIME_FORMAT', 162 | 'TIME_TO_SEC', 'TO_DAYS', 'TRIM', 'TRUNCATE', 'UCASE', 'UNCOMPRESS', 163 | 'UNCOMPRESSED_LENGTH', 'UNHEX', 'UNIX_TIMESTAMP', 'UPPER', 'USER', 'UTC_DATE', 164 | 'UTC_TIME', 'UTC_TIMESTAMP', 'UUID', 'VAR_POP', 'VAR_SAMP', 'VARIANCE', 165 | 'VERSION', 'WEEK', 'WEEKDAY', 'WEEKOFYEAR', 'YEAR', 'YEARWEEK'); 166 | 167 | protected static $aggregateFunctions = array('AVG', 'SUM', 'COUNT', 'MIN', 'MAX', 'STDDEV', 'STDDEV_SAMP', 168 | 'STDDEV_POP', 'VARIANCE', 'VAR_SAMP', 'VAR_POP', 'GROUP_CONCAT', 169 | 'BIT_AND', 'BIT_OR', 'BIT_XOR'); 170 | } 171 | -------------------------------------------------------------------------------- /tests/vendor/soundintheory/php-sql-parser/src/PHPSQL/Parser/Lexer.php: -------------------------------------------------------------------------------- 1 | 9 | * with contributions by Dan Vande More 10 | * 11 | * All rights reserved. 12 | * 13 | * Redistribution and use in source and binary forms, with or without modification, 14 | * are permitted provided that the following conditions are met: 15 | * 16 | * * Redistributions of source code must retain the above copyright notice, 17 | * this list of conditions and the following disclaimer. 18 | * * Redistributions in binary form must reproduce the above copyright notice, 19 | * this list of conditions and the following disclaimer in the documentation 20 | * and/or other materials provided with the distribution. 21 | * 22 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 23 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 24 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 25 | * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 26 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 27 | * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 28 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 29 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 30 | * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 31 | * DAMAGE. 32 | */ 33 | 34 | namespace PHPSQL\Parser; 35 | 36 | /** 37 | * This class splits the SQL string into little parts, which the parser can 38 | * use to build the result array. 39 | * 40 | * @author arothe 41 | * 42 | */ 43 | class Lexer extends \PHPSQL\Parser\Utils { 44 | 45 | private $splitters; 46 | 47 | public function __construct() { 48 | $this->splitters = new \PHPSQL\Parser\Lexer\Splitter(); 49 | } 50 | 51 | public function split($sql) { 52 | if (!is_string($sql)) { 53 | throw new \PHPSQL\Exception\InvalidParameter($sql); 54 | } 55 | 56 | $tokens = array(); 57 | $token = ""; 58 | 59 | $splitLen = $this->splitters->getMaxLengthOfSplitter(); 60 | $found = false; 61 | $len = strlen($sql); 62 | $pos = 0; 63 | 64 | while ($pos < $len) { 65 | 66 | for ($i = $splitLen; $i > 0; $i--) { 67 | $substr = substr($sql, $pos, $i); 68 | if ($this->splitters->isSplitter($substr)) { 69 | 70 | if ($token !== "") { 71 | $tokens[] = $token; 72 | } 73 | 74 | $tokens[] = $substr; 75 | $pos += $i; 76 | $token = ""; 77 | 78 | continue 2; 79 | } 80 | } 81 | 82 | $token .= $sql[$pos]; 83 | $pos++; 84 | } 85 | 86 | if ($token !== "") { 87 | $tokens[] = $token; 88 | } 89 | 90 | $tokens = $this->concatEscapeSequences($tokens); 91 | $tokens = $this->balanceBackticks($tokens); 92 | $tokens = $this->concatColReferences($tokens); 93 | $tokens = $this->balanceParenthesis($tokens); 94 | $tokens = $this->balanceMultilineComments($tokens); 95 | $tokens = $this->concatInlineComments($tokens); 96 | $tokens = $this->concatUserDefinedVariables($tokens); 97 | return $tokens; 98 | } 99 | 100 | private function concatUserDefinedVariables($tokens) { 101 | $i = 0; 102 | $cnt = count($tokens); 103 | $userdef = false; 104 | 105 | while ($i < $cnt) { 106 | 107 | if (!isset($tokens[$i])) { 108 | $i++; 109 | continue; 110 | } 111 | 112 | $token = $tokens[$i]; 113 | 114 | if ($userdef !== false) { 115 | $tokens[$userdef] .= $token; 116 | unset($tokens[$i]); 117 | if ($token !== "@") { 118 | $userdef = false; 119 | } 120 | } 121 | 122 | if ($userdef === false && $token === "@") { 123 | $userdef = $i; 124 | } 125 | 126 | $i++; 127 | } 128 | 129 | return array_values($tokens); 130 | } 131 | 132 | private function concatInlineComments($tokens) { 133 | 134 | $i = 0; 135 | $cnt = count($tokens); 136 | $comment = false; 137 | 138 | while ($i < $cnt) { 139 | 140 | if (!isset($tokens[$i])) { 141 | $i++; 142 | continue; 143 | } 144 | 145 | $token = $tokens[$i]; 146 | 147 | if ($comment !== false) { 148 | if ($token === "\n" || $token === "\r\n") { 149 | $comment = false; 150 | } else { 151 | unset($tokens[$i]); 152 | $tokens[$comment] .= $token; 153 | } 154 | } 155 | 156 | if (($comment === false) && ($token === "-")) { 157 | if (isset($tokens[$i + 1]) && $tokens[$i + 1] === "-") { 158 | $comment = $i; 159 | $tokens[$i] = "--"; 160 | $i++; 161 | unset($tokens[$i]); 162 | continue; 163 | } 164 | } 165 | 166 | $i++; 167 | } 168 | 169 | return array_values($tokens); 170 | } 171 | 172 | private function balanceMultilineComments($tokens) { 173 | 174 | $i = 0; 175 | $cnt = count($tokens); 176 | $comment = false; 177 | 178 | while ($i < $cnt) { 179 | 180 | if (!isset($tokens[$i])) { 181 | $i++; 182 | continue; 183 | } 184 | 185 | $token = $tokens[$i]; 186 | 187 | if ($comment !== false) { 188 | unset($tokens[$i]); 189 | $tokens[$comment] .= $token; 190 | if ($token === "*" && isset($tokens[$i + 1]) && $tokens[$i + 1] === "/") { 191 | unset($tokens[$i + 1]); 192 | $tokens[$comment] .= "/"; 193 | $comment = false; 194 | } 195 | } 196 | 197 | if (($comment === false) && ($token === "/")) { 198 | if (isset($tokens[$i + 1]) && $tokens[$i + 1] === "*") { 199 | $comment = $i; 200 | $tokens[$i] = "/*"; 201 | $i++; 202 | unset($tokens[$i]); 203 | continue; 204 | } 205 | } 206 | 207 | $i++; 208 | } 209 | return array_values($tokens); 210 | } 211 | 212 | private function isBacktick($token) { 213 | return ($token === "'" || $token === "\"" || $token === "`"); 214 | } 215 | 216 | private function balanceBackticks($tokens) { 217 | $i = 0; 218 | $cnt = count($tokens); 219 | while ($i < $cnt) { 220 | 221 | if (!isset($tokens[$i])) { 222 | $i++; 223 | continue; 224 | } 225 | 226 | $token = $tokens[$i]; 227 | 228 | if ($this->isBacktick($token)) { 229 | $tokens = $this->balanceCharacter($tokens, $i, $token); 230 | } 231 | 232 | $i++; 233 | } 234 | 235 | return $tokens; 236 | } 237 | 238 | # backticks are not balanced within one token, so we have 239 | # to re-combine some tokens 240 | private function balanceCharacter($tokens, $idx, $char) { 241 | 242 | $token_count = count($tokens); 243 | $i = $idx + 1; 244 | while ($i < $token_count) { 245 | 246 | if (!isset($tokens[$i])) { 247 | $i++; 248 | continue; 249 | } 250 | 251 | $token = $tokens[$i]; 252 | $tokens[$idx] .= $token; 253 | unset($tokens[$i]); 254 | 255 | if ($token === $char) { 256 | break; 257 | } 258 | 259 | $i++; 260 | } 261 | return array_values($tokens); 262 | } 263 | 264 | /* 265 | * does the token ends with dot? 266 | * concat it with the next token 267 | * 268 | * does the token starts with a dot? 269 | * concat it with the previous token 270 | */ 271 | private function concatColReferences($tokens) { 272 | 273 | $cnt = count($tokens); 274 | $i = 0; 275 | while ($i < $cnt) { 276 | 277 | if (!isset($tokens[$i])) { 278 | $i++; 279 | continue; 280 | } 281 | 282 | if ($tokens[$i][0] === ".") { 283 | 284 | // concat the previous tokens, till the token has been changed 285 | $k = $i - 1; 286 | $len = strlen($tokens[$i]); 287 | while (($k >= 0) && ($len == strlen($tokens[$i]))) { 288 | if (!isset($tokens[$k])) { # FIXME: this can be wrong if we have schema . table . column 289 | $k--; 290 | continue; 291 | } 292 | $tokens[$i] = $tokens[$k] . $tokens[$i]; 293 | unset($tokens[$k]); 294 | $k--; 295 | } 296 | } 297 | 298 | if ($this->endsWith($tokens[$i], '.')) { 299 | 300 | // concat the next tokens, till the token has been changed 301 | $k = $i + 1; 302 | $len = strlen($tokens[$i]); 303 | while (($k < $cnt) && ($len == strlen($tokens[$i]))) { 304 | if (!isset($tokens[$k])) { 305 | $k++; 306 | continue; 307 | } 308 | $tokens[$i] .= $tokens[$k]; 309 | unset($tokens[$k]); 310 | $k++; 311 | } 312 | } 313 | 314 | $i++; 315 | } 316 | 317 | return array_values($tokens); 318 | } 319 | 320 | private function concatEscapeSequences($tokens) { 321 | $tokenCount = count($tokens); 322 | $i = 0; 323 | while ($i < $tokenCount) { 324 | 325 | if ($this->endsWith($tokens[$i], "\\")) { 326 | $i++; 327 | if (isset($tokens[$i])) { 328 | $tokens[$i - 1] .= $tokens[$i]; 329 | unset($tokens[$i]); 330 | } 331 | } 332 | $i++; 333 | } 334 | return array_values($tokens); 335 | } 336 | 337 | private function balanceParenthesis($tokens) { 338 | $token_count = count($tokens); 339 | $i = 0; 340 | while ($i < $token_count) { 341 | if ($tokens[$i] !== '(') { 342 | $i++; 343 | continue; 344 | } 345 | $count = 1; 346 | for ($n = $i + 1; $n < $token_count; $n++) { 347 | $token = $tokens[$n]; 348 | if ($token === '(') { 349 | $count++; 350 | } 351 | if ($token === ')') { 352 | $count--; 353 | } 354 | $tokens[$i] .= $token; 355 | unset($tokens[$n]); 356 | if ($count === 0) { 357 | $n++; 358 | break; 359 | } 360 | } 361 | $i = $n; 362 | } 363 | return array_values($tokens); 364 | } 365 | } 366 | -------------------------------------------------------------------------------- /tests/vendor/soundintheory/php-sql-parser/src/PHPSQL/Parser/Lexer/Splitter.php: -------------------------------------------------------------------------------- 1 | 10 | * with contributions by Dan Vande More 11 | * 12 | * All rights reserved. 13 | * 14 | * Redistribution and use in source and binary forms, with or without modification, 15 | * are permitted provided that the following conditions are met: 16 | * 17 | * * Redistributions of source code must retain the above copyright notice, 18 | * this list of conditions and the following disclaimer. 19 | * * Redistributions in binary form must reproduce the above copyright notice, 20 | * this list of conditions and the following disclaimer in the documentation 21 | * and/or other materials provided with the distribution. 22 | * 23 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 24 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 25 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 26 | * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 27 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 28 | * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 29 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 30 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 31 | * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 32 | * DAMAGE. 33 | */ 34 | 35 | namespace PHPSQL\Parser\Lexer; 36 | 37 | class Splitter { 38 | 39 | private static $splitters = array("\r\n", "!=", ">=", "<=", "<>", ":=", "\\", "&&", ">", "<", "|", "=", "^", "(", 40 | ")", "\t", "\n", "'", "\"", "`", ",", "@", " ", "+", "-", "*", "/", ";"); 41 | private $tokenSize; 42 | private $hashSet; 43 | 44 | public function __construct() { 45 | $this->tokenSize = strlen(self::$splitters[0]); # should be the largest one 46 | $this->hashSet = array_flip(self::$splitters); 47 | } 48 | 49 | public function getMaxLengthOfSplitter() { 50 | return $this->tokenSize; 51 | } 52 | 53 | public function isSplitter($token) { 54 | return isset($this->hashSet[$token]); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /tests/vendor/soundintheory/php-sql-parser/src/PHPSQL/Parser/PositionCalculator.php: -------------------------------------------------------------------------------- 1 | 10 | * with contributions by Dan Vande More 11 | * 12 | * All rights reserved. 13 | * 14 | * Redistribution and use in source and binary forms, with or without modification, 15 | * are permitted provided that the following conditions are met: 16 | * 17 | * * Redistributions of source code must retain the above copyright notice, 18 | * this list of conditions and the following disclaimer. 19 | * * Redistributions in binary form must reproduce the above copyright notice, 20 | * this list of conditions and the following disclaimer in the documentation 21 | * and/or other materials provided with the distribution. 22 | * 23 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 24 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 25 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 26 | * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 27 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 28 | * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 29 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 30 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 31 | * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 32 | * DAMAGE. 33 | */ 34 | 35 | namespace PHPSQL\Parser; 36 | 37 | /** 38 | * 39 | * This class calculates the positions 40 | * of base_expr within the original SQL statement. 41 | * 42 | * @author arothe 43 | * 44 | */ 45 | class PositionCalculator extends \PHPSQL\Parser\Utils { 46 | 47 | private static $allowedOnOperator = array("\t", "\n", "\r", " ", ",", "(", ")", "_", "'", "\""); 48 | private static $allowedOnOther = array("\t", "\n", "\r", " ", ",", "(", ")", "<", ">", "*", "+", "-", "/", "|", 49 | "&", "=", "!", ";"); 50 | 51 | private function printPos($text, $sql, $charPos, $key, $parsed, $backtracking) { 52 | if (!isset($_ENV['DEBUG'])) { 53 | return; 54 | } 55 | 56 | $spaces = ""; 57 | $caller = debug_backtrace(); 58 | $i = 1; 59 | while ($caller[$i]['function'] === 'lookForBaseExpression') { 60 | $spaces .= " "; 61 | $i++; 62 | } 63 | $holdem = substr($sql, 0, $charPos) . "^" . substr($sql, $charPos); 64 | echo $spaces . $text . " key:" . $key . " parsed:" . $parsed . " back:" . serialize($backtracking) . " " 65 | . $holdem . "\n"; 66 | } 67 | 68 | public function setPositionsWithinSQL($sql, $parsed) { 69 | $charPos = 0; 70 | $backtracking = array(); 71 | $this->lookForBaseExpression($sql, $charPos, $parsed, 0, $backtracking); 72 | return $parsed; 73 | } 74 | 75 | private function findPositionWithinString($sql, $value, $expr_type) { 76 | 77 | $offset = 0; 78 | $ok = false; 79 | $pos = false; 80 | while (true) { 81 | 82 | $pos = strpos($sql, $value, $offset); 83 | if ($pos === false) { 84 | break; 85 | } 86 | 87 | $before = ""; 88 | if ($pos > 0) { 89 | $before = $sql[$pos - 1]; 90 | } 91 | 92 | $after = ""; 93 | if (isset($sql[$pos + strlen($value)])) { 94 | $after = $sql[$pos + strlen($value)]; 95 | } 96 | 97 | # if we have an operator, it should be surrounded by 98 | # whitespace, comma, parenthesis, digit or letter, end_of_string 99 | # an operator should not be surrounded by another operator 100 | 101 | if ($expr_type === 'operator') { 102 | 103 | $ok = ($before === "" || in_array($before, self::$allowedOnOperator, true)) 104 | || (strtolower($before) >= 'a' && strtolower($before) <= 'z') 105 | || ($before >= '0' && $before <= '9'); 106 | $ok = $ok 107 | && ($after === "" || in_array($after, self::$allowedOnOperator, true) 108 | || (strtolower($after) >= 'a' && strtolower($after) <= 'z') 109 | || ($after >= '0' && $after <= '9') || ($after === '?') || ($after === '@')); 110 | 111 | if (!$ok) { 112 | $offset = $pos + 1; 113 | continue; 114 | } 115 | 116 | break; 117 | } 118 | 119 | # in all other cases we accept 120 | # whitespace, comma, operators, parenthesis and end_of_string 121 | 122 | $ok = ($before === "" || in_array($before, self::$allowedOnOther, true)); 123 | $ok = $ok && ($after === "" || in_array($after, self::$allowedOnOther, true)); 124 | 125 | if ($ok) { 126 | break; 127 | } 128 | 129 | $offset = $pos + 1; 130 | } 131 | 132 | return $pos; 133 | } 134 | 135 | private function lookForBaseExpression($sql, &$charPos, &$parsed, $key, &$backtracking) { 136 | if (!is_numeric($key)) { 137 | if (($key === 'UNION' || $key === 'UNION ALL') 138 | || ($key === 'expr_type' && $parsed === \PHPSQL\Expression\Type::EXPRESSION) 139 | || ($key === 'expr_type' && $parsed === \PHPSQL\Expression\Type::SUBQUERY) 140 | || ($key === 'expr_type' && $parsed === \PHPSQL\Expression\Type::BRACKET_EXPRESSION) 141 | || ($key === 'expr_type' && $parsed === \PHPSQL\Expression\Type::TABLE_EXPRESSION) 142 | || ($key === 'expr_type' && $parsed === \PHPSQL\Expression\Type::RECORD) 143 | || ($key === 'expr_type' && $parsed === \PHPSQL\Expression\Type::IN_LIST) 144 | || ($key === 'expr_type' && $parsed === \PHPSQL\Expression\Type::MATCH_ARGUMENTS) 145 | || ($key === 'alias' && $parsed !== false)) { 146 | # we hold the current position and come back after the next base_expr 147 | # we do this, because the next base_expr contains the complete expression/subquery/record 148 | # and we have to look into it too 149 | $backtracking[] = $charPos; 150 | 151 | } elseif (($key === 'ref_clause' || $key === 'columns') && $parsed !== false) { 152 | # we hold the current position and come back after n base_expr(s) 153 | # there is an array of sub-elements before (!) the base_expr clause of the current element 154 | # so we go through the sub-elements and must come at the end 155 | $backtracking[] = $charPos; 156 | for ($i = 1; $i < count($parsed); $i++) { 157 | $backtracking[] = false; # backtracking only after n base_expr! 158 | } 159 | } elseif ($key === 'sub_tree' && $parsed !== false) { 160 | # we prevent wrong backtracking on subtrees (too much array_pop()) 161 | # there is an array of sub-elements after(!) the base_expr clause of the current element 162 | # so we go through the sub-elements and must not come back at the end 163 | for ($i = 1; $i < count($parsed); $i++) { 164 | $backtracking[] = false; 165 | } 166 | } else { 167 | # move the current pos after the keyword 168 | # SELECT, WHERE, INSERT etc. 169 | if (in_array($key, parent::$reserved)) { 170 | $charPos = stripos($sql, $key, $charPos); 171 | $charPos += strlen($key); 172 | } 173 | } 174 | } 175 | 176 | if (!is_array($parsed)) { 177 | return; 178 | } 179 | 180 | foreach ($parsed as $key => $value) { 181 | if ($key === 'base_expr') { 182 | 183 | #$this->printPos("0", $sql, $charPos, $key, $value, $backtracking); 184 | 185 | $subject = substr($sql, $charPos); 186 | $pos = $this->findPositionWithinString($subject, $value, 187 | isset($parsed['expr_type']) ? $parsed['expr_type'] : 'alias'); 188 | if ($pos === false) { 189 | throw new \PHPSQL\Exception\UnableToCalculatePosition($value, $subject); 190 | } 191 | 192 | $parsed['position'] = $charPos + $pos; 193 | $charPos += $pos + strlen($value); 194 | 195 | #$this->printPos("1", $sql, $charPos, $key, $value, $backtracking); 196 | 197 | $oldPos = array_pop($backtracking); 198 | if (isset($oldPos) && $oldPos !== false) { 199 | $charPos = $oldPos; 200 | } 201 | 202 | #$this->printPos("2", $sql, $charPos, $key, $value, $backtracking); 203 | 204 | } else { 205 | $this->lookForBaseExpression($sql, $charPos, $parsed[$key], $key, $backtracking); 206 | } 207 | } 208 | } 209 | } 210 | -------------------------------------------------------------------------------- /tests/vendor/soundintheory/php-sql-parser/src/PHPSQL/Parser/Utils.php: -------------------------------------------------------------------------------- 1 | 9 | * with contributions by Dan Vande More 10 | * 11 | * All rights reserved. 12 | * 13 | * Redistribution and use in source and binary forms, with or without modification, 14 | * are permitted provided that the following conditions are met: 15 | * 16 | * * Redistributions of source code must retain the above copyright notice, 17 | * this list of conditions and the following disclaimer. 18 | * * Redistributions in binary form must reproduce the above copyright notice, 19 | * this list of conditions and the following disclaimer in the documentation 20 | * and/or other materials provided with the distribution. 21 | * 22 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 23 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 24 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 25 | * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 26 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 27 | * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 28 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 29 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 30 | * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 31 | * DAMAGE. 32 | */ 33 | 34 | namespace PHPSQL\Parser; 35 | 36 | /** 37 | * This class implements some helper functions. 38 | * @author arothe 39 | * 40 | */ 41 | class Utils extends \PHPSQL\Parser\Constants { 42 | 43 | /** 44 | * Ends the given string $haystack with the string $needle? 45 | * @param string $haystack 46 | * @param string $needle 47 | * @return bool $in 48 | */ 49 | protected function endsWith($haystack, $needle) { 50 | $length = strlen($needle); 51 | if ($length == 0) { 52 | return true; 53 | } 54 | 55 | $start = $length * -1; 56 | return (substr($haystack, $start) === $needle); 57 | } 58 | 59 | /** 60 | * Revokes the escaping characters from an expression 61 | */ 62 | protected function revokeEscaping($sql) { 63 | $result = trim($sql); 64 | if (($result[0] === '`') && ($result[strlen($result) - 1] === '`')) { 65 | $result = substr($result, 1, -1); 66 | } 67 | return str_replace('``', '`', $result); 68 | } 69 | 70 | /** 71 | * This method removes parenthesis from start of the given string. 72 | * It removes also the associated closing parenthesis. 73 | */ 74 | protected function removeParenthesisFromStart($token) { 75 | 76 | $parenthesisRemoved = 0; 77 | 78 | $trim = trim($token); 79 | if ($trim !== "" && $trim[0] === "(") { // remove only one parenthesis pair now! 80 | $parenthesisRemoved++; 81 | $trim[0] = " "; 82 | $trim = trim($trim); 83 | } 84 | 85 | $parenthesis = $parenthesisRemoved; 86 | $i = 0; 87 | $string = 0; 88 | while ($i < strlen($trim)) { 89 | 90 | if ($trim[$i] === "\\") { 91 | $i += 2; # an escape character, the next character is irrelevant 92 | continue; 93 | } 94 | 95 | if ($trim[$i] === "'" || $trim[$i] === '"') { 96 | $string++; 97 | } 98 | 99 | if (($string % 2 === 0) && ($trim[$i] === "(")) { 100 | $parenthesis++; 101 | } 102 | 103 | if (($string % 2 === 0) && ($trim[$i] === ")")) { 104 | if ($parenthesis == $parenthesisRemoved) { 105 | $trim[$i] = " "; 106 | $parenthesisRemoved--; 107 | } 108 | $parenthesis--; 109 | } 110 | $i++; 111 | } 112 | return trim($trim); 113 | } 114 | 115 | public function getLastOf($array) { 116 | // $array is a copy of the original array, so we can change it without sideeffects 117 | if (!is_array($array)) { 118 | return false; 119 | } 120 | return array_pop($array); 121 | } 122 | 123 | /** 124 | * translates an array of objects into an associative array 125 | */ 126 | public function toArray($tokenList) { 127 | $expr = array(); 128 | foreach ($tokenList as $token) { 129 | /** 130 | * @var $token \PHPSQL\Expression\Token 131 | */ 132 | $expr[] = $token->toArray(); 133 | } 134 | return (empty($expr) ? false : $expr); 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /vendor/autoload.php: -------------------------------------------------------------------------------- 1 | 7 | * Jordi Boggiano 8 | * 9 | * For the full copyright and license information, please view the LICENSE 10 | * file that was distributed with this source code. 11 | */ 12 | 13 | namespace Composer\Autoload; 14 | 15 | /** 16 | * ClassLoader implements a PSR-0 class loader 17 | * 18 | * See https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md 19 | * 20 | * $loader = new \Composer\Autoload\ClassLoader(); 21 | * 22 | * // register classes with namespaces 23 | * $loader->add('Symfony\Component', __DIR__.'/component'); 24 | * $loader->add('Symfony', __DIR__.'/framework'); 25 | * 26 | * // activate the autoloader 27 | * $loader->register(); 28 | * 29 | * // to enable searching the include path (eg. for PEAR packages) 30 | * $loader->setUseIncludePath(true); 31 | * 32 | * In this example, if you try to use a class in the Symfony\Component 33 | * namespace or one of its children (Symfony\Component\Console for instance), 34 | * the autoloader will first look for the class under the component/ 35 | * directory, and it will then fallback to the framework/ directory if not 36 | * found before giving up. 37 | * 38 | * This class is loosely based on the Symfony UniversalClassLoader. 39 | * 40 | * @author Fabien Potencier 41 | * @author Jordi Boggiano 42 | */ 43 | class ClassLoader 44 | { 45 | // PSR-4 46 | private $prefixLengthsPsr4 = array(); 47 | private $prefixDirsPsr4 = array(); 48 | private $fallbackDirsPsr4 = array(); 49 | 50 | // PSR-0 51 | private $prefixesPsr0 = array(); 52 | private $fallbackDirsPsr0 = array(); 53 | 54 | private $useIncludePath = false; 55 | private $classMap = array(); 56 | 57 | public function getPrefixes() 58 | { 59 | return call_user_func_array('array_merge', $this->prefixesPsr0); 60 | } 61 | 62 | public function getPrefixesPsr4() 63 | { 64 | return $this->prefixDirsPsr4; 65 | } 66 | 67 | public function getFallbackDirs() 68 | { 69 | return $this->fallbackDirsPsr0; 70 | } 71 | 72 | public function getFallbackDirsPsr4() 73 | { 74 | return $this->fallbackDirsPsr4; 75 | } 76 | 77 | public function getClassMap() 78 | { 79 | return $this->classMap; 80 | } 81 | 82 | /** 83 | * @param array $classMap Class to filename map 84 | */ 85 | public function addClassMap(array $classMap) 86 | { 87 | if ($this->classMap) { 88 | $this->classMap = array_merge($this->classMap, $classMap); 89 | } else { 90 | $this->classMap = $classMap; 91 | } 92 | } 93 | 94 | /** 95 | * Registers a set of PSR-0 directories for a given prefix, either 96 | * appending or prepending to the ones previously set for this prefix. 97 | * 98 | * @param string $prefix The prefix 99 | * @param array|string $paths The PSR-0 root directories 100 | * @param bool $prepend Whether to prepend the directories 101 | */ 102 | public function add($prefix, $paths, $prepend = false) 103 | { 104 | if (!$prefix) { 105 | if ($prepend) { 106 | $this->fallbackDirsPsr0 = array_merge( 107 | (array) $paths, 108 | $this->fallbackDirsPsr0 109 | ); 110 | } else { 111 | $this->fallbackDirsPsr0 = array_merge( 112 | $this->fallbackDirsPsr0, 113 | (array) $paths 114 | ); 115 | } 116 | 117 | return; 118 | } 119 | 120 | $first = $prefix[0]; 121 | if (!isset($this->prefixesPsr0[$first][$prefix])) { 122 | $this->prefixesPsr0[$first][$prefix] = (array) $paths; 123 | 124 | return; 125 | } 126 | if ($prepend) { 127 | $this->prefixesPsr0[$first][$prefix] = array_merge( 128 | (array) $paths, 129 | $this->prefixesPsr0[$first][$prefix] 130 | ); 131 | } else { 132 | $this->prefixesPsr0[$first][$prefix] = array_merge( 133 | $this->prefixesPsr0[$first][$prefix], 134 | (array) $paths 135 | ); 136 | } 137 | } 138 | 139 | /** 140 | * Registers a set of PSR-4 directories for a given namespace, either 141 | * appending or prepending to the ones previously set for this namespace. 142 | * 143 | * @param string $prefix The prefix/namespace, with trailing '\\' 144 | * @param array|string $paths The PSR-0 base directories 145 | * @param bool $prepend Whether to prepend the directories 146 | * 147 | * @throws \InvalidArgumentException 148 | */ 149 | public function addPsr4($prefix, $paths, $prepend = false) 150 | { 151 | if (!$prefix) { 152 | // Register directories for the root namespace. 153 | if ($prepend) { 154 | $this->fallbackDirsPsr4 = array_merge( 155 | (array) $paths, 156 | $this->fallbackDirsPsr4 157 | ); 158 | } else { 159 | $this->fallbackDirsPsr4 = array_merge( 160 | $this->fallbackDirsPsr4, 161 | (array) $paths 162 | ); 163 | } 164 | } elseif (!isset($this->prefixDirsPsr4[$prefix])) { 165 | // Register directories for a new namespace. 166 | $length = strlen($prefix); 167 | if ('\\' !== $prefix[$length - 1]) { 168 | throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); 169 | } 170 | $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; 171 | $this->prefixDirsPsr4[$prefix] = (array) $paths; 172 | } elseif ($prepend) { 173 | // Prepend directories for an already registered namespace. 174 | $this->prefixDirsPsr4[$prefix] = array_merge( 175 | (array) $paths, 176 | $this->prefixDirsPsr4[$prefix] 177 | ); 178 | } else { 179 | // Append directories for an already registered namespace. 180 | $this->prefixDirsPsr4[$prefix] = array_merge( 181 | $this->prefixDirsPsr4[$prefix], 182 | (array) $paths 183 | ); 184 | } 185 | } 186 | 187 | /** 188 | * Registers a set of PSR-0 directories for a given prefix, 189 | * replacing any others previously set for this prefix. 190 | * 191 | * @param string $prefix The prefix 192 | * @param array|string $paths The PSR-0 base directories 193 | */ 194 | public function set($prefix, $paths) 195 | { 196 | if (!$prefix) { 197 | $this->fallbackDirsPsr0 = (array) $paths; 198 | } else { 199 | $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths; 200 | } 201 | } 202 | 203 | /** 204 | * Registers a set of PSR-4 directories for a given namespace, 205 | * replacing any others previously set for this namespace. 206 | * 207 | * @param string $prefix The prefix/namespace, with trailing '\\' 208 | * @param array|string $paths The PSR-4 base directories 209 | * 210 | * @throws \InvalidArgumentException 211 | */ 212 | public function setPsr4($prefix, $paths) 213 | { 214 | if (!$prefix) { 215 | $this->fallbackDirsPsr4 = (array) $paths; 216 | } else { 217 | $length = strlen($prefix); 218 | if ('\\' !== $prefix[$length - 1]) { 219 | throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); 220 | } 221 | $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; 222 | $this->prefixDirsPsr4[$prefix] = (array) $paths; 223 | } 224 | } 225 | 226 | /** 227 | * Turns on searching the include path for class files. 228 | * 229 | * @param bool $useIncludePath 230 | */ 231 | public function setUseIncludePath($useIncludePath) 232 | { 233 | $this->useIncludePath = $useIncludePath; 234 | } 235 | 236 | /** 237 | * Can be used to check if the autoloader uses the include path to check 238 | * for classes. 239 | * 240 | * @return bool 241 | */ 242 | public function getUseIncludePath() 243 | { 244 | return $this->useIncludePath; 245 | } 246 | 247 | /** 248 | * Registers this instance as an autoloader. 249 | * 250 | * @param bool $prepend Whether to prepend the autoloader or not 251 | */ 252 | public function register($prepend = false) 253 | { 254 | spl_autoload_register(array($this, 'loadClass'), true, $prepend); 255 | } 256 | 257 | /** 258 | * Unregisters this instance as an autoloader. 259 | */ 260 | public function unregister() 261 | { 262 | spl_autoload_unregister(array($this, 'loadClass')); 263 | } 264 | 265 | /** 266 | * Loads the given class or interface. 267 | * 268 | * @param string $class The name of the class 269 | * @return bool|null True if loaded, null otherwise 270 | */ 271 | public function loadClass($class) 272 | { 273 | if ($file = $this->findFile($class)) { 274 | includeFile($file); 275 | 276 | return true; 277 | } 278 | } 279 | 280 | /** 281 | * Finds the path to the file where the class is defined. 282 | * 283 | * @param string $class The name of the class 284 | * 285 | * @return string|false The path if found, false otherwise 286 | */ 287 | public function findFile($class) 288 | { 289 | // work around for PHP 5.3.0 - 5.3.2 https://bugs.php.net/50731 290 | if ('\\' == $class[0]) { 291 | $class = substr($class, 1); 292 | } 293 | 294 | // class map lookup 295 | if (isset($this->classMap[$class])) { 296 | return $this->classMap[$class]; 297 | } 298 | 299 | $file = $this->findFileWithExtension($class, '.php'); 300 | 301 | // Search for Hack files if we are running on HHVM 302 | if ($file === null && defined('HHVM_VERSION')) { 303 | $file = $this->findFileWithExtension($class, '.hh'); 304 | } 305 | 306 | if ($file === null) { 307 | // Remember that this class does not exist. 308 | return $this->classMap[$class] = false; 309 | } 310 | 311 | return $file; 312 | } 313 | 314 | private function findFileWithExtension($class, $ext) 315 | { 316 | // PSR-4 lookup 317 | $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext; 318 | 319 | $first = $class[0]; 320 | if (isset($this->prefixLengthsPsr4[$first])) { 321 | foreach ($this->prefixLengthsPsr4[$first] as $prefix => $length) { 322 | if (0 === strpos($class, $prefix)) { 323 | foreach ($this->prefixDirsPsr4[$prefix] as $dir) { 324 | if (file_exists($file = $dir . DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $length))) { 325 | return $file; 326 | } 327 | } 328 | } 329 | } 330 | } 331 | 332 | // PSR-4 fallback dirs 333 | foreach ($this->fallbackDirsPsr4 as $dir) { 334 | if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) { 335 | return $file; 336 | } 337 | } 338 | 339 | // PSR-0 lookup 340 | if (false !== $pos = strrpos($class, '\\')) { 341 | // namespaced class name 342 | $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1) 343 | . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR); 344 | } else { 345 | // PEAR-like class name 346 | $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext; 347 | } 348 | 349 | if (isset($this->prefixesPsr0[$first])) { 350 | foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) { 351 | if (0 === strpos($class, $prefix)) { 352 | foreach ($dirs as $dir) { 353 | if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { 354 | return $file; 355 | } 356 | } 357 | } 358 | } 359 | } 360 | 361 | // PSR-0 fallback dirs 362 | foreach ($this->fallbackDirsPsr0 as $dir) { 363 | if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { 364 | return $file; 365 | } 366 | } 367 | 368 | // PSR-0 include paths. 369 | if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) { 370 | return $file; 371 | } 372 | } 373 | } 374 | 375 | /** 376 | * Scope isolated include. 377 | * 378 | * Prevents access to $this/self from included files. 379 | */ 380 | function includeFile($file) 381 | { 382 | include $file; 383 | } 384 | -------------------------------------------------------------------------------- /vendor/composer/autoload_classmap.php: -------------------------------------------------------------------------------- 1 | array($baseDir . '/src'), 10 | 'PHPSQL' => array($vendorDir . '/soundintheory/php-sql-parser/src'), 11 | ); 12 | -------------------------------------------------------------------------------- /vendor/composer/autoload_psr4.php: -------------------------------------------------------------------------------- 1 | $path) { 28 | $loader->set($namespace, $path); 29 | } 30 | 31 | $map = require __DIR__ . '/autoload_psr4.php'; 32 | foreach ($map as $namespace => $path) { 33 | $loader->setPsr4($namespace, $path); 34 | } 35 | 36 | $classMap = require __DIR__ . '/autoload_classmap.php'; 37 | if ($classMap) { 38 | $loader->addClassMap($classMap); 39 | } 40 | 41 | $loader->register(true); 42 | 43 | return $loader; 44 | } 45 | } 46 | 47 | function composerRequireec97cf94e02d9279519ab8404367a120($file) 48 | { 49 | require $file; 50 | } 51 | -------------------------------------------------------------------------------- /vendor/composer/installed.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "soundintheory/php-sql-parser", 4 | "version": "1.0", 5 | "version_normalized": "1.0.0.0", 6 | "source": { 7 | "type": "git", 8 | "url": "https://github.com/soundintheory/php-sql-parser.git", 9 | "reference": "dcb81216a13be124d21711b8fefb6e80db7af472" 10 | }, 11 | "dist": { 12 | "type": "zip", 13 | "url": "https://api.github.com/repos/soundintheory/php-sql-parser/zipball/dcb81216a13be124d21711b8fefb6e80db7af472", 14 | "reference": "dcb81216a13be124d21711b8fefb6e80db7af472", 15 | "shasum": "" 16 | }, 17 | "require": { 18 | "php": ">=5.3.3" 19 | }, 20 | "time": "2013-08-09 21:16:50", 21 | "type": "library", 22 | "installation-source": "dist", 23 | "autoload": { 24 | "psr-0": { 25 | "PHPSQL": "src/" 26 | } 27 | }, 28 | "notification-url": "https://packagist.org/downloads/", 29 | "license": [ 30 | "BSD-2-Clause" 31 | ], 32 | "authors": [ 33 | { 34 | "name": "André Rothe", 35 | "email": "phosco@gmx.de", 36 | "homepage": "https://www.phosco.info", 37 | "role": "Committer" 38 | }, 39 | { 40 | "name": "Justin Swanhart", 41 | "email": "greenlion@gmail.com", 42 | "homepage": "http://code.google.com/u/greenlion@gmail.com/", 43 | "role": "Owner" 44 | }, 45 | { 46 | "name": "Andy White", 47 | "homepage": "https://github.com/soundintheory", 48 | "role": "maintainer" 49 | }, 50 | { 51 | "name": "Dan Vande More", 52 | "homepage": "https://github.com/fimbulvetr", 53 | "role": "contributor" 54 | } 55 | ], 56 | "description": "SQL parsing tools for PHP" 57 | } 58 | ] 59 | -------------------------------------------------------------------------------- /vendor/soundintheory/php-sql-parser/README.md: -------------------------------------------------------------------------------- 1 | PHP SQL Parser 2 | -------------- 3 | 4 | A fork of https://code.google.com/p/php-sql-parser/ 5 | 6 | A Parser for mysql-ish queries that can represent a query as an array. 7 | 8 | # Goals: 9 | 1. A PSR-0 Compatible implementation 10 | 2. Improvements 11 | 3. Profit!!! 12 | 13 | ## Usage 14 | 15 | ### Use your PSR-0 Compatible Autoloader or the sample one provided in example.php 16 | 17 | 18 | ## Improvements/Feedback. 19 | 20 | Please send them to me, or send a pull request. I will honor every reasonable request, where reasonable usually means elegance, simplicity and bug fixes. Suggestions for improvement are welcome, though you'll see them sooner if you write them. 21 | I will take unit tests as well! 22 | 23 | ## License 24 | 25 | PHPSQLParser is licensed under The BSD 2-Clause License, available online here: http://opensource.org/licenses/bsd-license.php 26 | 27 | /** 28 | * A pure PHP SQL (non validating) parser w/ focus on MySQL dialect of SQL 29 | * 30 | * Copyright (c) 2010-2012, Justin Swanhart 31 | * with contributions by André Rothe 32 | * with contributions by Dan Vande More 33 | * 34 | * All rights reserved. 35 | * 36 | * Redistribution and use in source and binary forms, with or without modification, 37 | * are permitted provided that the following conditions are met: 38 | * 39 | * * Redistributions of source code must retain the above copyright notice, 40 | * this list of conditions and the following disclaimer. 41 | * * Redistributions in binary form must reproduce the above copyright notice, 42 | * this list of conditions and the following disclaimer in the documentation 43 | * and/or other materials provided with the distribution. 44 | * 45 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 46 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 47 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 48 | * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 49 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 50 | * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 51 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 52 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 53 | * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 54 | * DAMAGE. 55 | */ -------------------------------------------------------------------------------- /vendor/soundintheory/php-sql-parser/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "soundintheory/php-sql-parser", 3 | "type": "library", 4 | "description": "SQL parsing tools for PHP", 5 | "license": "BSD-2-Clause", 6 | "require": { 7 | "php": ">=5.3.3" 8 | }, 9 | "autoload": { 10 | "psr-0": { "PHPSQL": "src/" } 11 | }, 12 | "authors": [ 13 | { "name": "Justin Swanhart", "email": "greenlion@gmail.com" }, 14 | { "name": "André Rothe", "email": "phosco@gmx.de" }, 15 | { "name": "Dan Vande More", "homepage": "https://github.com/fimbulvetr", "role": "contributor" }, 16 | { "name": "Andy White", "homepage": "https://github.com/soundintheory", "role": "maintainer" } 17 | ], 18 | "minimum-stability": "stable" 19 | } -------------------------------------------------------------------------------- /vendor/soundintheory/php-sql-parser/src/PHPSQL/Creator.php: -------------------------------------------------------------------------------- 1 | 8 | * with contributions by Dan Vande More 9 | * 10 | * 11 | * All rights reserved. 12 | * 13 | * Redistribution and use in source and binary forms, with or without modification, 14 | * are permitted provided that the following conditions are met: 15 | * 16 | * * Redistributions of source code must retain the above copyright notice, 17 | * this list of conditions and the following disclaimer. 18 | * * Redistributions in binary form must reproduce the above copyright notice, 19 | * this list of conditions and the following disclaimer in the documentation 20 | * andgo/or other materials provided with the distribution. 21 | * 22 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 23 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 24 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 25 | * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 26 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 27 | * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 28 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 29 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 30 | * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 31 | * DAMAGE. 32 | */ 33 | 34 | namespace PHPSQL; 35 | 36 | class Creator { 37 | 38 | public $created; 39 | 40 | public function __construct($parsed = false) { 41 | if ($parsed) { 42 | $this->create($parsed); 43 | } 44 | } 45 | 46 | public function create($parsed) { 47 | $k = key($parsed); 48 | switch ($k) { 49 | case "UNION": 50 | case "UNION ALL": 51 | throw new \PHPSQL\Exception\UnsupportedFeature($k); 52 | break; 53 | case "SELECT": 54 | $this->created = $this->processSelectStatement($parsed); 55 | break; 56 | case "INSERT": 57 | $this->created = $this->processInsertStatement($parsed); 58 | break; 59 | case "DELETE": 60 | $this->created = $this->processDeleteStatement($parsed); 61 | break; 62 | case "UPDATE": 63 | $this->created = $this->processUpdateStatement($parsed); 64 | break; 65 | default: 66 | throw new \PHPSQL\Exception\UnsupportedFeature($k); 67 | break; 68 | } 69 | return $this->created; 70 | } 71 | 72 | protected function processSelectStatement($parsed) { 73 | $sql = $this->processSELECT($parsed['SELECT']) . " " . $this->processFROM($parsed['FROM']); 74 | if (isset($parsed['WHERE'])) { 75 | $sql .= " " . $this->processWHERE($parsed['WHERE']); 76 | } 77 | if (isset($parsed['GROUP'])) { 78 | $sql .= " " . $this->processGROUP($parsed['GROUP']); 79 | } 80 | if (isset($parsed['ORDER'])) { 81 | $sql .= " " . $this->processORDER($parsed['ORDER']); 82 | } 83 | if (isset($parsed['LIMIT'])) { 84 | $sql .= " " . $this->processLIMIT($parsed['LIMIT']); 85 | } 86 | return $sql; 87 | } 88 | 89 | protected function processInsertStatement($parsed) { 90 | return $this->processINSERT($parsed['INSERT']) . " " . $this->processVALUES($parsed['VALUES']); 91 | # TODO: subquery? 92 | } 93 | 94 | protected function processDeleteStatement($parsed) { 95 | return $this->processDELETE($parsed['DELETE']) . " " . $this->processFROM($parsed['FROM']) . " " 96 | . $this->processWHERE($parsed['WHERE']); 97 | } 98 | 99 | protected function processUpdateStatement($parsed) { 100 | $sql = $this->processUPDATE($parsed['UPDATE']) . " " . $this->processSET($parsed['SET']); 101 | if (isset($parsed['WHERE'])) { 102 | $sql .= " " . $this->processWHERE($parsed['WHERE']); 103 | } 104 | return $sql; 105 | } 106 | 107 | protected function processDELETE($parsed) { 108 | $sql = "DELETE"; 109 | foreach ($parsed['TABLES'] as $k => $v) { 110 | $sql .= $v . ","; 111 | } 112 | return substr($sql, 0, -1); 113 | } 114 | 115 | protected function processSELECT($parsed) { 116 | $sql = ""; 117 | foreach ($parsed as $k => $v) { 118 | $len = strlen($sql); 119 | $sql .= $this->processColRef($v); 120 | $sql .= $this->processSelectExpression($v); 121 | $sql .= $this->processFunction($v); 122 | $sql .= $this->processConstant($v); 123 | 124 | if ($len == strlen($sql)) { 125 | throw new \PHPSQL\Exception\UnableToCreateSQL('SELECT', $k, $v, 'expr_type'); 126 | } 127 | 128 | $sql .= ","; 129 | } 130 | $sql = substr($sql, 0, -1); 131 | return "SELECT " . $sql; 132 | } 133 | 134 | protected function processFROM($parsed) { 135 | $sql = ""; 136 | foreach ($parsed as $k => $v) { 137 | $len = strlen($sql); 138 | $sql .= $this->processTable($v, $k); 139 | $sql .= $this->processTableExpression($v, $k); 140 | $sql .= $this->processSubquery($v, $k); 141 | 142 | if ($len == strlen($sql)) { 143 | throw new \PHPSQL\Exception\UnableToCreateSQL('FROM', $k, $v, 'expr_type'); 144 | } 145 | 146 | $sql .= " "; 147 | } 148 | return "FROM " . substr($sql, 0, -1); 149 | } 150 | 151 | protected function processORDER($parsed) { 152 | $sql = ""; 153 | foreach ($parsed as $k => $v) { 154 | $len = strlen($sql); 155 | $sql .= $this->processOrderByAlias($v); 156 | $sql .= $this->processColRef($v); 157 | 158 | if ($len == strlen($sql)) { 159 | throw new \PHPSQL\Exception\UnableToCreateSQL('ORDER', $k, $v, 'expr_type'); 160 | } 161 | 162 | $sql .= ","; 163 | } 164 | $sql = substr($sql, 0, -1); 165 | return "ORDER BY " . $sql; 166 | } 167 | 168 | protected function processLIMIT($parsed) { 169 | $sql = ($parsed['offset'] ? $parsed['offset'] . ", " : "") . $parsed['rowcount']; 170 | if ($sql === "") { 171 | throw new \PHPSQL\Exception\UnableToCreateSQL('LIMIT', 'rowcount', $parsed, 'rowcount'); 172 | } 173 | return "LIMIT " . $sql; 174 | } 175 | 176 | protected function processGROUP($parsed) { 177 | $sql = ""; 178 | foreach ($parsed as $k => $v) { 179 | $len = strlen($sql); 180 | $sql .= $this->processColRef($v); 181 | 182 | if ($len == strlen($sql)) { 183 | throw new \PHPSQL\Exception\UnableToCreateSQL('GROUP', $k, $v, 'expr_type'); 184 | } 185 | 186 | $sql .= ","; 187 | } 188 | $sql = substr($sql, 0, -1); 189 | return "GROUP BY " . $sql; 190 | } 191 | 192 | protected function processRecord($parsed) { 193 | if ($parsed['expr_type'] !== \PHPSQL\Expression\Type::RECORD) { 194 | return ""; 195 | } 196 | $sql = ""; 197 | foreach ($parsed['data'] as $k => $v) { 198 | $len = strlen($sql); 199 | $sql .= $this->processConstant($v); 200 | $sql .= $this->processFunction($v); 201 | $sql .= $this->processOperator($v); 202 | 203 | if ($len == strlen($sql)) { 204 | throw new \PHPSQL\Exception\UnableToCreateSQL(\PHPSQL\Expression\Type::RECORD, $k, $v, 'expr_type'); 205 | } 206 | 207 | $sql .= ","; 208 | } 209 | $sql = substr($sql, 0, -1); 210 | return "(" . $sql . ")"; 211 | 212 | } 213 | 214 | protected function processVALUES($parsed) { 215 | $sql = ""; 216 | foreach ($parsed as $k => $v) { 217 | $len = strlen($sql); 218 | $sql .= $this->processRecord($v); 219 | 220 | if ($len == strlen($sql)) { 221 | throw new \PHPSQL\Exception\UnableToCreateSQL('VALUES', $k, $v, 'expr_type'); 222 | } 223 | 224 | $sql .= ","; 225 | } 226 | $sql = substr($sql, 0, -1); 227 | return "VALUES " . $sql; 228 | } 229 | 230 | protected function processINSERT($parsed) { 231 | $sql = "INSERT INTO " . $parsed['table']; 232 | 233 | if ($parsed['columns'] === false) { 234 | return $sql; 235 | } 236 | 237 | $columns = ""; 238 | foreach ($parsed['columns'] as $k => $v) { 239 | $len = strlen($columns); 240 | $columns .= $this->processColRef($v); 241 | 242 | if ($len == strlen($columns)) { 243 | throw new \PHPSQL\Exception\UnableToCreateSQL('INSERT[columns]', $k, $v, 'expr_type'); 244 | } 245 | 246 | $columns .= ","; 247 | } 248 | 249 | if ($columns !== "") { 250 | $columns = " (" . substr($columns, 0, -1) . ")"; 251 | } 252 | 253 | $sql .= $columns; 254 | return $sql; 255 | } 256 | 257 | protected function processUPDATE($parsed) { 258 | return "UPDATE " . $parsed[0]['table']; 259 | } 260 | 261 | protected function processSetExpression($parsed) { 262 | if ($parsed['expr_type'] !== \PHPSQL\Expression\Type::EXPRESSION) { 263 | return ""; 264 | } 265 | $sql = ""; 266 | foreach ($parsed['sub_tree'] as $k => $v) { 267 | $len = strlen($sql); 268 | $sql .= $this->processColRef($v); 269 | $sql .= $this->processConstant($v); 270 | $sql .= $this->processOperator($v); 271 | $sql .= $this->processFunction($v); 272 | 273 | if ($len == strlen($sql)) { 274 | throw new \PHPSQL\Exception\UnableToCreateSQL('SET expression subtree', $k, $v, 'expr_type'); 275 | } 276 | 277 | $sql .= " "; 278 | } 279 | 280 | $sql = substr($sql, 0, -1); 281 | return $sql; 282 | } 283 | 284 | protected function processSET($parsed) { 285 | $sql = ""; 286 | foreach ($parsed as $k => $v) { 287 | $len = strlen($sql); 288 | $sql .= $this->processSetExpression($v); 289 | 290 | if ($len == strlen($sql)) { 291 | throw new \PHPSQL\Exception\UnableToCreateSQL('SET', $k, $v, 'expr_type'); 292 | } 293 | 294 | $sql .= ","; 295 | } 296 | return "SET " . substr($sql, 0, -1); 297 | } 298 | 299 | protected function processWHERE($parsed) { 300 | $sql = "WHERE "; 301 | foreach ($parsed as $k => $v) { 302 | $len = strlen($sql); 303 | 304 | $sql .= $this->processOperator($v); 305 | $sql .= $this->processConstant($v); 306 | $sql .= $this->processColRef($v); 307 | $sql .= $this->processSubquery($v); 308 | $sql .= $this->processInList($v); 309 | $sql .= $this->processFunction($v); 310 | $sql .= $this->processWhereExpression($v); 311 | $sql .= $this->processWhereBracketExpression($v); 312 | 313 | if (strlen($sql) == $len) { 314 | throw new \PHPSQL\Exception\UnableToCreateSQL('WHERE', $k, $v, 'expr_type'); 315 | } 316 | 317 | $sql .= " "; 318 | } 319 | return substr($sql, 0, -1); 320 | } 321 | 322 | protected function processWhereExpression($parsed) { 323 | if ($parsed['expr_type'] !== \PHPSQL\Expression\Type::EXPRESSION) { 324 | return ""; 325 | } 326 | $sql = ""; 327 | foreach ($parsed['sub_tree'] as $k => $v) { 328 | $len = strlen($sql); 329 | $sql .= $this->processColRef($v); 330 | $sql .= $this->processConstant($v); 331 | $sql .= $this->processOperator($v); 332 | $sql .= $this->processInList($v); 333 | $sql .= $this->processFunction($v); 334 | $sql .= $this->processWhereExpression($v); 335 | $sql .= $this->processWhereBracketExpression($v); 336 | 337 | if ($len == strlen($sql)) { 338 | throw new \PHPSQL\Exception\UnableToCreateSQL('WHERE expression subtree', $k, $v, 'expr_type'); 339 | } 340 | 341 | $sql .= " "; 342 | } 343 | 344 | $sql = substr($sql, 0, -1); 345 | return $sql; 346 | } 347 | 348 | protected function processWhereBracketExpression($parsed) { 349 | if ($parsed['expr_type'] !== \PHPSQL\Expression\Type::BRACKET_EXPRESSION) { 350 | return ""; 351 | } 352 | $sql = ""; 353 | foreach ($parsed['sub_tree'] as $k => $v) { 354 | $len = strlen($sql); 355 | $sql .= $this->processColRef($v); 356 | $sql .= $this->processConstant($v); 357 | $sql .= $this->processOperator($v); 358 | $sql .= $this->processInList($v); 359 | $sql .= $this->processFunction($v); 360 | $sql .= $this->processWhereExpression($v); 361 | $sql .= $this->processWhereBracketExpression($v); 362 | 363 | if ($len == strlen($sql)) { 364 | throw new \PHPSQL\Exception\UnableToCreateSQL('WHERE expression subtree', $k, $v, 'expr_type'); 365 | } 366 | 367 | $sql .= " "; 368 | } 369 | 370 | $sql = "(" . substr($sql, 0, -1) . ")"; 371 | return $sql; 372 | } 373 | 374 | protected function processOrderByAlias($parsed) { 375 | if ($parsed['expr_type'] !== \PHPSQL\Expression\Type::ALIAS) { 376 | return ""; 377 | } 378 | return $parsed['base_expr'] . $this->processDirection($parsed['direction']); 379 | } 380 | 381 | protected function processLimitRowCount($key, $value) { 382 | if ($key != 'rowcount') { 383 | return ""; 384 | } 385 | return $value; 386 | } 387 | 388 | protected function processLimitOffset($key, $value) { 389 | if ($key !== 'offset') { 390 | return ""; 391 | } 392 | return $value; 393 | } 394 | 395 | protected function processFunction($parsed) { 396 | if (($parsed['expr_type'] !== \PHPSQL\Expression\Type::AGGREGATE_FUNCTION) 397 | && ($parsed['expr_type'] !== \PHPSQL\Expression\Type::SIMPLE_FUNCTION)) { 398 | return ""; 399 | } 400 | 401 | if ($parsed['sub_tree'] === false) { 402 | return $parsed['base_expr'] . "()"; 403 | } 404 | 405 | $sql = ""; 406 | foreach ($parsed['sub_tree'] as $k => $v) { 407 | $len = strlen($sql); 408 | $sql .= $this->processFunction($v); 409 | $sql .= $this->processConstant($v); 410 | $sql .= $this->processColRef($v); 411 | $sql .= $this->processReserved($v); 412 | 413 | if ($len == strlen($sql)) { 414 | throw new \PHPSQL\Exception\UnableToCreateSQL('function subtree', $k, $v, 'expr_type'); 415 | } 416 | 417 | $sql .= ($this->isReserved($v) ? " " : ","); 418 | } 419 | return $parsed['base_expr'] . "(" . substr($sql, 0, -1) . ")"; 420 | } 421 | 422 | protected function processSelectExpression($parsed) { 423 | if ($parsed['expr_type'] !== \PHPSQL\Expression\Type::EXPRESSION) { 424 | return ""; 425 | } 426 | $sql = $this->processSubTree($parsed, " "); 427 | $sql .= $this->processAlias($parsed['alias']); 428 | return $sql; 429 | } 430 | 431 | protected function processSelectBracketExpression($parsed) { 432 | if ($parsed['expr_type'] !== \PHPSQL\Expression\Type::BRACKET_EXPRESSION) { 433 | return ""; 434 | } 435 | $sql = $this->processSubTree($parsed, " "); 436 | $sql = "(" . $sql . ")"; 437 | return $sql; 438 | } 439 | 440 | protected function processSubTree($parsed, $delim = " ") { 441 | if ($parsed['sub_tree'] === '') { 442 | return ""; 443 | } 444 | $sql = ""; 445 | foreach ($parsed['sub_tree'] as $k => $v) { 446 | $len = strlen($sql); 447 | $sql .= $this->processFunction($v); 448 | $sql .= $this->processOperator($v); 449 | $sql .= $this->processConstant($v); 450 | $sql .= $this->processSubQuery($v); 451 | $sql .= $this->processSelectBracketExpression($v); 452 | 453 | if ($len == strlen($sql)) { 454 | throw new \PHPSQL\Exception\UnableToCreateSQL('expression subtree', $k, $v, 'expr_type'); 455 | } 456 | 457 | $sql .= $delim; 458 | } 459 | return substr($sql, 0, -1); 460 | } 461 | 462 | protected function processRefClause($parsed) { 463 | if ($parsed === false) { 464 | return ""; 465 | } 466 | 467 | $sql = ""; 468 | foreach ($parsed as $k => $v) { 469 | $len = strlen($sql); 470 | $sql .= $this->processColRef($v); 471 | $sql .= $this->processOperator($v); 472 | $sql .= $this->processConstant($v); 473 | 474 | if ($len == strlen($sql)) { 475 | throw new \PHPSQL\Exception\UnableToCreateSQL('expression ref_clause', $k, $v, 'expr_type'); 476 | } 477 | 478 | $sql .= " "; 479 | } 480 | return "(" . substr($sql, 0, -1) . ")"; 481 | } 482 | 483 | protected function processAlias($parsed) { 484 | if ($parsed === false) { 485 | return ""; 486 | } 487 | $sql = ""; 488 | if ($parsed['as']) { 489 | $sql .= " as"; 490 | } 491 | $sql .= " " . $parsed['name']; 492 | return $sql; 493 | } 494 | 495 | protected function processJoin($parsed) { 496 | if ($parsed === 'CROSS') { 497 | return ","; 498 | } 499 | if ($parsed === 'JOIN') { 500 | return "INNER JOIN"; 501 | } 502 | if ($parsed === 'LEFT') { 503 | return "LEFT JOIN"; 504 | } 505 | if ($parsed === 'RIGHT') { 506 | return "RIGHT JOIN"; 507 | } 508 | // TODO: add more 509 | throw new \PHPSQL\Exception\UnsupportedFeature($parsed); 510 | } 511 | 512 | protected function processRefType($parsed) { 513 | if ($parsed === false) { 514 | return ""; 515 | } 516 | if ($parsed === 'ON') { 517 | return " ON "; 518 | } 519 | if ($parsed === 'USING') { 520 | return " USING "; 521 | } 522 | // TODO: add more 523 | throw new \PHPSQL\Exception\UnsupportedFeature($parsed); 524 | } 525 | 526 | protected function processTable($parsed, $index) { 527 | if ($parsed['expr_type'] !== \PHPSQL\Expression\Type::TABLE) { 528 | return ""; 529 | } 530 | 531 | $sql = $parsed['table']; 532 | $sql .= $this->processAlias($parsed['alias']); 533 | 534 | if ($index !== 0) { 535 | $sql = $this->processJoin($parsed['join_type']) . " " . $sql; 536 | $sql .= $this->processRefType($parsed['ref_type']); 537 | $sql .= $this->processRefClause($parsed['ref_clause']); 538 | } 539 | return $sql; 540 | } 541 | 542 | protected function processTableExpression($parsed, $index) { 543 | if ($parsed['expr_type'] !== \PHPSQL\Expression\Type::TABLE_EXPRESSION) { 544 | return ""; 545 | } 546 | $sql = substr($this->processFROM($parsed['sub_tree']), 5); // remove FROM keyword 547 | $sql = "(" . $sql . ")"; 548 | $sql .= $this->processAlias($parsed['alias']); 549 | 550 | if ($index !== 0) { 551 | $sql = $this->processJoin($parsed['join_type']) . " " . $sql; 552 | $sql .= $this->processRefType($parsed['ref_type']); 553 | $sql .= $this->processRefClause($parsed['ref_clause']); 554 | } 555 | return $sql; 556 | } 557 | 558 | protected function processSubQuery($parsed, $index = 0) { 559 | if ($parsed['expr_type'] !== \PHPSQL\Expression\Type::SUBQUERY) { 560 | return ""; 561 | } 562 | 563 | $sql = $this->processSelectStatement($parsed['sub_tree']); 564 | $sql = "(" . $sql . ")"; 565 | 566 | if (isset($parsed['alias'])) { 567 | $sql .= $this->processAlias($parsed['alias']); 568 | } 569 | 570 | if ($index !== 0) { 571 | $sql = $this->processJoin($parsed['join_type']) . " " . $sql; 572 | $sql .= $this->processRefType($parsed['ref_type']); 573 | $sql .= $this->processRefClause($parsed['ref_clause']); 574 | } 575 | return $sql; 576 | } 577 | 578 | protected function processOperator($parsed) { 579 | if ($parsed['expr_type'] !== \PHPSQL\Expression\Type::OPERATOR) { 580 | return ""; 581 | } 582 | return $parsed['base_expr']; 583 | } 584 | 585 | protected function processColRef($parsed) { 586 | if ($parsed['expr_type'] !== \PHPSQL\Expression\Type::COLREF) { 587 | return ""; 588 | } 589 | $sql = $parsed['base_expr']; 590 | if (isset($parsed['alias'])) { 591 | $sql .= $this->processAlias($parsed['alias']); 592 | } 593 | if (isset($parsed['direction'])) { 594 | $sql .= $this->processDirection($parsed['direction']); 595 | } 596 | return $sql; 597 | } 598 | 599 | protected function processDirection($parsed) { 600 | $sql = ($parsed ? " " . $parsed : ""); 601 | return $sql; 602 | } 603 | 604 | protected function processReserved($parsed) { 605 | if (!$this->isReserved($parsed)) { 606 | return ""; 607 | } 608 | return $parsed['base_expr']; 609 | } 610 | 611 | protected function isReserved($parsed) { 612 | return ($parsed['expr_type'] === \PHPSQL\Expression\Type::RESERVED); 613 | } 614 | 615 | protected function processConstant($parsed) { 616 | if ($parsed['expr_type'] !== \PHPSQL\Expression\Type::CONSTANT) { 617 | return ""; 618 | } 619 | return $parsed['base_expr']; 620 | } 621 | 622 | protected function processInList($parsed) { 623 | if ($parsed['expr_type'] !== \PHPSQL\Expression\Type::IN_LIST) { 624 | return ""; 625 | } 626 | $sql = $this->processSubTree($parsed, ","); 627 | return "(" . $sql . ")"; 628 | } 629 | 630 | } 631 | -------------------------------------------------------------------------------- /vendor/soundintheory/php-sql-parser/src/PHPSQL/Exception/Exception.php: -------------------------------------------------------------------------------- 1 | 7 | * with contributions by Dan Vande More 8 | * 9 | * All rights reserved. 10 | * 11 | * Redistribution and use in source and binary forms, with or without modification, 12 | * are permitted provided that the following conditions are met: 13 | * 14 | * * Redistributions of source code must retain the above copyright notice, 15 | * this list of conditions and the following disclaimer. 16 | * * Redistributions in binary form must reproduce the above copyright notice, 17 | * this list of conditions and the following disclaimer in the documentation 18 | * and/or other materials provided with the distribution. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 21 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 22 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 23 | * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 24 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 25 | * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 26 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 28 | * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 29 | * DAMAGE. 30 | */ 31 | 32 | namespace PHPSQL\Exception; 33 | 34 | class InvalidParameter extends \InvalidArgumentException { 35 | 36 | protected $argument; 37 | 38 | public function __construct($argument) { 39 | $this->argument = $argument; 40 | parent::__construct("no SQL string to parse: \n" . $argument, 10); 41 | } 42 | 43 | public function getArgument() { 44 | return $this->argument; 45 | } 46 | } -------------------------------------------------------------------------------- /vendor/soundintheory/php-sql-parser/src/PHPSQL/Exception/UnableToCalculatePosition.php: -------------------------------------------------------------------------------- 1 | 7 | * with contributions by Dan Vande More 8 | * 9 | * All rights reserved. 10 | * 11 | * Redistribution and use in source and binary forms, with or without modification, 12 | * are permitted provided that the following conditions are met: 13 | * 14 | * * Redistributions of source code must retain the above copyright notice, 15 | * this list of conditions and the following disclaimer. 16 | * * Redistributions in binary form must reproduce the above copyright notice, 17 | * this list of conditions and the following disclaimer in the documentation 18 | * and/or other materials provided with the distribution. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 21 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 22 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 23 | * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 24 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 25 | * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 26 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 28 | * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 29 | * DAMAGE. 30 | */ 31 | 32 | namespace PHPSQL\Exception; 33 | 34 | class UnableToCalculatePosition extends \PHPSQL\Exception\Exception { 35 | 36 | protected $needle; 37 | protected $haystack; 38 | 39 | public function __construct($needle, $haystack) { 40 | $this->needle = $needle; 41 | $this->haystack = $haystack; 42 | parent::__construct("cannot calculate position of " . $needle . " within " . $haystack, 5); 43 | } 44 | 45 | public function getNeedle() { 46 | return $this->needle; 47 | } 48 | 49 | public function getHaystack() { 50 | return $this->haystack; 51 | } 52 | } -------------------------------------------------------------------------------- /vendor/soundintheory/php-sql-parser/src/PHPSQL/Exception/UnableToCreateSQL.php: -------------------------------------------------------------------------------- 1 | 7 | * with contributions by Dan Vande More 8 | * 9 | * All rights reserved. 10 | * 11 | * Redistribution and use in source and binary forms, with or without modification, 12 | * are permitted provided that the following conditions are met: 13 | * 14 | * * Redistributions of source code must retain the above copyright notice, 15 | * this list of conditions and the following disclaimer. 16 | * * Redistributions in binary form must reproduce the above copyright notice, 17 | * this list of conditions and the following disclaimer in the documentation 18 | * and/or other materials provided with the distribution. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 21 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 22 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 23 | * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 24 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 25 | * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 26 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 28 | * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 29 | * DAMAGE. 30 | */ 31 | 32 | namespace PHPSQL\Exception; 33 | 34 | class UnableToCreateSQL extends \PHPSQL\Exception\Exception { 35 | 36 | protected $part; 37 | protected $partkey; 38 | protected $entry; 39 | protected $entrykey; 40 | 41 | public function __construct($part, $partkey, $entry, $entrykey) { 42 | $this->part = $part; 43 | $this->partkey = $partkey; 44 | $this->entry = $entry; 45 | $this->entrykey = $entrykey; 46 | parent::__construct("unknown " . $entrykey . " in " . $part . "[" . $partkey . "] " . $entry[$entrykey], 15); 47 | } 48 | 49 | public function getEntry() { 50 | return $this->entry; 51 | } 52 | 53 | public function getEntryKey() { 54 | return $this->entrykey; 55 | } 56 | 57 | public function getSQLPart() { 58 | return $this->part; 59 | } 60 | 61 | public function getSQLPartKey() { 62 | return $this->partkey; 63 | } 64 | } -------------------------------------------------------------------------------- /vendor/soundintheory/php-sql-parser/src/PHPSQL/Exception/UnsupportedFeature.php: -------------------------------------------------------------------------------- 1 | 7 | * with contributions by Dan Vande More 8 | * 9 | * All rights reserved. 10 | * 11 | * Redistribution and use in source and binary forms, with or without modification, 12 | * are permitted provided that the following conditions are met: 13 | * 14 | * * Redistributions of source code must retain the above copyright notice, 15 | * this list of conditions and the following disclaimer. 16 | * * Redistributions in binary form must reproduce the above copyright notice, 17 | * this list of conditions and the following disclaimer in the documentation 18 | * and/or other materials provided with the distribution. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 21 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 22 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 23 | * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 24 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 25 | * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 26 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 28 | * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 29 | * DAMAGE. 30 | */ 31 | 32 | namespace PHPSQL\Exception; 33 | 34 | class UnsupportedFeature extends \PHPSQL\Exception\Exception { 35 | 36 | protected $key; 37 | 38 | public function __construct($key) { 39 | $this->key = $key; 40 | parent::__construct($key . " not implemented.", 20); 41 | } 42 | 43 | public function getKey() { 44 | return $this->key; 45 | } 46 | } -------------------------------------------------------------------------------- /vendor/soundintheory/php-sql-parser/src/PHPSQL/Expression/Token.php: -------------------------------------------------------------------------------- 1 | 10 | * with contributions by Dan Vande More 11 | * 12 | * All rights reserved. 13 | * 14 | * Redistribution and use in source and binary forms, with or without modification, 15 | * are permitted provided that the following conditions are met: 16 | * 17 | * * Redistributions of source code must retain the above copyright notice, 18 | * this list of conditions and the following disclaimer. 19 | * * Redistributions in binary form must reproduce the above copyright notice, 20 | * this list of conditions and the following disclaimer in the documentation 21 | * and/or other materials provided with the distribution. 22 | * 23 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 24 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 25 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 26 | * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 27 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 28 | * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 29 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 30 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 31 | * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 32 | * DAMAGE. 33 | */ 34 | 35 | namespace PHPSQL\Expression; 36 | 37 | class Token { 38 | 39 | private $subTree; 40 | private $expression; 41 | private $key; 42 | private $token; 43 | private $tokenType; 44 | private $trim; 45 | private $upper; 46 | 47 | public function __construct($key = "", $token = "") { 48 | $this->subTree = false; 49 | $this->expression = ""; 50 | $this->key = $key; 51 | $this->token = $token; 52 | $this->tokenType = false; 53 | $this->trim = trim($token); 54 | $this->upper = strtoupper($this->trim); 55 | } 56 | 57 | # TODO: we could replace it with a constructor new \PHPSQL\Expression\Token(this, "*") 58 | public function addToken($string) { 59 | $this->token .= $string; 60 | } 61 | 62 | public function isEnclosedWithinParenthesis() { 63 | return ($this->upper[0] === '(' && substr($this->upper, -1) === ')'); 64 | } 65 | 66 | public function setSubTree($tree) { 67 | $this->subTree = $tree; 68 | } 69 | 70 | public function getSubTree() { 71 | return $this->subTree; 72 | } 73 | 74 | public function getUpper($idx = false) { 75 | return $idx !== false ? $this->upper[$idx] : $this->upper; 76 | } 77 | 78 | public function getTrim($idx = false) { 79 | return $idx !== false ? $this->trim[$idx] : $this->trim; 80 | } 81 | 82 | public function getToken($idx = false) { 83 | return $idx !== false ? $this->token[$idx] : $this->token; 84 | } 85 | 86 | public function setTokenType($type) { 87 | $this->tokenType = $type; 88 | } 89 | 90 | public function endsWith($needle) { 91 | $length = strlen($needle); 92 | if ($length == 0) { 93 | return true; 94 | } 95 | 96 | $start = $length * -1; 97 | return (substr($this->token, $start) === $needle); 98 | } 99 | 100 | public function isWhitespaceToken() { 101 | return ($this->trim === ""); 102 | } 103 | 104 | public function isCommaToken() { 105 | return ($this->trim === ","); 106 | } 107 | 108 | public function isVariableToken() { 109 | return $this->upper[0] === '@'; 110 | } 111 | 112 | public function isSubQueryToken() { 113 | return preg_match("/^\\(\\s*SELECT/i", $this->trim); 114 | } 115 | 116 | public function isExpression() { 117 | return $this->tokenType === \PHPSQL\Expression\Type::EXPRESSION; 118 | } 119 | 120 | public function isBracketExpression() { 121 | return $this->tokenType === \PHPSQL\Expression\Type::BRACKET_EXPRESSION; 122 | } 123 | 124 | public function isOperator() { 125 | return $this->tokenType === \PHPSQL\Expression\Type::OPERATOR; 126 | } 127 | 128 | public function isInList() { 129 | return $this->tokenType === \PHPSQL\Expression\Type::IN_LIST; 130 | } 131 | 132 | public function isFunction() { 133 | return $this->tokenType === \PHPSQL\Expression\Type::SIMPLE_FUNCTION; 134 | } 135 | 136 | public function isUnspecified() { 137 | return ($this->tokenType === false); 138 | } 139 | 140 | public function isAggregateFunction() { 141 | return $this->tokenType === \PHPSQL\Expression\Type::AGGREGATE_FUNCTION; 142 | } 143 | 144 | public function isColumnReference() { 145 | return $this->tokenType === \PHPSQL\Expression\Type::COLREF; 146 | } 147 | 148 | public function isConstant() { 149 | return $this->tokenType === \PHPSQL\Expression\Type::CONSTANT; 150 | } 151 | 152 | public function isSign() { 153 | return $this->tokenType === \PHPSQL\Expression\Type::SIGN; 154 | } 155 | 156 | public function isSubQuery() { 157 | return $this->tokenType === \PHPSQL\Expression\Type::SUBQUERY; 158 | } 159 | 160 | public function toArray() { 161 | return array('expr_type' => $this->tokenType, 'base_expr' => $this->token, 'sub_tree' => $this->subTree); 162 | } 163 | } 164 | -------------------------------------------------------------------------------- /vendor/soundintheory/php-sql-parser/src/PHPSQL/Expression/Type.php: -------------------------------------------------------------------------------- 1 | 10 | * with contributions by Dan Vande More 11 | * 12 | * All rights reserved. 13 | * 14 | * Redistribution and use in source and binary forms, with or without modification, 15 | * are permitted provided that the following conditions are met: 16 | * 17 | * * Redistributions of source code must retain the above copyright notice, 18 | * this list of conditions and the following disclaimer. 19 | * * Redistributions in binary form must reproduce the above copyright notice, 20 | * this list of conditions and the following disclaimer in the documentation 21 | * and/or other materials provided with the distribution. 22 | * 23 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 24 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 25 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 26 | * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 27 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 28 | * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 29 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 30 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 31 | * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 32 | * DAMAGE. 33 | */ 34 | 35 | namespace PHPSQL\Expression; 36 | 37 | class Type { 38 | 39 | const USER_VARIABLE = "user_variable"; 40 | const SESSION_VARIABLE = "session_variable"; 41 | const GLOBAL_VARIABLE = "global_variable"; 42 | const LOCAL_VARIABLE = "local_variable"; 43 | 44 | const COLREF = "colref"; 45 | const RESERVED = "reserved"; 46 | const CONSTANT = "const"; 47 | 48 | const AGGREGATE_FUNCTION = "aggregate_function"; 49 | const SIMPLE_FUNCTION = "function"; 50 | 51 | const EXPRESSION = "expression"; 52 | const BRACKET_EXPRESSION = "bracket_expression"; 53 | const TABLE_EXPRESSION = "table_expression"; 54 | 55 | const SUBQUERY = "subquery"; 56 | const IN_LIST = "in-list"; 57 | const OPERATOR = "operator"; 58 | const SIGN = "sign"; 59 | const RECORD = "record"; 60 | 61 | const MATCH_ARGUMENTS = "match-arguments"; 62 | const MATCH_MODE = "match-mode"; 63 | 64 | const ALIAS = "alias"; 65 | const POSITION = "pos"; 66 | 67 | const TEMPORARY_TABLE = "temporary_table"; 68 | const TABLE = "table"; 69 | const VIEW = "view"; 70 | const DATABASE = "database"; 71 | const SCHEMA = "schema"; 72 | } 73 | -------------------------------------------------------------------------------- /vendor/soundintheory/php-sql-parser/src/PHPSQL/Parser/Constants.php: -------------------------------------------------------------------------------- 1 | 9 | * with contributions by Dan Vande More 10 | * 11 | * All rights reserved. 12 | * 13 | * Redistribution and use in source and binary forms, with or without modification, 14 | * are permitted provided that the following conditions are met: 15 | * 16 | * * Redistributions of source code must retain the above copyright notice, 17 | * this list of conditions and the following disclaimer. 18 | * * Redistributions in binary form must reproduce the above copyright notice, 19 | * this list of conditions and the following disclaimer in the documentation 20 | * and/or other materials provided with the distribution. 21 | * 22 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 23 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 24 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 25 | * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 26 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 27 | * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 28 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 29 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 30 | * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 31 | * DAMAGE. 32 | */ 33 | 34 | namespace PHPSQL\Parser; 35 | 36 | class Constants { 37 | 38 | protected static $reserved = array('ABS', 'ACOS', 'ADDDATE', 'ADDTIME', 'AES_ENCRYPT', 'AES_DECRYPT', 'AGAINST', 39 | 'ASCII', 'ASIN', 'ATAN', 'AVG', 'BENCHMARK', 'BIN', 'BIT_AND', 'BIT_OR', 40 | 'BITCOUNT', 'BITLENGTH', 'CAST', 'CEILING', 'CHAR', 'CHAR_LENGTH', 41 | 'CHARACTER_LENGTH', 'CHARSET', 'COALESCE', 'COERCIBILITY', 'COLLATION', 42 | 'COMPRESS', 'CONCAT', 'CONCAT_WS', 'CONNECTION_ID', 'CONV', 'CONVERT', 43 | 'CONVERT_TZ', 'COS', 'COT', 'COUNT', 'CRC32', 'CURDATE', 'CURRENT_USER', 44 | 'CURRVAL', 'CURTIME', 'DATABASE', 'DATETIME', 'DATE_ADD', 'DATE_DIFF', 45 | 'DATE_FORMAT', 'DATE_SUB', 'DAY', 'DAYNAME', 'DAYOFMONTH', 'DAYOFWEEK', 46 | 'DAYOFYEAR', 'DECODE', 'DEFAULT', 'DEGREES', 'DES_DECRYPT', 'DES_ENCRYPT', 47 | 'ELT', 'ENCODE', 'ENCRYPT', 'EXP', 'EXPORT_SET', 'EXTRACT', 'FIELD', 48 | 'FIND_IN_SET', 'FLOOR', 'FORMAT', 'FOUND_ROWS', 'FROM_DAYS', 'FROM_UNIXTIME', 49 | 'GET_FORMAT', 'GET_LOCK', 'GROUP_CONCAT', 'GREATEST', 'HEX', 'HOUR', 'IF', 50 | 'IFNULL', 'IN', 'INET_ATON', 'INET_NTOA', 'INSERT', 'INSTR', 'INTERVAL', 51 | 'IS_FREE_LOCK', 'IS_USED_LOCK', 'LAST_DAY', 'LAST_INSERT_ID', 'LCASE', 'LEAST', 52 | 'LEFT', 'LENGTH', 'LN', 'LOAD_FILE', 'LOCALTIME', 'LOCALTIMESTAMP', 'LOCATE', 53 | 'LOG', 'LOG2', 'LOG10', 'LOWER', 'LPAD', 'LTRIM', 'MAKE_SET', 'MAKEDATE', 54 | 'MAKETIME', 'MASTER_POS_WAIT', 'MATCH', 'MAX', 'MD5', 'MICROSECOND', 'MID', 55 | 'MIN', 'MINUTE', 'MOD', 'MONTH', 'MONTHNAME', 'NEXTVAL', 'NOW', 'NULLIF', 'OCT', 56 | 'OCTET_LENGTH', 'OLD_PASSWORD', 'ORD', 'PASSWORD', 'PERIOD_ADD', 'PERIOD_DIFF', 57 | 'PI', 'POSITION', 'POW', 'POWER', 'QUARTER', 'QUOTE', 'RADIANS', 'RAND', 58 | 'RELEASE_LOCK', 'REPEAT', 'REPLACE', 'REVERSE', 'RIGHT', 'ROUND', 'ROW_COUNT', 59 | 'RPAD', 'RTRIM', 'SEC_TO_TIME', 'SECOND', 'SESSION_USER', 'SHA', 'SHA1', 'SIGN', 60 | 'SOUNDEX', 'SPACE', 'SQRT', 'STD', 'STDDEV', 'STDDEV_POP', 'STDDEV_SAMP', 61 | 'STRCMP', 'STR_TO_DATE', 'SUBDATE', 'SUBSTRING', 'SUBSTRING_INDEX', 'SUBTIME', 62 | 'SUM', 'SYSDATE', 'SYSTEM_USER', 'TAN', 'TIME', 'TIMEDIFF', 'TIMESTAMP', 63 | 'TIMESTAMPADD', 'TIMESTAMPDIFF', 'TIME_FORMAT', 'TIME_TO_SEC', 'TO_DAYS', 64 | 'TRIM', 'TRUNCATE', 'UCASE', 'UNCOMPRESS', 'UNCOMPRESSED_LENGTH', 'UNHEX', 65 | 'UNIX_TIMESTAMP', 'UPPER', 'USER', 'UTC_DATE', 'UTC_TIME', 'UTC_TIMESTAMP', 66 | 'UUID', 'VAR_POP', 'VAR_SAMP', 'VARIANCE', 'VERSION', 'WEEK', 'WEEKDAY', 67 | 'WEEKOFYEAR', 'YEAR', 'YEARWEEK', 'ADD', 'ALL', 'ALTER', 'ANALYZE', 'AND', 'AS', 68 | 'ASC', 'ASENSITIVE', 'AUTO_INCREMENT', 'BDB', 'BEFORE', 'BERKELEYDB', 'BETWEEN', 69 | 'BIGINT', 'BINARY', 'BLOB', 'BOTH', 'BY', 'CALL', 'CASCADE', 'CASE', 'CHANGE', 70 | 'CHAR', 'CHARACTER', 'CHECK', 'COLLATE', 'COLUMN', 'COLUMNS', 'CONDITION', 71 | 'CONNECTION', 'CONSTRAINT', 'CONTINUE', 'CREATE', 'CROSS', 'CURRENT_DATE', 72 | 'CURRENT_TIME', 'CURRENT_TIMESTAMP', 'CURSOR', 'DATABASE', 'DATABASES', 73 | 'DAY_HOUR', 'DAY_MICROSECOND', 'DAY_MINUTE', 'DAY_SECOND', 'DEC', 'DECIMAL', 74 | 'DECLARE', 'DEFAULT', 'DELAYED', 'DELETE', 'DESC', 'DESCRIBE', 'DETERMINISTIC', 75 | 'DISTINCT', 'DISTINCTROW', 'DIV', 'DOUBLE', 'DROP', 'ELSE', 'ELSEIF', 'END', 76 | 'ENCLOSED', 'ESCAPED', 'EXISTS', 'EXIT', 'EXPLAIN', 'FALSE', 'FETCH', 'FIELDS', 77 | 'FLOAT', 'FOR', 'FORCE', 'FOREIGN', 'FOUND', 'FRAC_SECOND', 'FROM', 'FULLTEXT', 78 | 'GRANT', 'GROUP', 'HAVING', 'HIGH_PRIORITY', 'HOUR_MICROSECOND', 'HOUR_MINUTE', 79 | 'HOUR_SECOND', 'IF', 'IGNORE', 'IN', 'INDEX', 'INFILE', 'INNER', 'INNODB', 80 | 'INOUT', 'INSENSITIVE', 'INSERT', 'INT', 'INTEGER', 'INTERVAL', 'INTO', 81 | 'IO_THREAD', 'IS', 'ITERATE', 'JOIN', 'KEY', 'KEYS', 'KILL', 'LEADING', 'LEAVE', 82 | 'LEFT', 'LIKE', 'LIMIT', 'LINES', 'LOAD', 'LOCALTIME', 'LOCALTIMESTAMP', 'LOCK', 83 | 'LONG', 'LONGBLOB', 'LONGTEXT', 'LOOP', 'LOW_PRIORITY', 'MASTER_SERVER_ID', 84 | 'MATCH', 'MEDIUMBLOB', 'MEDIUMINT', 'MEDIUMTEXT', 'MIDDLEINT', 85 | 'MINUTE_MICROSECOND', 'MINUTE_SECOND', 'MOD', 'NATURAL', 'NOT', 86 | 'NO_WRITE_TO_BINLOG', 'NULL', 'NUMERIC', 'ON', 'OPTIMIZE', 'OPTION', 87 | 'OPTIONALLY', 'OR', 'ORDER', 'OUT', 'OUTER', 'OUTFILE', 'PRECISION', 'PRIMARY', 88 | 'PRIVILEGES', 'PROCEDURE', 'PURGE', 'READ', 'REAL', 'REFERENCES', 'REGEXP', 89 | 'RENAME', 'REPEAT', 'REPLACE', 'REQUIRE', 'RESTRICT', 'RETURN', 'REVOKE', 90 | 'RIGHT', 'RLIKE', 'SECOND_MICROSECOND', 'SELECT', 'SENSITIVE', 'SEPARATOR', 91 | 'SET', 'SHOW', 'SMALLINT', 'SOME', 'SONAME', 'SPATIAL', 'SPECIFIC', 'SQL', 92 | 'SQLEXCEPTION', 'SQLSTATE', 'SQLWARNING', 'SQL_BIG_RESULT', 93 | 'SQL_CALC_FOUND_ROWS', 'SQL_SMALL_RESULT', 'SQL_TSI_DAY', 'SQL_TSI_FRAC_SECOND', 94 | 'SQL_TSI_HOUR', 'SQL_TSI_MINUTE', 'SQL_TSI_MONTH', 'SQL_TSI_QUARTER', 95 | 'SQL_TSI_SECOND', 'SQL_TSI_WEEK', 'SQL_TSI_YEAR', 'SSL', 'STARTING', 96 | 'STRAIGHT_JOIN', 'STRIPED', 'TABLE', 'TABLES', 'TERMINATED', 'THEN', 97 | 'TIMESTAMPADD', 'TIMESTAMPDIFF', 'TINYBLOB', 'TINYINT', 'TINYTEXT', 'TO', 98 | 'TRAILING', 'TRUE', 'UNDO', 'UNION', 'UNIQUE', 'UNLOCK', 'UNSIGNED', 'UPDATE', 99 | 'USAGE', 'USE', 'USER_RESOURCES', 'USING', 'UTC_DATE', 'UTC_TIME', 100 | 'UTC_TIMESTAMP', 'VALUES', 'VARBINARY', 'VARCHAR', 'VARCHARACTER', 'VARYING', 101 | 'WHEN', 'WHERE', 'WHILE', 'WITH', 'WRITE', 'XOR', 'YEAR_MONTH', 'ZEROFILL'); 102 | 103 | protected static $parameterizedFunctions = array('ABS', 'ACOS', 'ADDDATE', 'ADDTIME', 'AES_ENCRYPT', 'AES_DECRYPT', 104 | 'AGAINST', 'ASCII', 'ASIN', 'ATAN', 'AVG', 'BENCHMARK', 'BIN', 105 | 'BIT_AND', 'BIT_OR', 'BITCOUNT', 'BITLENGTH', 'CAST', 'CEILING', 106 | 'CHAR', 'CHAR_LENGTH', 'CHARACTER_LENGTH', 'CHARSET', 'COALESCE', 107 | 'COERCIBILITY', 'COLLATION', 'COMPRESS', 'CONCAT', 'CONCAT_WS', 108 | 'CONV', 'CONVERT', 'CONVERT_TZ', 'COS', 'COT', 'COUNT', 'CRC32', 109 | 'CURRVAL', 'DATE_ADD', 'DATE_DIFF', 'DATE_FORMAT', 'DATE_SUB', 110 | 'DAY', 'DAYNAME', 'DAYOFMONTH', 'DAYOFWEEK', 'DAYOFYEAR', 111 | 'DECODE', 'DEFAULT', 'DEGREES', 'DES_DECRYPT', 'DES_ENCRYPT', 112 | 'ELT', 'ENCODE', 'ENCRYPT', 'EXP', 'EXPORT_SET', 'EXTRACT', 113 | 'FIELD', 'FIND_IN_SET', 'FLOOR', 'FORMAT', 'FROM_DAYS', 114 | 'FROM_UNIXTIME', 'GET_FORMAT', 'GET_LOCK', 'GROUP_CONCAT', 115 | 'GREATEST', 'HEX', 'HOUR', 'IF', 'IFNULL', 'IN', 'INET_ATON', 116 | 'INET_NTOA', 'INSERT', 'INSTR', 'INTERVAL', 'IS_FREE_LOCK', 117 | 'IS_USED_LOCK', 'LAST_DAY', 'LCASE', 'LEAST', 'LEFT', 'LENGTH', 118 | 'LN', 'LOAD_FILE', 'LOCATE', 'LOG', 'LOG2', 'LOG10', 'LOWER', 119 | 'LPAD', 'LTRIM', 'MAKE_SET', 'MAKEDATE', 'MAKETIME', 120 | 'MASTER_POS_WAIT', 'MATCH', 'MAX', 'MD5', 'MICROSECOND', 'MID', 121 | 'MIN', 'MINUTE', 'MOD', 'MONTH', 'MONTHNAME', 'NEXTVAL', 'NULLIF', 122 | 'OCT', 'OCTET_LENGTH', 'OLD_PASSWORD', 'ORD', 'PASSWORD', 123 | 'PERIOD_ADD', 'PERIOD_DIFF', 'PI', 'POSITION', 'POW', 'POWER', 124 | 'QUARTER', 'QUOTE', 'RADIANS', 'RELEASE_LOCK', 'REPEAT', 125 | 'REPLACE', 'REVERSE', 'RIGHT', 'ROUND', 'RPAD', 'RTRIM', 126 | 'SEC_TO_TIME', 'SECOND', 'SHA', 'SHA1', 'SIGN', 'SOUNDEX', 127 | 'SPACE', 'SQRT', 'STD', 'STDDEV', 'STDDEV_POP', 'STDDEV_SAMP', 128 | 'STRCMP', 'STR_TO_DATE', 'SUBDATE', 'SUBSTRING', 129 | 'SUBSTRING_INDEX', 'SUBTIME', 'SUM', 'TAN', 'TIME', 'TIMEDIFF', 130 | 'TIMESTAMP', 'TIMESTAMPADD', 'TIMESTAMPDIFF', 'TIME_FORMAT', 131 | 'TIME_TO_SEC', 'TO_DAYS', 'TRIM', 'TRUNCATE', 'UCASE', 132 | 'UNCOMPRESS', 'UNCOMPRESSED_LENGTH', 'UNHEX', 'UPPER', 'VAR_POP', 133 | 'VAR_SAMP', 'VARIANCE', 'WEEK', 'WEEKDAY', 'WEEKOFYEAR', 'YEAR', 134 | 'YEARWEEK'); 135 | 136 | protected static $functions = array('ABS', 'ACOS', 'ADDDATE', 'ADDTIME', 'AES_ENCRYPT', 'AES_DECRYPT', 'AGAINST', 137 | 'ASCII', 'ASIN', 'ATAN', 'AVG', 'BENCHMARK', 'BIN', 'BIT_AND', 'BIT_OR', 138 | 'BITCOUNT', 'BITLENGTH', 'CAST', 'CEILING', 'CHAR', 'CHAR_LENGTH', 139 | 'CHARACTER_LENGTH', 'CHARSET', 'COALESCE', 'COERCIBILITY', 'COLLATION', 140 | 'COMPRESS', 'CONCAT', 'CONCAT_WS', 'CONNECTION_ID', 'CONV', 'CONVERT', 141 | 'CONVERT_TZ', 'COS', 'COT', 'COUNT', 'CRC32', 'CURDATE', 'CURRENT_USER', 142 | 'CURRVAL', 'CURTIME', 'DATABASE', 'DATE_ADD', 'DATE_DIFF', 'DATE_FORMAT', 143 | 'DATE_SUB', 'DAY', 'DAYNAME', 'DAYOFMONTH', 'DAYOFWEEK', 'DAYOFYEAR', 'DECODE', 144 | 'DEFAULT', 'DEGREES', 'DES_DECRYPT', 'DES_ENCRYPT', 'ELT', 'ENCODE', 'ENCRYPT', 145 | 'EXP', 'EXPORT_SET', 'EXTRACT', 'FIELD', 'FIND_IN_SET', 'FLOOR', 'FORMAT', 146 | 'FOUND_ROWS', 'FROM_DAYS', 'FROM_UNIXTIME', 'GET_FORMAT', 'GET_LOCK', 147 | 'GROUP_CONCAT', 'GREATEST', 'HEX', 'HOUR', 'IF', 'IFNULL', 'IN', 'INET_ATON', 148 | 'INET_NTOA', 'INSERT', 'INSTR', 'INTERVAL', 'IS_FREE_LOCK', 'IS_USED_LOCK', 149 | 'LAST_DAY', 'LAST_INSERT_ID', 'LCASE', 'LEAST', 'LEFT', 'LENGTH', 'LN', 150 | 'LOAD_FILE', 'LOCALTIME', 'LOCALTIMESTAMP', 'LOCATE', 'LOG', 'LOG2', 'LOG10', 151 | 'LOWER', 'LPAD', 'LTRIM', 'MAKE_SET', 'MAKEDATE', 'MAKETIME', 152 | 'MASTER_POS_WAIT', 'MATCH', 'MAX', 'MD5', 'MICROSECOND', 'MID', 'MIN', 153 | 'MINUTE', 'MOD', 'MONTH', 'MONTHNAME', 'NEXTVAL', 'NOW', 'NULLIF', 'OCT', 154 | 'OCTET_LENGTH', 'OLD_PASSWORD', 'ORD', 'PASSWORD', 'PERIOD_ADD', 'PERIOD_DIFF', 155 | 'PI', 'POSITION', 'POW', 'POWER', 'QUARTER', 'QUOTE', 'RADIANS', 'RAND', 156 | 'RELEASE_LOCK', 'REPEAT', 'REPLACE', 'REVERSE', 'RIGHT', 'ROUND', 'ROW_COUNT', 157 | 'RPAD', 'RTRIM', 'SEC_TO_TIME', 'SECOND', 'SESSION_USER', 'SHA', 'SHA1', 158 | 'SIGN', 'SOUNDEX', 'SPACE', 'SQRT', 'STD', 'STDDEV', 'STDDEV_POP', 159 | 'STDDEV_SAMP', 'STRCMP', 'STR_TO_DATE', 'SUBDATE', 'SUBSTRING', 160 | 'SUBSTRING_INDEX', 'SUBTIME', 'SUM', 'SYSDATE', 'SYSTEM_USER', 'TAN', 'TIME', 161 | 'TIMEDIFF', 'TIMESTAMP', 'TIMESTAMPADD', 'TIMESTAMPDIFF', 'TIME_FORMAT', 162 | 'TIME_TO_SEC', 'TO_DAYS', 'TRIM', 'TRUNCATE', 'UCASE', 'UNCOMPRESS', 163 | 'UNCOMPRESSED_LENGTH', 'UNHEX', 'UNIX_TIMESTAMP', 'UPPER', 'USER', 'UTC_DATE', 164 | 'UTC_TIME', 'UTC_TIMESTAMP', 'UUID', 'VAR_POP', 'VAR_SAMP', 'VARIANCE', 165 | 'VERSION', 'WEEK', 'WEEKDAY', 'WEEKOFYEAR', 'YEAR', 'YEARWEEK'); 166 | 167 | protected static $aggregateFunctions = array('AVG', 'SUM', 'COUNT', 'MIN', 'MAX', 'STDDEV', 'STDDEV_SAMP', 168 | 'STDDEV_POP', 'VARIANCE', 'VAR_SAMP', 'VAR_POP', 'GROUP_CONCAT', 169 | 'BIT_AND', 'BIT_OR', 'BIT_XOR'); 170 | } 171 | -------------------------------------------------------------------------------- /vendor/soundintheory/php-sql-parser/src/PHPSQL/Parser/Lexer.php: -------------------------------------------------------------------------------- 1 | 9 | * with contributions by Dan Vande More 10 | * 11 | * All rights reserved. 12 | * 13 | * Redistribution and use in source and binary forms, with or without modification, 14 | * are permitted provided that the following conditions are met: 15 | * 16 | * * Redistributions of source code must retain the above copyright notice, 17 | * this list of conditions and the following disclaimer. 18 | * * Redistributions in binary form must reproduce the above copyright notice, 19 | * this list of conditions and the following disclaimer in the documentation 20 | * and/or other materials provided with the distribution. 21 | * 22 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 23 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 24 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 25 | * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 26 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 27 | * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 28 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 29 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 30 | * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 31 | * DAMAGE. 32 | */ 33 | 34 | namespace PHPSQL\Parser; 35 | 36 | /** 37 | * This class splits the SQL string into little parts, which the parser can 38 | * use to build the result array. 39 | * 40 | * @author arothe 41 | * 42 | */ 43 | class Lexer extends \PHPSQL\Parser\Utils { 44 | 45 | private $splitters; 46 | 47 | public function __construct() { 48 | $this->splitters = new \PHPSQL\Parser\Lexer\Splitter(); 49 | } 50 | 51 | public function split($sql) { 52 | if (!is_string($sql)) { 53 | throw new \PHPSQL\Exception\InvalidParameter($sql); 54 | } 55 | 56 | $tokens = array(); 57 | $token = ""; 58 | 59 | $splitLen = $this->splitters->getMaxLengthOfSplitter(); 60 | $found = false; 61 | $len = strlen($sql); 62 | $pos = 0; 63 | 64 | while ($pos < $len) { 65 | 66 | for ($i = $splitLen; $i > 0; $i--) { 67 | $substr = substr($sql, $pos, $i); 68 | if ($this->splitters->isSplitter($substr)) { 69 | 70 | if ($token !== "") { 71 | $tokens[] = $token; 72 | } 73 | 74 | $tokens[] = $substr; 75 | $pos += $i; 76 | $token = ""; 77 | 78 | continue 2; 79 | } 80 | } 81 | 82 | $token .= $sql[$pos]; 83 | $pos++; 84 | } 85 | 86 | if ($token !== "") { 87 | $tokens[] = $token; 88 | } 89 | 90 | $tokens = $this->concatEscapeSequences($tokens); 91 | $tokens = $this->balanceBackticks($tokens); 92 | $tokens = $this->concatColReferences($tokens); 93 | $tokens = $this->balanceParenthesis($tokens); 94 | $tokens = $this->balanceMultilineComments($tokens); 95 | $tokens = $this->concatInlineComments($tokens); 96 | $tokens = $this->concatUserDefinedVariables($tokens); 97 | return $tokens; 98 | } 99 | 100 | private function concatUserDefinedVariables($tokens) { 101 | $i = 0; 102 | $cnt = count($tokens); 103 | $userdef = false; 104 | 105 | while ($i < $cnt) { 106 | 107 | if (!isset($tokens[$i])) { 108 | $i++; 109 | continue; 110 | } 111 | 112 | $token = $tokens[$i]; 113 | 114 | if ($userdef !== false) { 115 | $tokens[$userdef] .= $token; 116 | unset($tokens[$i]); 117 | if ($token !== "@") { 118 | $userdef = false; 119 | } 120 | } 121 | 122 | if ($userdef === false && $token === "@") { 123 | $userdef = $i; 124 | } 125 | 126 | $i++; 127 | } 128 | 129 | return array_values($tokens); 130 | } 131 | 132 | private function concatInlineComments($tokens) { 133 | 134 | $i = 0; 135 | $cnt = count($tokens); 136 | $comment = false; 137 | 138 | while ($i < $cnt) { 139 | 140 | if (!isset($tokens[$i])) { 141 | $i++; 142 | continue; 143 | } 144 | 145 | $token = $tokens[$i]; 146 | 147 | if ($comment !== false) { 148 | if ($token === "\n" || $token === "\r\n") { 149 | $comment = false; 150 | } else { 151 | unset($tokens[$i]); 152 | $tokens[$comment] .= $token; 153 | } 154 | } 155 | 156 | if (($comment === false) && ($token === "-")) { 157 | if (isset($tokens[$i + 1]) && $tokens[$i + 1] === "-") { 158 | $comment = $i; 159 | $tokens[$i] = "--"; 160 | $i++; 161 | unset($tokens[$i]); 162 | continue; 163 | } 164 | } 165 | 166 | $i++; 167 | } 168 | 169 | return array_values($tokens); 170 | } 171 | 172 | private function balanceMultilineComments($tokens) { 173 | 174 | $i = 0; 175 | $cnt = count($tokens); 176 | $comment = false; 177 | 178 | while ($i < $cnt) { 179 | 180 | if (!isset($tokens[$i])) { 181 | $i++; 182 | continue; 183 | } 184 | 185 | $token = $tokens[$i]; 186 | 187 | if ($comment !== false) { 188 | unset($tokens[$i]); 189 | $tokens[$comment] .= $token; 190 | if ($token === "*" && isset($tokens[$i + 1]) && $tokens[$i + 1] === "/") { 191 | unset($tokens[$i + 1]); 192 | $tokens[$comment] .= "/"; 193 | $comment = false; 194 | } 195 | } 196 | 197 | if (($comment === false) && ($token === "/")) { 198 | if (isset($tokens[$i + 1]) && $tokens[$i + 1] === "*") { 199 | $comment = $i; 200 | $tokens[$i] = "/*"; 201 | $i++; 202 | unset($tokens[$i]); 203 | continue; 204 | } 205 | } 206 | 207 | $i++; 208 | } 209 | return array_values($tokens); 210 | } 211 | 212 | private function isBacktick($token) { 213 | return ($token === "'" || $token === "\"" || $token === "`"); 214 | } 215 | 216 | private function balanceBackticks($tokens) { 217 | $i = 0; 218 | $cnt = count($tokens); 219 | while ($i < $cnt) { 220 | 221 | if (!isset($tokens[$i])) { 222 | $i++; 223 | continue; 224 | } 225 | 226 | $token = $tokens[$i]; 227 | 228 | if ($this->isBacktick($token)) { 229 | $tokens = $this->balanceCharacter($tokens, $i, $token); 230 | } 231 | 232 | $i++; 233 | } 234 | 235 | return $tokens; 236 | } 237 | 238 | # backticks are not balanced within one token, so we have 239 | # to re-combine some tokens 240 | private function balanceCharacter($tokens, $idx, $char) { 241 | 242 | $token_count = count($tokens); 243 | $i = $idx + 1; 244 | while ($i < $token_count) { 245 | 246 | if (!isset($tokens[$i])) { 247 | $i++; 248 | continue; 249 | } 250 | 251 | $token = $tokens[$i]; 252 | $tokens[$idx] .= $token; 253 | unset($tokens[$i]); 254 | 255 | if ($token === $char) { 256 | break; 257 | } 258 | 259 | $i++; 260 | } 261 | return array_values($tokens); 262 | } 263 | 264 | /* 265 | * does the token ends with dot? 266 | * concat it with the next token 267 | * 268 | * does the token starts with a dot? 269 | * concat it with the previous token 270 | */ 271 | private function concatColReferences($tokens) { 272 | 273 | $cnt = count($tokens); 274 | $i = 0; 275 | while ($i < $cnt) { 276 | 277 | if (!isset($tokens[$i])) { 278 | $i++; 279 | continue; 280 | } 281 | 282 | if ($tokens[$i][0] === ".") { 283 | 284 | // concat the previous tokens, till the token has been changed 285 | $k = $i - 1; 286 | $len = strlen($tokens[$i]); 287 | while (($k >= 0) && ($len == strlen($tokens[$i]))) { 288 | if (!isset($tokens[$k])) { # FIXME: this can be wrong if we have schema . table . column 289 | $k--; 290 | continue; 291 | } 292 | $tokens[$i] = $tokens[$k] . $tokens[$i]; 293 | unset($tokens[$k]); 294 | $k--; 295 | } 296 | } 297 | 298 | if ($this->endsWith($tokens[$i], '.')) { 299 | 300 | // concat the next tokens, till the token has been changed 301 | $k = $i + 1; 302 | $len = strlen($tokens[$i]); 303 | while (($k < $cnt) && ($len == strlen($tokens[$i]))) { 304 | if (!isset($tokens[$k])) { 305 | $k++; 306 | continue; 307 | } 308 | $tokens[$i] .= $tokens[$k]; 309 | unset($tokens[$k]); 310 | $k++; 311 | } 312 | } 313 | 314 | $i++; 315 | } 316 | 317 | return array_values($tokens); 318 | } 319 | 320 | private function concatEscapeSequences($tokens) { 321 | $tokenCount = count($tokens); 322 | $i = 0; 323 | while ($i < $tokenCount) { 324 | 325 | if ($this->endsWith($tokens[$i], "\\")) { 326 | $i++; 327 | if (isset($tokens[$i])) { 328 | $tokens[$i - 1] .= $tokens[$i]; 329 | unset($tokens[$i]); 330 | } 331 | } 332 | $i++; 333 | } 334 | return array_values($tokens); 335 | } 336 | 337 | private function balanceParenthesis($tokens) { 338 | $token_count = count($tokens); 339 | $i = 0; 340 | while ($i < $token_count) { 341 | if ($tokens[$i] !== '(') { 342 | $i++; 343 | continue; 344 | } 345 | $count = 1; 346 | for ($n = $i + 1; $n < $token_count; $n++) { 347 | $token = $tokens[$n]; 348 | if ($token === '(') { 349 | $count++; 350 | } 351 | if ($token === ')') { 352 | $count--; 353 | } 354 | $tokens[$i] .= $token; 355 | unset($tokens[$n]); 356 | if ($count === 0) { 357 | $n++; 358 | break; 359 | } 360 | } 361 | $i = $n; 362 | } 363 | return array_values($tokens); 364 | } 365 | } 366 | -------------------------------------------------------------------------------- /vendor/soundintheory/php-sql-parser/src/PHPSQL/Parser/Lexer/Splitter.php: -------------------------------------------------------------------------------- 1 | 10 | * with contributions by Dan Vande More 11 | * 12 | * All rights reserved. 13 | * 14 | * Redistribution and use in source and binary forms, with or without modification, 15 | * are permitted provided that the following conditions are met: 16 | * 17 | * * Redistributions of source code must retain the above copyright notice, 18 | * this list of conditions and the following disclaimer. 19 | * * Redistributions in binary form must reproduce the above copyright notice, 20 | * this list of conditions and the following disclaimer in the documentation 21 | * and/or other materials provided with the distribution. 22 | * 23 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 24 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 25 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 26 | * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 27 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 28 | * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 29 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 30 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 31 | * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 32 | * DAMAGE. 33 | */ 34 | 35 | namespace PHPSQL\Parser\Lexer; 36 | 37 | class Splitter { 38 | 39 | private static $splitters = array("\r\n", "!=", ">=", "<=", "<>", ":=", "\\", "&&", ">", "<", "|", "=", "^", "(", 40 | ")", "\t", "\n", "'", "\"", "`", ",", "@", " ", "+", "-", "*", "/", ";"); 41 | private $tokenSize; 42 | private $hashSet; 43 | 44 | public function __construct() { 45 | $this->tokenSize = strlen(self::$splitters[0]); # should be the largest one 46 | $this->hashSet = array_flip(self::$splitters); 47 | } 48 | 49 | public function getMaxLengthOfSplitter() { 50 | return $this->tokenSize; 51 | } 52 | 53 | public function isSplitter($token) { 54 | return isset($this->hashSet[$token]); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /vendor/soundintheory/php-sql-parser/src/PHPSQL/Parser/PositionCalculator.php: -------------------------------------------------------------------------------- 1 | 10 | * with contributions by Dan Vande More 11 | * 12 | * All rights reserved. 13 | * 14 | * Redistribution and use in source and binary forms, with or without modification, 15 | * are permitted provided that the following conditions are met: 16 | * 17 | * * Redistributions of source code must retain the above copyright notice, 18 | * this list of conditions and the following disclaimer. 19 | * * Redistributions in binary form must reproduce the above copyright notice, 20 | * this list of conditions and the following disclaimer in the documentation 21 | * and/or other materials provided with the distribution. 22 | * 23 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 24 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 25 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 26 | * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 27 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 28 | * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 29 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 30 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 31 | * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 32 | * DAMAGE. 33 | */ 34 | 35 | namespace PHPSQL\Parser; 36 | 37 | /** 38 | * 39 | * This class calculates the positions 40 | * of base_expr within the original SQL statement. 41 | * 42 | * @author arothe 43 | * 44 | */ 45 | class PositionCalculator extends \PHPSQL\Parser\Utils { 46 | 47 | private static $allowedOnOperator = array("\t", "\n", "\r", " ", ",", "(", ")", "_", "'", "\""); 48 | private static $allowedOnOther = array("\t", "\n", "\r", " ", ",", "(", ")", "<", ">", "*", "+", "-", "/", "|", 49 | "&", "=", "!", ";"); 50 | 51 | private function printPos($text, $sql, $charPos, $key, $parsed, $backtracking) { 52 | if (!isset($_ENV['DEBUG'])) { 53 | return; 54 | } 55 | 56 | $spaces = ""; 57 | $caller = debug_backtrace(); 58 | $i = 1; 59 | while ($caller[$i]['function'] === 'lookForBaseExpression') { 60 | $spaces .= " "; 61 | $i++; 62 | } 63 | $holdem = substr($sql, 0, $charPos) . "^" . substr($sql, $charPos); 64 | echo $spaces . $text . " key:" . $key . " parsed:" . $parsed . " back:" . serialize($backtracking) . " " 65 | . $holdem . "\n"; 66 | } 67 | 68 | public function setPositionsWithinSQL($sql, $parsed) { 69 | $charPos = 0; 70 | $backtracking = array(); 71 | $this->lookForBaseExpression($sql, $charPos, $parsed, 0, $backtracking); 72 | return $parsed; 73 | } 74 | 75 | private function findPositionWithinString($sql, $value, $expr_type) { 76 | 77 | $offset = 0; 78 | $ok = false; 79 | $pos = false; 80 | while (true) { 81 | 82 | $pos = strpos($sql, $value, $offset); 83 | if ($pos === false) { 84 | break; 85 | } 86 | 87 | $before = ""; 88 | if ($pos > 0) { 89 | $before = $sql[$pos - 1]; 90 | } 91 | 92 | $after = ""; 93 | if (isset($sql[$pos + strlen($value)])) { 94 | $after = $sql[$pos + strlen($value)]; 95 | } 96 | 97 | # if we have an operator, it should be surrounded by 98 | # whitespace, comma, parenthesis, digit or letter, end_of_string 99 | # an operator should not be surrounded by another operator 100 | 101 | if ($expr_type === 'operator') { 102 | 103 | $ok = ($before === "" || in_array($before, self::$allowedOnOperator, true)) 104 | || (strtolower($before) >= 'a' && strtolower($before) <= 'z') 105 | || ($before >= '0' && $before <= '9'); 106 | $ok = $ok 107 | && ($after === "" || in_array($after, self::$allowedOnOperator, true) 108 | || (strtolower($after) >= 'a' && strtolower($after) <= 'z') 109 | || ($after >= '0' && $after <= '9') || ($after === '?') || ($after === '@')); 110 | 111 | if (!$ok) { 112 | $offset = $pos + 1; 113 | continue; 114 | } 115 | 116 | break; 117 | } 118 | 119 | # in all other cases we accept 120 | # whitespace, comma, operators, parenthesis and end_of_string 121 | 122 | $ok = ($before === "" || in_array($before, self::$allowedOnOther, true)); 123 | $ok = $ok && ($after === "" || in_array($after, self::$allowedOnOther, true)); 124 | 125 | if ($ok) { 126 | break; 127 | } 128 | 129 | $offset = $pos + 1; 130 | } 131 | 132 | return $pos; 133 | } 134 | 135 | private function lookForBaseExpression($sql, &$charPos, &$parsed, $key, &$backtracking) { 136 | if (!is_numeric($key)) { 137 | if (($key === 'UNION' || $key === 'UNION ALL') 138 | || ($key === 'expr_type' && $parsed === \PHPSQL\Expression\Type::EXPRESSION) 139 | || ($key === 'expr_type' && $parsed === \PHPSQL\Expression\Type::SUBQUERY) 140 | || ($key === 'expr_type' && $parsed === \PHPSQL\Expression\Type::BRACKET_EXPRESSION) 141 | || ($key === 'expr_type' && $parsed === \PHPSQL\Expression\Type::TABLE_EXPRESSION) 142 | || ($key === 'expr_type' && $parsed === \PHPSQL\Expression\Type::RECORD) 143 | || ($key === 'expr_type' && $parsed === \PHPSQL\Expression\Type::IN_LIST) 144 | || ($key === 'expr_type' && $parsed === \PHPSQL\Expression\Type::MATCH_ARGUMENTS) 145 | || ($key === 'alias' && $parsed !== false)) { 146 | # we hold the current position and come back after the next base_expr 147 | # we do this, because the next base_expr contains the complete expression/subquery/record 148 | # and we have to look into it too 149 | $backtracking[] = $charPos; 150 | 151 | } elseif (($key === 'ref_clause' || $key === 'columns') && $parsed !== false) { 152 | # we hold the current position and come back after n base_expr(s) 153 | # there is an array of sub-elements before (!) the base_expr clause of the current element 154 | # so we go through the sub-elements and must come at the end 155 | $backtracking[] = $charPos; 156 | for ($i = 1; $i < count($parsed); $i++) { 157 | $backtracking[] = false; # backtracking only after n base_expr! 158 | } 159 | } elseif ($key === 'sub_tree' && $parsed !== false) { 160 | # we prevent wrong backtracking on subtrees (too much array_pop()) 161 | # there is an array of sub-elements after(!) the base_expr clause of the current element 162 | # so we go through the sub-elements and must not come back at the end 163 | for ($i = 1; $i < count($parsed); $i++) { 164 | $backtracking[] = false; 165 | } 166 | } else { 167 | # move the current pos after the keyword 168 | # SELECT, WHERE, INSERT etc. 169 | if (in_array($key, parent::$reserved)) { 170 | $charPos = stripos($sql, $key, $charPos); 171 | $charPos += strlen($key); 172 | } 173 | } 174 | } 175 | 176 | if (!is_array($parsed)) { 177 | return; 178 | } 179 | 180 | foreach ($parsed as $key => $value) { 181 | if ($key === 'base_expr') { 182 | 183 | #$this->printPos("0", $sql, $charPos, $key, $value, $backtracking); 184 | 185 | $subject = substr($sql, $charPos); 186 | $pos = $this->findPositionWithinString($subject, $value, 187 | isset($parsed['expr_type']) ? $parsed['expr_type'] : 'alias'); 188 | if ($pos === false) { 189 | throw new \PHPSQL\Exception\UnableToCalculatePosition($value, $subject); 190 | } 191 | 192 | $parsed['position'] = $charPos + $pos; 193 | $charPos += $pos + strlen($value); 194 | 195 | #$this->printPos("1", $sql, $charPos, $key, $value, $backtracking); 196 | 197 | $oldPos = array_pop($backtracking); 198 | if (isset($oldPos) && $oldPos !== false) { 199 | $charPos = $oldPos; 200 | } 201 | 202 | #$this->printPos("2", $sql, $charPos, $key, $value, $backtracking); 203 | 204 | } else { 205 | $this->lookForBaseExpression($sql, $charPos, $parsed[$key], $key, $backtracking); 206 | } 207 | } 208 | } 209 | } 210 | -------------------------------------------------------------------------------- /vendor/soundintheory/php-sql-parser/src/PHPSQL/Parser/Utils.php: -------------------------------------------------------------------------------- 1 | 9 | * with contributions by Dan Vande More 10 | * 11 | * All rights reserved. 12 | * 13 | * Redistribution and use in source and binary forms, with or without modification, 14 | * are permitted provided that the following conditions are met: 15 | * 16 | * * Redistributions of source code must retain the above copyright notice, 17 | * this list of conditions and the following disclaimer. 18 | * * Redistributions in binary form must reproduce the above copyright notice, 19 | * this list of conditions and the following disclaimer in the documentation 20 | * and/or other materials provided with the distribution. 21 | * 22 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 23 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 24 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 25 | * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 26 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 27 | * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 28 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 29 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 30 | * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 31 | * DAMAGE. 32 | */ 33 | 34 | namespace PHPSQL\Parser; 35 | 36 | /** 37 | * This class implements some helper functions. 38 | * @author arothe 39 | * 40 | */ 41 | class Utils extends \PHPSQL\Parser\Constants { 42 | 43 | /** 44 | * Ends the given string $haystack with the string $needle? 45 | * @param string $haystack 46 | * @param string $needle 47 | * @return bool $in 48 | */ 49 | protected function endsWith($haystack, $needle) { 50 | $length = strlen($needle); 51 | if ($length == 0) { 52 | return true; 53 | } 54 | 55 | $start = $length * -1; 56 | return (substr($haystack, $start) === $needle); 57 | } 58 | 59 | /** 60 | * Revokes the escaping characters from an expression 61 | */ 62 | protected function revokeEscaping($sql) { 63 | $result = trim($sql); 64 | if (($result[0] === '`') && ($result[strlen($result) - 1] === '`')) { 65 | $result = substr($result, 1, -1); 66 | } 67 | return str_replace('``', '`', $result); 68 | } 69 | 70 | /** 71 | * This method removes parenthesis from start of the given string. 72 | * It removes also the associated closing parenthesis. 73 | */ 74 | protected function removeParenthesisFromStart($token) { 75 | 76 | $parenthesisRemoved = 0; 77 | 78 | $trim = trim($token); 79 | if ($trim !== "" && $trim[0] === "(") { // remove only one parenthesis pair now! 80 | $parenthesisRemoved++; 81 | $trim[0] = " "; 82 | $trim = trim($trim); 83 | } 84 | 85 | $parenthesis = $parenthesisRemoved; 86 | $i = 0; 87 | $string = 0; 88 | while ($i < strlen($trim)) { 89 | 90 | if ($trim[$i] === "\\") { 91 | $i += 2; # an escape character, the next character is irrelevant 92 | continue; 93 | } 94 | 95 | if ($trim[$i] === "'" || $trim[$i] === '"') { 96 | $string++; 97 | } 98 | 99 | if (($string % 2 === 0) && ($trim[$i] === "(")) { 100 | $parenthesis++; 101 | } 102 | 103 | if (($string % 2 === 0) && ($trim[$i] === ")")) { 104 | if ($parenthesis == $parenthesisRemoved) { 105 | $trim[$i] = " "; 106 | $parenthesisRemoved--; 107 | } 108 | $parenthesis--; 109 | } 110 | $i++; 111 | } 112 | return trim($trim); 113 | } 114 | 115 | public function getLastOf($array) { 116 | // $array is a copy of the original array, so we can change it without sideeffects 117 | if (!is_array($array)) { 118 | return false; 119 | } 120 | return array_pop($array); 121 | } 122 | 123 | /** 124 | * translates an array of objects into an associative array 125 | */ 126 | public function toArray($tokenList) { 127 | $expr = array(); 128 | foreach ($tokenList as $token) { 129 | /** 130 | * @var $token \PHPSQL\Expression\Token 131 | */ 132 | $expr[] = $token->toArray(); 133 | } 134 | return (empty($expr) ? false : $expr); 135 | } 136 | } 137 | --------------------------------------------------------------------------------