Repository: qieangel2013/EsParser Branch: master Commit: 3beffb3e3219 Files: 124 Total size: 692.1 KB Directory structure: gitextract_02kj_sub/ ├── EsParser_realse.php ├── README.md ├── composer.json ├── index.php └── src/ ├── example.php └── library/ ├── EsCreator.php ├── EsParser.php ├── builders/ │ ├── AliasBuilder.php │ ├── CharacterSetBuilder.php │ ├── CheckBuilder.php │ ├── CollationBuilder.php │ ├── ColumnDefinitionBuilder.php │ ├── ColumnListBuilder.php │ ├── ColumnReferenceBuilder.php │ ├── ColumnTypeBracketExpressionBuilder.php │ ├── ColumnTypeBuilder.php │ ├── ConstantBuilder.php │ ├── ConstraintBuilder.php │ ├── CreateBuilder.php │ ├── CreateStatementBuilder.php │ ├── CreateTableBuilder.php │ ├── CreateTableDefinitionBuilder.php │ ├── CreateTableOptionsBuilder.php │ ├── CreateTableSelectOptionBuilder.php │ ├── DataTypeBuilder.php │ ├── DatabaseBuilder.php │ ├── DeleteBuilder.php │ ├── DeleteStatementBuilder.php │ ├── DirectionBuilder.php │ ├── EngineBuilder.php │ ├── ForeignKeyBuilder.php │ ├── ForeignRefBuilder.php │ ├── FromBuilder.php │ ├── FunctionBuilder.php │ ├── GroupByBuilder.php │ ├── InListBuilder.php │ ├── IndexColumnBuilder.php │ ├── IndexParserBuilder.php │ ├── IndexSizeBuilder.php │ ├── IndexTypeBuilder.php │ ├── InsertBuilder.php │ ├── InsertStatementBuilder.php │ ├── JoinBuilder.php │ ├── LikeBuilder.php │ ├── LikeExpressionBuilder.php │ ├── LimitBuilder.php │ ├── OperatorBuilder.php │ ├── OrderByAliasBuilder.php │ ├── OrderByBuilder.php │ ├── PositionBuilder.php │ ├── PrimaryKeyBuilder.php │ ├── ProcedureBuilder.php │ ├── RecordBuilder.php │ ├── RefClauseBuilder.php │ ├── RefTypeBuilder.php │ ├── ReservedBuilder.php │ ├── SelectBracketExpressionBuilder.php │ ├── SelectBuilder.php │ ├── SelectExpressionBuilder.php │ ├── SelectStatementBuilder.php │ ├── SetBuilder.php │ ├── SetExpressionBuilder.php │ ├── ShowBuilder.php │ ├── ShowStatementBuilder.php │ ├── SubQueryBuilder.php │ ├── SubTreeBuilder.php │ ├── TableBracketExpressionBuilder.php │ ├── TableBuilder.php │ ├── TableExpressionBuilder.php │ ├── UpdateBuilder.php │ ├── UpdateStatementBuilder.php │ ├── UserVariableBuilder.php │ ├── ValuesBuilder.php │ ├── WhereBracketExpressionBuilder.php │ ├── WhereBuilder.php │ └── WhereExpressionBuilder.php ├── exceptions/ │ ├── InvalidParameterException.php │ ├── UnableToCalculatePositionException.php │ ├── UnableToCreateSQLException.php │ └── UnsupportedFeatureException.php ├── lexer/ │ ├── LexerSplitter.php │ └── PHPSQLLexer.php ├── positions/ │ └── PositionCalculator.php ├── processors/ │ ├── AbstractProcessor.php │ ├── ColumnDefinitionProcessor.php │ ├── ColumnListProcessor.php │ ├── CreateDefinitionProcessor.php │ ├── CreateProcessor.php │ ├── DefaultProcessor.php │ ├── DeleteProcessor.php │ ├── DescProcessor.php │ ├── DescribeProcessor.php │ ├── DropProcessor.php │ ├── DuplicateProcessor.php │ ├── ExplainProcessor.php │ ├── ExpressionListProcessor.php │ ├── FromProcessor.php │ ├── GroupByProcessor.php │ ├── HavingProcessor.php │ ├── IndexColumnListProcessor.php │ ├── InsertProcessor.php │ ├── IntoProcessor.php │ ├── LimitProcessor.php │ ├── OrderByProcessor.php │ ├── RecordProcessor.php │ ├── ReferenceDefinitionProcessor.php │ ├── RenameProcessor.php │ ├── ReplaceProcessor.php │ ├── SQLChunkProcessor.php │ ├── SQLProcessor.php │ ├── SelectExpressionProcessor.php │ ├── SelectProcessor.php │ ├── SetProcessor.php │ ├── ShowProcessor.php │ ├── TableProcessor.php │ ├── UnionProcessor.php │ ├── UpdateProcessor.php │ ├── UsingProcessor.php │ ├── ValuesProcessor.php │ └── WhereProcessor.php └── utils/ ├── ExpressionToken.php ├── ExpressionType.php ├── PHPSQLParserConstants.php └── PHPSQLParserUtils.php ================================================ FILE CONTENTS ================================================ ================================================ FILE: EsParser_realse.php ================================================ 1, 'message'=>'es的配置项不能为空!' ); $this->result=json_encode($config_err,true); return $this->result; }else{ $this->index_es=$es_config['index']; $this->type_es=$es_config['type']; $this->url=$es_config['url']; if(!isset($es_config['version'])){ $version=$this->getEsData($es_config['url']); if($version){ if(version_compare($version,'5.0.0', '<')){ $this->version_es='2.x'; }else if( version_compare($version,'5.0.0', '>=') && version_compare($version,'6.0.0', '<')){ $this->version_es='5.x'; }else{ $this->version_es='6.x'; } }else{ $this->version_es='5.x'; } }else{ if(trim($es_config['version'])==''){ $this->version_es='5.x'; }else{ $this->version_es=$es_config['version']; } } } if ($sql) { $this->parse($sql, $calcPositions); } } /** * * @param String $sql The SQL statement. * @param boolean $calcPositions True, if the output should contain [position], false otherwise. * * @return array An associative array with all meta information about the SQL statement. */ public function parsesql($sql, $calcPositions = false) { $processor = new DefaultProcessor(); $queries = $processor->process($sql); if ($calcPositions) { $calculator = new PositionCalculator(); $queries = $calculator->setPositionsWithinSQL($sql, $queries); } $this->parsed = $queries; return $this->parsed; } public function parse($sql, $calcPositions = false) { $processor = new DefaultProcessor(); $queries = $processor->process($sql); if ($calcPositions) { $calculator = new PositionCalculator(); $queries = $calculator->setPositionsWithinSQL($sql, $queries); } $this->parsed = $queries; return $this->EsBuilder(); //return $this->parsed; } private function EsBuilder(){ //table if(isset($this->parsed['FROM']) && !empty($this->parsed['FROM'])){ $this->table($this->parsed['FROM']); } //update if(isset($this->parsed['UPDATE']) && !empty($this->parsed['UPDATE'])){ $this->update($this->parsed['UPDATE']); } //set if(isset($this->parsed['SET']) && !empty($this->parsed['SET'])){ $this->updateset($this->parsed['SET']); } //delete if(isset($this->parsed['DELETE']) && !empty($this->parsed['DELETE'])){ $this->delete($this->parsed['DELETE']); } //limit if(isset($this->parsed['LIMIT']) && !empty($this->parsed['LIMIT'])){ $this->limit($this->parsed['LIMIT']); if(isset($this->parsed['GROUP']) && !empty($this->parsed['GROUP'])){ $this->Builderarr['size']=0; }else{ $this->Builderarr['from']=$this->limit['from'] * $this->limit['size']; $this->Builderarr['size']=$this->limit['size']; } } //where if(isset($this->parsed['WHERE']) && !empty($this->parsed['WHERE'])){ $this->where($this->parsed['WHERE']); } //groupby if(isset($this->parsed['GROUP']) && !empty($this->parsed['GROUP'])){ $this->groupby($this->parsed['GROUP']); if(!empty($this->agg['aggs'])){ $this->Builderarr['aggs']=$this->agg['aggs']; } } //orderby if(isset($this->parsed['ORDER']) && !empty($this->parsed['ORDER'])){ $this->orderby($this->parsed['ORDER']); if(!empty($this->sort['sort'])){ $this->Builderarr['sort']=$this->sort['sort']; } } //select if(isset($this->parsed['SELECT']) && !empty($this->parsed['SELECT'])){ $this->select($this->parsed['SELECT']); } if(!isset($this->Builderarr) && empty($this->Builderarr)){ $this->Builderarr['query']['match_all']=(object)array(); } //request return $this->PostEs($this->Builderarr); } public function explain(){ $this->explain=json_encode($this->Builderarr,true); return $this->explain; } private function table($arr){ if(isset($this->parsed['DELETE']) && !empty($this->parsed['DELETE'])){ foreach ($arr as $v) { if($v['table']){ $this->url .="/".$this->index_es."/".$this->type_es."/_delete_by_query?pretty"; } } }else{ foreach ($arr as $v) { if($v['table']){ $this->url .="/".$this->index_es."/".$this->type_es."/_search?pretty"; } } } } private function update($arr){ foreach ($arr as $v) { if($v['table']){ $this->table=$v['table']; $this->url .="/".$this->index_es."/".$this->type_es."/"; } } } private function delete($arr){ } private function getEsData($url){ $ch = curl_init($url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1) ; curl_setopt($ch, CURLOPT_TIMEOUT, 60); curl_setopt($ch, CURLOPT_HEADER, 0); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_SSLVERSION, 3); curl_setopt($ch, CURLOPT_BINARYTRANSFER, true) ; $output = curl_exec($ch); if($output === false) //超时处理 { if(curl_errno($ch) == CURLE_OPERATION_TIMEDOUT) { my_file_put_contents("getEsData.txt", "时间:".date('Ymd-H:i:s',time())."\r\n错误内容为:curl通过get方式请求{$url}的连接超时\r\n"); } } curl_close($ch); $output=json_decode($output,true); if (empty($output)) { return array(); } return $output['version']['number']; } private function PostEs($postdata,$json=true,$token=false){ $url=$this->url; $datastring = json_encode($postdata,true); $ch = curl_init($url); curl_setopt($ch, CURLOPT_URL, $url) ; curl_setopt($ch, CURLOPT_POST, 1) ; curl_setopt($ch, CURLOPT_HEADER, 0); curl_setopt($ch, CURLINFO_HEADER_OUT, true); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_TIMEOUT, 60); //只需要设置一个秒的数量就可以 curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_SSLVERSION, 3); curl_setopt($ch, CURLOPT_POSTFIELDS, $datastring); if ($json) { curl_setopt($ch, CURLOPT_HTTPHEADER, array( 'Content-Type: application/json;', 'Content-Length: ' . strlen($datastring)) ); } if ($token) { curl_setopt( $ch, CURLOPT_HTTPHEADER, array( 'Content-Type: application/json; charset=utf-8', 'Content-Length: ' . strlen($datastring), 'Authorization:'.$token ) ); } $output=curl_exec($ch); if($output === false) //超时处理 { if(curl_errno($ch) == CURLE_OPERATION_TIMEDOUT) { file_put_contents("getEsData.txt", "时间:".date('Ymd-H:i:s',time())."\r\n错误内容为:curl通过post方式请求{$this->url}的连接超时\r\n"); } } curl_close($ch); $output=json_decode($output,true); if (empty($output)) { $this->result=json_encode(array(),true); } if(isset($output['error'])){ $this->result=json_encode($output,true); }else if(isset($this->parsed['UPDATE']) && !empty($this->parsed['UPDATE'])){ $update_arr=$output['_shards']; unset($update_arr['total']); $this->result=json_encode($update_arr,true); }else if(isset($this->parsed['DELETE']) && !empty($this->parsed['DELETE'])){ $delete_arr['total']=$output['total']; $delete_arr['deleted']=$output['deleted']; $delete_arr['successfull']=$output['deleted']; $this->result=json_encode($delete_arr,true); }else{ $total_str=$output['hits']['total']; if(isset($this->parsed['GROUP']) && !empty($this->parsed['GROUP'])){ if($output['hits']['hits'] && empty($output['aggregations'][$this->fistgroup]['buckets'])){ $outputs['result']=array_slice($output['hits']['hits'],-$this->limit['size']); }else if(isset($output['aggregations'][$this->fistgroup]['buckets']) && !empty($output['aggregations'][$this->fistgroup]['buckets'])){ $outputs['result']=$output['aggregations'][$this->fistgroup]['buckets']; }else{ $outputs['result']=array_slice($output['aggregations'][$this->fistgroup]['buckets'],-$this->limit['size']); } }else{ if(isset($output['aggregations']) && !empty($output['aggregations'])){ $outputs['result']=$output['aggregations']; }else{ $outputs['result']=$output['hits']['hits']; } } $outputs['total']=$total_str; $this->result=json_encode($outputs,true); } return $this->result; } private function where($arr){ for($i=0;$iwhereext($arr[$i]['sub_tree'],$j); } } }else{ $this->whereext($arr,$i); } } } private function whereext($arr,$i){ if(!is_numeric($arr[$i]['base_expr'])){ $lowerstr = strtolower($arr[$i]['base_expr']); }else{ $lowerstr = $arr[$i]['base_expr']; } switch ($lowerstr) { case '=': if(isset($arr[$i+2]['base_expr']) && strtolower($arr[$i+2]['base_expr'])=='or' || isset($arr[$i-2]['base_expr']) && strtolower($arr[$i-2]['base_expr'])=='or'){ if(strrpos($arr[$i-1]['base_expr'],".")){ $term_tmp_arr=explode(".",$arr[$i-1]['base_expr']); $termk=$term_tmp_arr[1]; }else{ $termk=$arr[$i-1]['base_expr']; } $tmp_da_str=str_replace('"','',$arr[$i+1]['base_expr']); $tmp_da_str=str_replace("'","",$tmp_da_str); if(isset($this->Builderarr['query']['bool']['filter'][0]) && $this->tmp_lock!='' && $this->tmp_lock!=$lowerstr){ if($this->tmp_str_filter==''){ $this->count_tmp_filter++; }else if($this->tmp_str_filter!='' && $this->tmp_str_filter!=$termk){ $this->count_tmp_filter++; } } if(isset($this->Builderarr['query']['bool']['filter'][0]['bool']['must'][0]) && $this->tmp_lock_str!='' && $this->tmp_lock_str!=$lowerstr){ if($this->tmp_str==''){ $this->count_tmp++; }else if($this->tmp_str!='' && $this->tmp_str!=$termk){ $this->count_tmp++; } } if(isset($this->parsed['UPDATE']) && !empty($this->parsed['UPDATE'])){ $this->url .=$tmp_da_str ."/_update?pretty"; }else{ if(!is_numeric($arr[$i+1]['base_expr']) && $this->version_es=='8.x'){ $term['match_phrase'][$termk.'.keyword']['query']=$tmp_da_str; $this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]['bool']['must'][$this->count_tmp]['bool']['should'][]=$term; }else{ $term['match_phrase'][$termk]['query']=$tmp_da_str; $this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]['bool']['must'][$this->count_tmp]['bool']['should'][]=$term; } unset($term['match_phrase']); } $this->tmp_lock=$lowerstr; $this->tmp_lock_str=$lowerstr; }else if(isset($arr[$i+2]['base_expr']) && strtolower($arr[$i+2]['base_expr'])=='and' || isset($arr[$i-2]['base_expr']) && strtolower($arr[$i-2]['base_expr'])=='and'){ if(strrpos($arr[$i-1]['base_expr'],".")){ $term_tmp_arr=explode(".",$arr[$i-1]['base_expr']); $termk=$term_tmp_arr[1]; }else{ $termk=$arr[$i-1]['base_expr']; } $tmp_da_str=str_replace('"','',$arr[$i+1]['base_expr']); $tmp_da_str=str_replace("'","",$tmp_da_str); if(isset($this->Builderarr['query']['bool']['must'][0]) && $this->tmp_lock_str!='' && $this->tmp_lock_str!=$lowerstr){ if($this->tmp_str==''){ $this->count_tmp++; }else if($this->tmp_str!='' && $this->tmp_str!=$termk){ $this->count_tmp++; } } if(isset($this->parsed['UPDATE']) && !empty($this->parsed['UPDATE'])){ $this->url .=$tmp_da_str ."/_update?pretty"; }else{ if(!is_numeric($arr[$i+1]['base_expr']) && $this->version_es=='8.x'){ $term['match_phrase'][$termk.'.keyword']['query']=$tmp_da_str; $this->Builderarr['query']['bool']['must'][$this->count_tmp]['bool']['must'][]=$term; }else{ $term['match_phrase'][$termk]['query']=$tmp_da_str; $this->Builderarr['query']['bool']['must'][$this->count_tmp]['bool']['must'][]=$term; } unset($term['match_phrase']); } $this->tmp_lock_str=$lowerstr; } break; case 'in': if(strrpos($arr[$i-1]['base_expr'],".")){ $term_tmp_arr=explode(".",$arr[$i-1]['base_expr']); $termk=$term_tmp_arr[1]; }else{ $termk=$arr[$i-1]['base_expr']; } if(isset($this->Builderarr['query']['bool']['filter'][0]) && $this->tmp_lock!='' && $this->tmp_lock==$lowerstr){ if($this->tmp_str_filter==''){ $this->count_tmp_filter++; }else if($this->tmp_str_filter!='' && $this->tmp_str_filter!=$termk){ $this->count_tmp_filter++; } } if(isset($arr[$i+1]['sub_tree']) && !empty($arr[$i+1]['sub_tree'])){ foreach ($arr[$i+1]['sub_tree'] as &$vv) { if(!is_numeric($vv['base_expr']) && $this->version_es=='5.x'){ $termk .='.keyword'; } $this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]['terms'][$termk][]=$vv['base_expr']; } } unset($termk); $this->tmp_lock=$lowerstr; break; case '>': if(strrpos($arr[$i-1]['base_expr'],".")){ $term_tmp_arr=explode(".",$arr[$i-1]['base_expr']); $termk=$term_tmp_arr[1]; }else{ $termk=$arr[$i-1]['base_expr']; } $tmp_da_str=str_replace('"','',$arr[$i+1]['base_expr']); $tmp_da_str=str_replace("'","",$tmp_da_str); $is_date=strtotime($tmp_da_str)?strtotime($tmp_da_str):false; if(isset($arr[$i+2]['base_expr']) && strtolower($arr[$i+2]['base_expr'])=='or' || isset($arr[$i-2]['base_expr']) && strtolower($arr[$i-2]['base_expr'])=='or'){ if(isset($this->Builderarr['query']['bool']['filter'][0]) && $this->tmp_lock!='' && $this->tmp_lock==$lowerstr){ if($this->tmp_str_filter==''){ $this->count_tmp_filter++; }else if($this->tmp_str_filter!='' && $this->tmp_str_filter!=$termk){ $this->count_tmp_filter++; } } if(isset($this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]['bool']['must'][0]) && $this->tmp_lock_fi!='' && $this->tmp_lock_fi==$lowerstr){ if($this->tmp_fi==''){ $this->count_fi++; }else if($this->tmp_fi!='' && $this->tmp_fi!=$termk){ $this->count_fi++; } } if(isset($this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]['bool']['must'][$this->count_fi]['bool']['should'][0]) && $this->tmp_lock_range!=''){ if($this->tmp_str_range==''){ $this->count_tmp_range++; }else if($this->tmp_str_range!='' && $this->tmp_str_range!=$termk){ $this->count_tmp_range++; } } $this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]['bool']['must'][$this->count_fi]['bool']['should'][$this->count_tmp_range]['range'][$termk]['gt']=$tmp_da_str; if(!isset($this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]['bool']['must'][$this->count_fi]['bool']['should'][$this->count_tmp_range]['range'][$termk]['time_zone']) && $is_date){ $this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]['bool']['must'][$this->count_fi]['bool']['should'][$this->count_tmp_range]['range'][$termk]['time_zone']="+08:00"; } }else{ if(isset($this->Builderarr['query']['bool']['must'][0]) && $this->tmp_lock_str!='' && $this->tmp_lock_str!=$lowerstr){ if($this->tmp_str==''){ $this->count_tmp++; }else if($this->tmp_str!='' && $this->tmp_str!=$termk){ $this->count_tmp++; } } $this->Builderarr['query']['bool']['must'][$this->count_tmp]['range'][$termk]['gt']=$tmp_da_str; if(!isset($this->Builderarr['query']['bool']['must'][$this->count_tmp]['range'][$termk]['time_zone']) && $is_date){ $this->Builderarr['query']['bool']['must'][$this->count_tmp]['range'][$termk]['time_zone']="+08:00"; } } $this->tmp_str=$termk; $this->tmp_lock_str=$lowerstr; $this->tmp_lock=$lowerstr; $this->tmp_lock_range=$lowerstr; $this->tmp_lock_fi=$lowerstr; break; case '>=': if(strrpos($arr[$i-1]['base_expr'],".")){ $term_tmp_arr=explode(".",$arr[$i-1]['base_expr']); $termk=$term_tmp_arr[1]; }else{ $termk=$arr[$i-1]['base_expr']; } $tmp_da_str=str_replace('"','',$arr[$i+1]['base_expr']); $tmp_da_str=str_replace("'","",$tmp_da_str); $is_date=strtotime($tmp_da_str)?strtotime($tmp_da_str):false; if(isset($arr[$i+2]['base_expr']) && strtolower($arr[$i+2]['base_expr'])=='or' || isset($arr[$i-2]['base_expr']) && strtolower($arr[$i-2]['base_expr'])=='or'){ if(isset($this->Builderarr['query']['bool']['filter'][0]) && $this->tmp_lock!='' && $this->tmp_lock==$lowerstr){ if($this->tmp_str_filter==''){ $this->count_tmp_filter++; }else if($this->tmp_str_filter!='' && $this->tmp_str_filter!=$termk){ $this->count_tmp_filter++; } } if(isset($this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]['bool']['must'][0]) && $this->tmp_lock_fi!='' && $this->tmp_lock_fi==$lowerstr){ if($this->tmp_fi==''){ $this->count_fi++; }else if($this->tmp_fi!='' && $this->tmp_fi!=$termk){ $this->count_fi++; } } if(isset($this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]['bool']['must'][$this->count_fi]['bool']['should'][0]) && $this->tmp_lock_range!='' ){ if($this->tmp_str_range==''){ $this->count_tmp_range++; }else if($this->tmp_str_range!='' && $this->tmp_str_range!=$termk){ $this->count_tmp_range++; } } $this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]['bool']['must'][$this->count_fi]['bool']['should'][$this->count_tmp_range]['range'][$termk]['gte']=$tmp_da_str; if(!isset($this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]['bool']['must'][$this->count_fi]['bool']['should'][$this->count_tmp_range]['range'][$termk]['time_zone']) && $is_date){ $this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]['bool']['must'][$this->count_fi]['bool']['should'][$this->count_tmp_range]['range'][$termk]['time_zone']="+08:00"; } }else{ if(isset($this->Builderarr['query']['bool']['must'][0]) && $this->tmp_lock_str!='' && $this->tmp_lock_str!=$lowerstr){ if($this->tmp_str==''){ $this->count_tmp++; }else if($this->tmp_str!='' && $this->tmp_str!=$termk){ $this->count_tmp++; } } $this->Builderarr['query']['bool']['must'][$this->count_tmp]['range'][$termk]['gte']=$tmp_da_str; if(!isset($this->Builderarr['query']['bool']['must'][$this->count_tmp]['range'][$termk]['time_zone']) && $is_date){ $this->Builderarr['query']['bool']['must'][$this->count_tmp]['range'][$termk]['time_zone']="+08:00"; } } $this->tmp_str=$termk; $this->tmp_lock_str=$lowerstr; $this->tmp_lock=$lowerstr; $this->tmp_lock_range=$lowerstr; $this->tmp_lock_fi=$lowerstr; break; case '<': if(strrpos($arr[$i-1]['base_expr'],".")){ $term_tmp_arr=explode(".",$arr[$i-1]['base_expr']); $termk=$term_tmp_arr[1]; }else{ $termk=$arr[$i-1]['base_expr']; } $tmp_da_str=str_replace('"','',$arr[$i+1]['base_expr']); $tmp_da_str=str_replace("'","",$tmp_da_str); $is_date=strtotime($tmp_da_str)?strtotime($tmp_da_str):false; if(isset($arr[$i+2]['base_expr']) && strtolower($arr[$i+2]['base_expr'])=='or' || isset($arr[$i-2]['base_expr']) && strtolower($arr[$i-2]['base_expr'])=='or'){ if(isset($this->Builderarr['query']['bool']['filter'][0]) && $this->tmp_lock!='' && $this->tmp_lock==$lowerstr){ if($this->tmp_str_filter==''){ $this->count_tmp_filter++; }else if($this->tmp_str_filter!='' && $this->tmp_str_filter!=$termk){ $this->count_tmp_filter++; } } if(isset($this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]['bool']['must'][0]) && $this->tmp_lock_fi!='' && $this->tmp_lock_fi==$lowerstr){ if($this->tmp_fi==''){ $this->count_fi++; }else if($this->tmp_fi!='' && $this->tmp_fi!=$termk){ $this->count_fi++; } } if(isset($this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]['bool']['must'][$this->count_fi]['bool']['should'][0]) && $this->tmp_lock_range!=''){ if($this->tmp_str_range==''){ $this->count_tmp_range++; }else if($this->tmp_str_range!='' && $this->tmp_str_range!=$termk){ $this->count_tmp_range++; } } $this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]['bool']['must'][$this->count_fi]['bool']['should'][$this->count_tmp_range]['range'][$termk]['lt']=$tmp_da_str; if(!isset($this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]['bool']['must'][$this->count_fi]['bool']['should'][$this->count_tmp_range]['range'][$termk]['time_zone']) && $is_date){ $this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]['bool']['must'][$this->count_fi]['bool']['should'][$this->count_tmp_range]['range'][$termk]['time_zone']="+08:00"; } }else{ if(isset($this->Builderarr['query']['bool']['must'][0]) && $this->tmp_lock_str!='' && $this->tmp_lock_str!=$lowerstr){ if($this->tmp_str==''){ $this->count_tmp++; }else if($this->tmp_str!='' && $this->tmp_str!=$termk){ $this->count_tmp++; } } $this->Builderarr['query']['bool']['must'][$this->count_tmp]['range'][$termk]['lt']=$tmp_da_str; if(!isset($this->Builderarr['query']['bool']['must'][$this->count_tmp]['range'][$termk]['time_zone']) && $is_date){ $this->Builderarr['query']['bool']['must'][$this->count_tmp]['range'][$termk]['time_zone']="+08:00"; } } $this->tmp_str=$termk; $this->tmp_lock_str=$lowerstr; $this->tmp_lock=$lowerstr; $this->tmp_lock_range=$lowerstr; $this->tmp_lock_fi=$lowerstr; break; case '<=': if(strrpos($arr[$i-1]['base_expr'],".")){ $term_tmp_arr=explode(".",$arr[$i-1]['base_expr']); $termk=$term_tmp_arr[1]; }else{ $termk=$arr[$i-1]['base_expr']; } $tmp_da_str=str_replace('"','',$arr[$i+1]['base_expr']); $tmp_da_str=str_replace("'","",$tmp_da_str); $is_date=strtotime($tmp_da_str)?strtotime($tmp_da_str):false; if(isset($arr[$i+2]['base_expr']) && strtolower($arr[$i+2]['base_expr'])=='or' || isset($arr[$i-2]['base_expr']) && strtolower($arr[$i-2]['base_expr'])=='or'){ if(isset($this->Builderarr['query']['bool']['filter'][0]) && $this->tmp_lock!='' && $this->tmp_lock==$lowerstr){ if($this->tmp_str_filter==''){ $this->count_tmp_filter++; }else if($this->tmp_str_filter!='' && $this->tmp_str_filter!=$termk){ $this->count_tmp_filter++; } } if(isset($this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]['bool']['must'][0]) && $this->tmp_lock_fi!='' && $this->tmp_lock_fi==$lowerstr){ if($this->tmp_fi==''){ $this->count_fi++; }else if($this->tmp_fi!='' && $this->tmp_fi!=$termk){ $this->count_fi++; } } if(isset($this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]['bool']['must'][$this->count_fi]['bool']['should'][0]) && $this->tmp_lock_range!='' ){ if($this->tmp_str_range==''){ $this->count_tmp_range++; }else if($this->tmp_str_range!='' && $this->tmp_str_range!=$termk){ $this->count_tmp_range++; } } $this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]['bool']['must'][$this->count_fi]['bool']['should'][$this->count_tmp_range]['range'][$termk]['lte']=$tmp_da_str; if(!isset($this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]['bool']['must'][$this->count_fi]['bool']['should'][$this->count_tmp_range]['range'][$termk]['time_zone']) && $is_date){ $this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]['bool']['must'][$this->count_fi]['bool']['should'][$this->count_tmp_range]['range'][$termk]['time_zone']="+08:00"; } }else{ if(isset($this->Builderarr['query']['bool']['must'][0]) && $this->tmp_lock_str!='' && $this->tmp_lock_str!=$lowerstr){ if($this->tmp_str==''){ $this->count_tmp++; }else if($this->tmp_str!='' && $this->tmp_str!=$termk){ $this->count_tmp++; } } $this->Builderarr['query']['bool']['must'][$this->count_tmp]['range'][$termk]['lte']=$tmp_da_str; if(!isset($this->Builderarr['query']['bool']['must'][$this->count_tmp]['range'][$termk]['time_zone']) && $is_date){ $this->Builderarr['query']['bool']['must'][$this->count_tmp]['range'][$termk]['time_zone']="+08:00"; } } $this->tmp_str=$termk; $this->tmp_lock_str=$lowerstr; $this->tmp_lock=$lowerstr; $this->tmp_lock_range=$lowerstr; $this->tmp_lock_fi=$lowerstr; break; case 'like': if(strrpos($arr[$i-1]['base_expr'],".")){ $term_tmp_arr=explode(".",$arr[$i-1]['base_expr']); $termk=$term_tmp_arr[1]; }else{ $termk=$arr[$i-1]['base_expr']; } $tmp_la_str=str_replace('"','',$arr[$i+1]['base_expr']); $tmp_la_str=str_replace("'","",$tmp_la_str); if(isset($arr[$i+2]['base_expr']) && strtolower($arr[$i+2]['base_expr'])=='or' || isset($arr[$i-2]['base_expr']) && strtolower($arr[$i-2]['base_expr'])=='or'){ if(isset($this->Builderarr['query']['bool']['filter'][0]) && $this->tmp_lock!='' && $this->tmp_lock!=$lowerstr){ if($this->tmp_str_filter==''){ $this->count_tmp_filter++; }else if($this->tmp_str_filter!='' && $this->tmp_str_filter!=$termk){ $this->count_tmp_filter++; } } if(isset($this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]['bool']['must'][0]) && $this->tmp_lock_fi!='' && $this->tmp_lock_fi!=$lowerstr){ if($this->tmp_fi==''){ $this->count_fi++; }else if($this->tmp_fi!='' && $this->tmp_fi!=$termk){ $this->count_fi++; } } if(!is_numeric($arr[$i+1]['base_expr']) && $this->version_es=='8.x'){ $term['match'][$termk.'.keyword']=str_replace("%","",$tmp_la_str); $this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]['bool']['must'][$this->count_fi]['bool']['should'][]=$term; }else{ $term['match'][$termk]=str_replace("%","",$tmp_la_str); $this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]['bool']['must'][$this->count_fi]['bool']['should'][]=$term; } }else{ if(isset($this->Builderarr['query']['bool']['must'][0]) && $this->tmp_lock_str!='' && $this->tmp_lock_str!=$lowerstr){ if($this->tmp_str==''){ $this->count_tmp++; }else if($this->tmp_str!='' && $this->tmp_str!=$termk){ $this->count_tmp++; } } if(!is_numeric($arr[$i+1]['base_expr']) && $this->version_es=='8.x'){ $term['match'][$termk.'.keyword']=str_replace("%","",$tmp_la_str); $this->Builderarr['query']['bool']['must'][$this->count_tmp]['bool']['must'][]=$term; }else{ $term['match'][$termk]=str_replace("%","",$tmp_la_str); $this->Builderarr['query']['bool']['must'][$this->count_tmp]['bool']['must'][]=$term; } } unset($term['match']); $this->tmp_lock_str=$lowerstr; $this->tmp_lock=$lowerstr; $this->tmp_lock_fi=$lowerstr; break; case 'between': if(strrpos($arr[$i-1]['base_expr'],".")){ $term_tmp_arr=explode(".",$arr[$i-1]['base_expr']); $termk=$term_tmp_arr[1]; }else{ $termk=$arr[$i-1]['base_expr']; } if(isset($this->Builderarr['query']['bool']['must'][0]) && $this->tmp_lock_str!='' && $this->tmp_lock_str!=$lowerstr){ if($this->tmp_str==''){ $this->count_tmp++; }else if($this->tmp_str!='' && $this->tmp_str!=$termk){ $this->count_tmp++; } } $tmp_da_str=str_replace('"','',$arr[$i+1]['base_expr']); $tmp_da_str=str_replace("'","",$tmp_da_str); $is_date=strtotime($tmp_da_str)?strtotime($tmp_da_str):false; $this->Builderarr['query']['bool']['must'][$this->count_tmp]['range'][$termk]['gte']=$tmp_da_str; if(!isset($this->Builderarr['query']['bool']['must'][$this->count_tmp]['range'][$termk]['time_zone']) && $is_date){ $this->Builderarr['query']['bool']['must'][$this->count_tmp]['range'][$termk]['time_zone']="+08:00"; } $tmp_da_str=str_replace('"','',$arr[$i+3]['base_expr']); $tmp_da_str=str_replace("'","",$tmp_da_str); $this->Builderarr['query']['bool']['must'][$this->count_tmp]['range'][$termk]['lte']=$tmp_da_str; $this->tmp_str=$termk; $this->tmp_lock_str=$lowerstr; break; } } private function listtree($arr,$aggs,$order){ $countmp=0; for($i=count($arr)-1;$i>=0;$i--){ if(isset($arr[$i-1])){ $key_arr=array_keys($arr[$i]); if($countmp==0){ $arr[$i][$key_arr[0]]['terms']['size']=$this->limit['from']*$this->limit['size']==0?10:($this->limit['from'] + 1 )*$this->limit['size']; if($aggs['aggs']){ $arr[$i][$key_arr[0]]['aggs']=$aggs['aggs']; } if($order){ $arr[$i][$key_arr[0]]['terms']['order']=$order['order']; } $arr[$i][$key_arr[0]]['aggs']['top']['top_hits']['size']=$this->top_hits; $countmp=1; } $key_pre=array_keys($arr[$i-1]); $arr[$i-1][$key_pre[0]]['aggs']=$arr[$i]; unset($arr[$i]); }else{ if(count($arr)==1 && $countmp==0){ $key_arrs=array_keys($arr[$i]); $arr[$i][$key_arrs[0]]['terms']['size']=$this->limit['from']*$this->limit['size']==0?10:($this->limit['from'] + 1 )*$this->limit['size']; $arr[$i][$key_arrs[0]]['aggs']['top']['top_hits']['size']=$this->top_hits; $countmp=1; } } } return $arr; } private function groupby($arr){ $aggs= array(); $agg= array(); $agg_orderby=array(); for($i=0; $i fistgroup) && $this->fistgroup==''){ $this->fistgroup=$termk_tmp.'_group'; } $agg[$i][$termk_tmp.'_group']['terms']['field']=$termk; } if(isset($this->parsed['SELECT']) && !empty($this->parsed['SELECT'])){ foreach ($this->parsed['SELECT'] as $v) { $this->top_hits=1; if(strrpos($v['base_expr'],"*")){ //$this->top_hits=1; }else{ if($v['expr_type']=='aggregate_function'){ $lowerstr = strtolower($v['base_expr']); switch ($lowerstr) { case 'count': if(strrpos($v['sub_tree'][0]['base_expr'],".")){ $term_tmp_arrs=explode(".",$v['sub_tree'][0]['base_expr']); $cardinalitys[$v['alias']['name']]['cardinality']['field']=$term_tmp_arrs[1]; }else{ $cardinalitys[$v['alias']['name']]['cardinality']['field']=$v['sub_tree'][0]['base_expr']; } $tmmp=1; $agggs['aggs']=$cardinalitys; $aggs=array_merge_recursive($aggs, $agggs); unset($cardinalitys); break; case 'sum': if(strrpos($v['sub_tree'][0]['base_expr'],".")){ $term_tmp_arrs=explode(".",$v['sub_tree'][0]['base_expr']); $cardinalitys[$v['alias']['name']]['sum']['field']=$term_tmp_arrs[1]; }else{ $cardinalitys[$v['alias']['name']]['sum']['field']=$v['sub_tree'][0]['base_expr']; } $tmmp=1; $agggs['aggs']=$cardinalitys; $aggs=array_merge_recursive($aggs, $agggs); unset($cardinalitys); break; case 'min': if(strrpos($v['sub_tree'][0]['base_expr'],".")){ $term_tmp_arrs=explode(".",$v['sub_tree'][0]['base_expr']); $cardinalitys[$v['alias']['name']]['min']['field']=$term_tmp_arrs[1]; }else{ $cardinalitys[$v['alias']['name']]['min']['field']=$v['sub_tree'][0]['base_expr']; } $tmmp=1; $agggs['aggs']=$cardinalitys; $aggs=array_merge_recursive($aggs, $agggs); unset($cardinalitys); break; case 'max': if(strrpos($v['sub_tree'][0]['base_expr'],".")){ $term_tmp_arrs=explode(".",$v['sub_tree'][0]['base_expr']); $cardinalitys[$v['alias']['name']]['max']['field']=$term_tmp_arrs[1]; }else{ $cardinalitys[$v['alias']['name']]['max']['field']=$v['sub_tree'][0]['base_expr']; } $tmmp=1; $agggs['aggs']=$cardinalitys; $aggs=array_merge_recursive($aggs, $agggs); unset($cardinalitys); break; case 'avg': if(strrpos($v['sub_tree'][0]['base_expr'],".")){ $term_tmp_arrs=explode(".",$v['sub_tree'][0]['base_expr']); $cardinalitys[$v['alias']['name']]['avg']['field']=$term_tmp_arrs[1]; }else{ $cardinalitys[$v['alias']['name']]['avg']['field']=$v['sub_tree'][0]['base_expr']; } $tmmp=1; $agggs['aggs']=$cardinalitys; $aggs=array_merge_recursive($aggs, $agggs); unset($cardinalitys); break; } if(isset($this->parsed['ORDER']) && !empty($this->parsed['ORDER'])){ foreach ($this->parsed['ORDER'] as $vv) { if($vv['base_expr']==$v['alias']['name']){ $agg_orderby['order'][$vv['base_expr']]=$vv['direction']; } } } } } } if($tmmp==0){ $agg[$j][$termk_tmp.'_group']['terms']['field']=$termk; $agg[$j][$termk_tmp.'_group']['terms']['size']=$this->limit['from']*$this->limit['size']==0?10:($this->limit['from'] + 1 )*$this->limit['size']; $agggs[$j][$termk_tmp.'_group']['aggs']=(object)array(); $aggs[$j]=array_merge_recursive($agg[$j], $agggs[$j]); unset($aggs[$j][$termk_tmp.'_group']['aggs']); } } $this->agg['aggs']=$this->listtree($agg,$aggs,$agg_orderby)[0]; } private function orderby($arr){ if(isset($this->parsed['SELECT']) && !empty($this->parsed['SELECT'])){ foreach ($this->parsed['SELECT'] as $v) { foreach ($arr as $kk=>$vv) { if($v['alias']){ if($v['alias']['name']==$vv['base_expr']){ unset($arr[$kk]); } } } } } foreach ($arr as &$va) { if(strrpos($va['base_expr'],".")){ $term_tmp_arr=explode(".",$va['base_expr']); $termk=$term_tmp_arr[1]; }else{ $termk=$va['base_expr']; } $this->sort['sort'][][$termk]['order']=$va['direction']; } } private function limit($arr){ if(!$arr['offset']){ $this->limit['from']=0; }else{ $this->limit['from']=$arr['offset']; } $this->limit['size']=$arr['rowcount']; } private function select($arr){ if(isset($this->parsed['GROUP']) && !empty($this->parsed['GROUP'])){ }else{ foreach ($arr as $k => $v) { if($v['expr_type']=='aggregate_function'){ if(strrpos($v['sub_tree'][0]['base_expr'],".")){ $term_tmp_arrs=explode(".",$v['sub_tree'][0]['base_expr']); if($term_tmp_arrs[1]=='*'){ continue; } if(isset($v['alias']['name'])){ $this->Builderarr['aggs'][$v['alias']['name']]['stats']['field']=$term_tmp_arrs[1]; }else{ $this->Builderarr['aggs'][$v['sub_tree'][0]['base_expr']]['stats']['field']=$term_tmp_arrs[1]; } }else{ if($v['sub_tree'][0]['base_expr']=='*'){ continue; } if(isset($v['alias']['name'])){ $this->Builderarr['aggs'][$v['alias']['name']]['stats']['field']=$v['sub_tree'][0]['base_expr']; }else{ $this->Builderarr['aggs'][$v['sub_tree'][0]['base_expr']]['stats']['field']=$v['sub_tree'][0]['base_expr']; } } } } } } private function updateset($arr){ foreach ($arr as &$v) { if($v['sub_tree']){ $tmp_sub[$v['sub_tree'][0]['base_expr']]=$v['sub_tree'][2]['base_expr']; $this->Builderarr['doc']=$tmp_sub; unset($tmp_sub); } } } } ?> ================================================ FILE: README.md ================================================ # EsParser php的操作类库,通过写sql来转化dsl来查询elasticsearch ### composer使用 { "require": { "qieangel2013/esparser": "dev-master" } } composer install require __DIR__.'/vendor/autoload.php'; //$sql = 'select * from alp_dish_sales_saas where sid in(994,290) limit 1,10'; //$sql='update alp_dish_sales_saas set mid=3 where adsid=15125110'; //$sql='delete from alp_dish_sales_saas where adsid=15546509'; //$sql="select *,concat_ws('_',category_name.keyword,dish_name.keyword,sku_name.keyword) as dfg from alp_dish_sales_saas where sale_date>'2017-01-01' and sale_date<'2017-09-02' group by dfg order by total_count desc"; //$sql = 'select *,DATE_FORMAT(sale_date,"%Y-%m-%d") as days from alp_dish_sales_saas group by days '; $sql="insert into test(`id`,`name`)values(9,'zz')"; $sql2="insert into test(`id`,`name`)values(9,'zz')"; $es_config=array( 'index' =>"alp_dish_sales_saas", 'type' =>"alp_dish_sales_saas", 'url' =>"http://127.0.0.1:9200", 'version' =>"5.x" //1.x 2.x 5.x 6.x 7.x,可以不配置,系统会请求获取版本,这样会多一次请求,建议配置一下 ); $parser = new EsParser($sql, true,$es_config);//第三个参数是es的配置参数,一定要配置 print_r($parser->build());//打印结果 print_r($parser->setSql($sql2)->build());//打印结果 $result=$parser->scroll();//深度分页初始化会返回第一条 $result=json_decode($result,true); print_r($result);//打印深度分页结果 $result1=$parser->scroll($result['scrollid']);//深度分页下一页 print_r(json_decode($result1,true));//打印深度分页结果 $result2=$parser->scroll($result['scrollid']);//深度分页下一页 print_r(json_decode($result2,true));//打印深度分页结果 $result3=$parser->scroll($result['scrollid']);//深度分页下一页 print_r(json_decode($result3,true));//打印深度分页结果 //print_r($parser->explain());//打印dsl ### 普通调用 require_once dirname(__FILE__) . '/src/library/EsParser.php'; //$sql = 'select * from alp_dish_sales_saas where sid in(994,290) limit 1,10'; //$sql='update alp_dish_sales_saas set mid=3 where adsid=15125110'; //$sql='delete from alp_dish_sales_saas where adsid=15546509'; //$sql="select *,concat_ws('_',category_name.keyword,dish_name.keyword,sku_name.keyword) as dfg from alp_dish_sales_saas where sale_date>'2017-01-01' and sale_date<'2017-09-02' group by dfg order by total_count desc"; //$sql = 'select *,DATE_FORMAT(sale_date,"%Y-%m-%d") as days from alp_dish_sales_saas group by days '; $sql="insert into test(`id`,`name`)values(9,'zz')"; $sql2="insert into test(`id`,`name`)values(9,'zz')"; $es_config=array( 'index' =>"alp_dish_sales_saas", 'type' =>"alp_dish_sales_saas", 'url' =>"http://127.0.0.1:9200", 'version' =>"5.x" //1.x 2.x 5.x 6.x 7.x,可以不配置,系统会请求获取版本,这样会多一次请求,建议配置一下 ); $parser = new EsParser($sql, true,$es_config);//第三个参数是es的配置参数,一定要配置 print_r($parser->build());//打印结果 print_r($parser->setSql($sql2)->build());//打印结果 $result=$parser->scroll();//深度分页初始化会返回第一条 $result=json_decode($result,true); print_r($result);//打印深度分页结果 $result1=$parser->scroll($result['scrollid']);//深度分页下一页 print_r(json_decode($result1,true));//打印深度分页结果 $result2=$parser->scroll($result['scrollid']);//深度分页下一页 print_r(json_decode($result2,true));//打印深度分页结果 $result3=$parser->scroll($result['scrollid']);//深度分页下一页 print_r(json_decode($result3,true));//打印深度分页结果 //print_r($parser->explain()); //打印dsl ### 目前支持的sql函数 * SQL Insert * SQL Select * SQL Delete * SQL Update * SQL Where * SQL Order By * SQL Group By * SQL AND * SQL OR (多重or如:((a=1 and b=2) or (c=3 and d=4)) and e=5) * SQL Like * SQL Not Like * SQL Is NULL * SQL Is Not NULL * SQL COUNT distinct * SQL In * SQL Not In * SQL = * SQL != * SQL <> * SQL avg() * SQL count() * SQL max() * SQL min() * SQL sum() * SQL Between * SQL Aliases * SQL concat_ws * SQL DATE_FORMATE * SQL Having ### 使用注意事项 请在配置项填写es的版本,这样系统不会请求获取版本,这样不会多一次请求,建议配置一下 ### 交流使用 qq群:578276199 ### 项目地址 github:https://github.com/qieangel2013/EsParser oschina:https://gitee.com/qieangel2013/EsParser ### 如果你对我的辛勤劳动给予肯定,请给我捐赠,你的捐赠是我最大的动力 ![](https://github.com/qieangel2013/zys/blob/master/public/images/pw.jpg) ![](https://github.com/qieangel2013/zys/blob/master/public/images/pay.png) [项目捐赠列表](https://github.com/qieangel2013/zys/wiki/%E9%A1%B9%E7%9B%AE%E6%8D%90%E8%B5%A0) ================================================ FILE: composer.json ================================================ { "name": "qieangel2013/esparser", "description": "es php library", "type": "library", "keywords": ["sql","elasticsearch","restful"], "license": "MIT", "authors": [ { "name": "qieangel2013", "email": "904208360@qq.com" } ], "require": { "php": ">=5.3" }, "classmap" : ["src/library/"], "minimum-stability": "dev" } ================================================ FILE: index.php ================================================ =10 and a.d<20 and a.h>56 and a.f in(1,2,3,4,5) group by a.name order by a.id desc limit 10'; //$sql='select a.*,count(a.id) as sid,a.total_price,sum(a.total) as count_total from table1 group by a.total_price order by count_total,a.co'; //$sql = 'select * from alp_dish_sales_saas where sid in(994,290) limit 0,10'; $sql='select category_name cate_name,dish_name,dishsno,sale_date,sum(total_price) total_price,sum(total_count) total_count,category_name,sku_name properties from alp_dish_sales_saas where sale_date>="2017-01-01" and sale_date<="2017-09-03" and sid in(994,290) limit 3,10'; //$sql='update alp_dish_sales_saas set mid=3 where adsid=15125110'; //$sql='delete from alp_dish_sales_saas where adsid=15546509'; $es_config=array( 'index' =>"alp_dish_sales_saas", 'type' =>"alp_dish_sales_saas", 'url' =>"http://127.0.0.1:9200", 'version' =>"5.x" //1.x 2.x 5.x 6.x,可以不配置,系统会请求获取版本,这样会多一次请求 ); $parser = new EsParser($sql, true,$es_config);//第三个参数是es的配置参数,一定要配置 print_r($parser->build());//打印结果 $result=$parser->scroll();//深度分页初始化会返回第一条 $result=json_decode($result,true); print_r($result);//打印深度分页结果 $result1=$parser->scroll($result['scrollid']);//深度分页下一页 print_r(json_decode($result1,true));//打印深度分页结果 $result2=$parser->scroll($result['scrollid']);//深度分页下一页 print_r(json_decode($result2,true));//打印深度分页结果 $result3=$parser->scroll($result['scrollid']);//深度分页下一页 print_r(json_decode($result3,true));//打印深度分页结果 //print_r($parser->explain()); //打印dsl ================================================ FILE: src/example.php ================================================ =10 and a.d<20 and a.h>56 and a.f in(1,2,3,4,5) group by a.name order by a.id desc limit 10'; //$sql='select a.*,count(a.id) as sid,a.total_price,sum(a.total) as count_total from table1 group by a.total_price order by count_total,a.co'; //$sql = 'select * from alp_dish_sales_saas where sid in(994,290) limit 0,10'; $sql='select category_name cate_name,dish_name,dishsno,sale_date,sum(total_price) total_price,sum(total_count) total_count,category_name,sku_name properties from alp_dish_sales_saas where sale_date>="2017-01-01" and sale_date<="2017-09-03" and sid in(994,290) limit 3,10'; //$sql='update alp_dish_sales_saas set mid=3 where adsid=15125110'; //$sql='delete from alp_dish_sales_saas where adsid=15546509'; $es_config=array( 'index' =>"alp_dish_sales_saas", 'type' =>"alp_dish_sales_saas", 'url' =>"http://127.0.0.1:9200", 'version' =>"5.x" //1.x 2.x 5.x 6.x,可以不配置,系统会请求获取版本,这样会多一次请求 ); $parser = new EsParser($sql, true,$es_config);//第三个参数是es的配置参数,一定要配置 print_r($parser->build());//打印结果 $result=$parser->scroll();//深度分页初始化会返回第一条 $result=json_decode($result,true); print_r($result);//打印深度分页结果 $result1=$parser->scroll($result['scrollid']);//深度分页下一页 print_r(json_decode($result1,true));//打印深度分页结果 $result2=$parser->scroll($result['scrollid']);//深度分页下一页 print_r(json_decode($result2,true));//打印深度分页结果 $result3=$parser->scroll($result['scrollid']);//深度分页下一页 print_r(json_decode($result3,true));//打印深度分页结果 //print_r($parser->explain()); //打印dsl ================================================ FILE: src/library/EsCreator.php ================================================ * @copyright 2010-2014 André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * @version SVN: $Id: PHPSQLCreator.php 790 2013-12-17 12:16:48Z phosco@gmx.de $ * */ require_once dirname(__FILE__) . '/exceptions/UnsupportedFeatureException.php'; require_once dirname(__FILE__) . '/builders/SelectStatementBuilder.php'; require_once dirname(__FILE__) . '/builders/DeleteStatementBuilder.php'; require_once dirname(__FILE__) . '/builders/UpdateStatementBuilder.php'; require_once dirname(__FILE__) . '/builders/InsertStatementBuilder.php'; require_once dirname(__FILE__) . '/builders/CreateStatementBuilder.php'; require_once dirname(__FILE__) . '/builders/ShowStatementBuilder.php'; /** * This class generates SQL from the output of the PHPSQLParser. * * @author André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ class PHPSQLCreator { public function __construct($parsed = false) { if ($parsed) { $this->create($parsed); } } public function create($parsed) { $k = key($parsed); switch ($k) { case "UNION": case "UNION ALL": throw new UnsupportedFeatureException($k); break; case "SELECT": $builder = new SelectStatementBuilder($parsed); $this->created = $builder->build($parsed); break; case "INSERT": $builder = new InsertStatementBuilder($parsed); $this->created = $builder->build($parsed); break; case "DELETE": $builder = new DeleteStatementBuilder($parsed); $this->created = $builder->build($parsed); break; case "UPDATE": $builder = new UpdateStatementBuilder($parsed); $this->created = $builder->build($parsed); break; case "RENAME": $this->created = $this->processRenameTableStatement($parsed); break; case "SHOW": $builder = new ShowStatementBuilder($parsed); $this->created = $builder->build($parsed); break; case "CREATE": $builder = new CreateStatementBuilder($parsed); $this->created = $builder->build($parsed); break; default: throw new UnsupportedFeatureException($k); break; } return $this->created; } // TODO: we should change that, there are multiple "rename objects" as // table, user, database protected function processRenameTableStatement($parsed) { $rename = $parsed['RENAME']; $sql = ""; foreach ($rename as $k => $v) { $len = strlen($sql); $sql .= $this->processSourceAndDestTable($v); if ($len == strlen($sql)) { throw new UnableToCreateSQLException('RENAME', $k, $v, 'expr_type'); } $sql .= ","; } $sql = substr($sql, 0, -1); return "RENAME TABLE " . $sql; } protected function processSourceAndDestTable($v) { if (!isset($v['source']) || !isset($v['destination'])) { return ""; } return $v['source']['base_expr'] . " TO " . $v['destination']['base_expr']; } } ?> ================================================ FILE: src/library/EsParser.php ================================================ 1, 'message'=>'es的配置项不能为空!' ); $this->result=json_encode($config_err,true); return $this->result; }else{ $this->index_es=$es_config['index']; $this->type_es=$es_config['type']; $this->url=$es_config['url']; $this->scrollurl=$es_config['url']; $this->basescrollurl=$es_config['url']; if(!isset($es_config['version'])){ $version=$this->getEsData($es_config['url']); if($version){ if(version_compare($version,'5.0.0', '<')){ $this->version_es='2.x'; }else if( version_compare($version,'5.0.0', '>=') && version_compare($version,'6.0.0', '<')){ $this->version_es='5.x'; }else if( version_compare($version,'6.0.0', '>=') && version_compare($version,'7.0.0', '<')){ $this->version_es='6.x'; } else { $this->version_es='7.x'; } }else{ $this->version_es='5.x'; } }else{ if(trim($es_config['version'])==''){ $this->version_es='5.x'; }else{ $this->version_es=$es_config['version']; } } } if ($sql) { $this->parse($sql, $calcPositions); } } /** * * @param String $sql The SQL statement. * @param boolean $calcPositions True, if the output should contain [position], false otherwise. * * @return array An associative array with all meta information about the SQL statement. */ public function parsesql($sql, $calcPositions = false) { $processor = new DefaultProcessor(); $queries = $processor->process($sql); if ($calcPositions) { $calculator = new PositionCalculator(); $queries = $calculator->setPositionsWithinSQL($sql, $queries); } $this->parsed = $queries; return $this->parsed; } public function setSql($sql, $calcPositions = false) { $this->Builderarr = []; $this->url = $this->basescrollurl; return $this->parse($sql, $calcPositions); } public function parse($sql, $calcPositions = false) { $processor = new DefaultProcessor(); $queries = $processor->process($sql); if ($calcPositions) { $calculator = new PositionCalculator(); $queries = $calculator->setPositionsWithinSQL($sql, $queries); } $this->parsed = $queries; return $this->EsBuilder(); //return $this->parsed; } private function EsBuilder(){ //table if(isset($this->parsed['FROM']) && !empty($this->parsed['FROM'])){ $this->table($this->parsed['FROM']); } //insert if(isset($this->parsed['INSERT']) && !empty($this->parsed['INSERT'])){ $this->insert($this->parsed['INSERT']); } //update if(isset($this->parsed['UPDATE']) && !empty($this->parsed['UPDATE'])){ $this->update($this->parsed['UPDATE']); } //set if(isset($this->parsed['SET']) && !empty($this->parsed['SET'])){ $this->updateset($this->parsed['SET']); } //delete if(isset($this->parsed['DELETE']) && !empty($this->parsed['DELETE'])){ $this->delete($this->parsed['DELETE']); } //limit if(isset($this->parsed['LIMIT']) && !empty($this->parsed['LIMIT'])){ $this->limit($this->parsed['LIMIT']); if(isset($this->parsed['GROUP']) && !empty($this->parsed['GROUP'])){ $this->Builderarr['size']=0; $this->limit($this->parsed['LIMIT']); }else{ $this->Builderarr['from']=$this->limit['from'] * $this->limit['size']; $this->Builderarr['size']=$this->limit['size']; } }else{ $this->limit(array()); } //having if(isset($this->parsed['HAVING']) && !empty($this->parsed['HAVING'])){ $this->having($this->parsed['HAVING']); } //where if(isset($this->parsed['WHERE']) && !empty($this->parsed['WHERE'])){ $this->where($this->parsed['WHERE']); } //groupby if(isset($this->parsed['GROUP']) && !empty($this->parsed['GROUP'])){ $this->groupby($this->parsed['GROUP']); if(!empty($this->agg['aggs'])){ $this->Builderarr['aggs']=$this->agg['aggs']; } } //orderby if(isset($this->parsed['ORDER']) && !empty($this->parsed['ORDER'])){ $this->orderby($this->parsed['ORDER']); if(!empty($this->sort['sort'])){ $this->Builderarr['sort']=$this->sort['sort']; } } //select if(isset($this->parsed['SELECT']) && !empty($this->parsed['SELECT'])){ $this->select($this->parsed['SELECT']); } if(!isset($this->Builderarr) && empty($this->Builderarr)){ $this->Builderarr['query']['match_all']=(object)array(); } return $this; } public function build(){ //request return $this->PostEs($this->Builderarr); } public function explain(){ $this->explain=json_encode($this->Builderarr,true); return $this->explain; } public function scroll($scrollid=''){ $this->isscroll=1; if($scrollid){ $this->scrollurl=$this->basescrollurl; $this->scrollurl .="/_search/scroll?pretty"; $this->Builderarr=array(); $this->Builderarr['scroll']=$this->scrolltime; $this->Builderarr['scroll_id']=$scrollid; }else{ $this->scrollurl .="/".$this->index_es."/".$this->type_es."/_search?pretty&scroll=".$this->scrolltime; } $this->url=$this->scrollurl; return $this->PostEs($this->Builderarr); } private function table($arr){ if(isset($this->parsed['DELETE']) && !empty($this->parsed['DELETE'])){ foreach ($arr as $v) { if($v['table']){ if ($this->version_es == '7.x'){ $this->url .="/".$this->index_es."/_delete_by_query?pretty"; }else { $this->url .="/".$this->index_es."/".$this->type_es."/_delete_by_query?pretty"; } } } }else{ foreach ($arr as $v) { if($v['table']){ if ($this->version_es == '7.x'){ $this->url .="/".$this->index_es."/_search?pretty"; } else { $this->url .="/".$this->index_es."/".$this->type_es."/_search?pretty"; } } } } } private function insert($arr){ if ($this->version_es == '7.x'){ $this->url .="/".$this->index_es."?pretty"; }else { $this->url .="/".$this->index_es."/".$this->type_es."?pretty"; } foreach ($arr as $k=>$v) { if(count($v['columns'])>0){ $this->Builderarr=$this->resdata($v['columns'],$this->parsed['VALUES'][$k]['data']); } } } private function resdata($data,$value){ foreach ($data as $v) { if($v['base_expr']){ $fielddata=str_replace('`','',$v['base_expr']); $fieldarr[]=$fielddata; } } foreach ($value as $vv) { if(strlen($vv['base_expr'])){ $fielddata=str_replace("'",'',$vv['base_expr']); $fielddata=str_replace('"','',$fielddata); $valuearr[]=$fielddata; } } return array_combine($fieldarr,$valuearr); } private function update($arr){ foreach ($arr as $v) { if($v['table']){ $this->table=$v['table']; $this->url .="/".$this->index_es."/".$this->type_es."/"; } } } private function delete($arr){ } private function getEsData($url){ $ch = curl_init($url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1) ; curl_setopt($ch, CURLOPT_TIMEOUT, 60); curl_setopt($ch, CURLOPT_HEADER, 0); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_SSLVERSION, 3); curl_setopt($ch, CURLOPT_BINARYTRANSFER, true) ; $output = curl_exec($ch); if($output === false) //超时处理 { if(curl_errno($ch) == CURLE_OPERATION_TIMEDOUT) { my_file_put_contents("getEsData.txt", "时间:".date('Ymd-H:i:s',time())."\r\n错误内容为:curl通过get方式请求{$url}的连接超时\r\n"); } } curl_close($ch); $output=json_decode($output,true); if (empty($output)) { return array(); } return $output['version']['number']; } private function PostEs($postdata,$json=true,$token=false){ $url=$this->url; $datastring = json_encode($postdata,true); $ch = curl_init($url); curl_setopt($ch, CURLOPT_URL, $url) ; curl_setopt($ch, CURLOPT_POST, 1) ; curl_setopt($ch, CURLOPT_HEADER, 0); curl_setopt($ch, CURLINFO_HEADER_OUT, true); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_TIMEOUT, 60); //只需要设置一个秒的数量就可以 curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_SSLVERSION, 3); curl_setopt($ch, CURLOPT_POSTFIELDS, $datastring); if ($json) { curl_setopt($ch, CURLOPT_HTTPHEADER, array( 'Content-Type: application/json;', 'Content-Length: ' . strlen($datastring)) ); } if ($token) { curl_setopt( $ch, CURLOPT_HTTPHEADER, array( 'Content-Type: application/json; charset=utf-8', 'Content-Length: ' . strlen($datastring), 'Authorization:'.$token ) ); } $output=curl_exec($ch); if($output === false) //超时处理 { if(curl_errno($ch) == CURLE_OPERATION_TIMEDOUT) { file_put_contents("getEsData.txt", "时间:".date('Ymd-H:i:s',time())."\r\n错误内容为:curl通过post方式请求{$this->url}的连接超时\r\n"); } } curl_close($ch); $output=json_decode($output,true); if (empty($output)) { $this->result=json_encode(array(),true); } if(isset($output['error'])){ $this->result=json_encode($output,true); }else if(isset($this->parsed['UPDATE']) && !empty($this->parsed['UPDATE'])){ $update_arr=$output['_shards']; unset($update_arr['total']); $this->result=json_encode($update_arr,true); }else if(isset($this->parsed['DELETE']) && !empty($this->parsed['DELETE'])){ $delete_arr['total']=$output['total']; $delete_arr['deleted']=$output['deleted']; $delete_arr['successfull']=$output['deleted']; $this->result=json_encode($delete_arr,true); }else if(isset($this->parsed['INSERT']) && !empty($this->parsed['INSERT'])){ $this->result=json_encode($output,true); }else{ if ($this->version_es == '7.x'){ $total_str=$output['hits']['total']['value']; }else { $total_str=$output['hits']['total']; } if(isset($this->parsed['GROUP']) && !empty($this->parsed['GROUP'])){ if($output['hits']['hits'] && empty($output['aggregations'][$this->fistgroup]['buckets'])){ $tmp_counter=count($output['hits']['hits']); $counter=($this->limit['from'] + 1 )*$this->limit['size']; if($tmp_counter<$counter){ $page=ceil($tmp_counter/$this->limit['size']); $outputs['page']=$page==0?1:$page; $outputs['result']=array_slice($output['hits']['hits'],($page-1)*$this->limit['size'],$tmp_counter-(($page-1)*$this->limit['size'])); }else if($tmp_counter==$counter){ $outputs['page']=$this->limit['from']+1; $outputs['result']=array_slice($output['hits']['hits'],-$this->limit['size']); }else{ $page=$this->limit['from']+1; $outputs['page']=$page==0?1:$page; $outputs['result']=array_slice($output['hits']['hits'],($page-1)*$this->limit['size'],$this->limit['size']); } }else if(isset($output['aggregations'][$this->fistgroup]['buckets']) && !empty($output['aggregations'][$this->fistgroup]['buckets'])){ $tmp_counter=count($output['aggregations'][$this->fistgroup]['buckets']); $counter=($this->limit['from'] + 1 )*$this->limit['size']; if($tmp_counter<$counter){ $page=ceil($tmp_counter/$this->limit['size']); $outputs['page']=$page==0?1:$page; $outputs['result'][$this->fistgroup]['buckets']=array_slice($output['aggregations'][$this->fistgroup]['buckets'],($page-1)*$this->limit['size'],$tmp_counter-(($page-1)*$this->limit['size'])); }else if($tmp_counter==$counter){ $outputs['page']=$this->limit['from']+1; $outputs['result'][$this->fistgroup]['buckets']=array_slice($output['aggregations'][$this->fistgroup]['buckets'],-$this->limit['size']); }else{ $page=$this->limit['from']+1; $outputs['page']=$page==0?1:$page; $outputs['result'][$this->fistgroup]['buckets']=array_slice($output['aggregations'][$this->fistgroup]['buckets'],($page-1)*$this->limit['size'],$this->limit['size']); } }else{ $tmp_counter=count($output['aggregations'][$this->fistgroup]['buckets']); $counter=($this->limit['from'] + 1 )*$this->limit['size']; if($tmp_counter<$counter){ $page=ceil($tmp_counter/$this->limit['size']); $outputs['page']=$page==0?1:$page; $outputs['result']=array_slice($output['aggregations'][$this->fistgroup]['buckets'],($page-1)*$this->limit['size'],$tmp_counter-(($page-1)*$this->limit['size'])); }else if($tmp_counter==$counter){ $outputs['page']=$this->limit['from']+1; $outputs['result']=array_slice($output['aggregations'][$this->fistgroup]['buckets'],-$this->limit['size']); } } }else{ if(isset($output['aggregations']) && !empty($output['aggregations'])){ $outputs['result']=$output['aggregations']; }else{ $page_tmp=ceil($total_str/$this->limit['size']); $page=$this->limit['from'] + 1 ; if($page_tmp>=$page){ }else{ $page=$page_tmp; if($page_tmp!=0){ $this->Builderarr['from']=($page_tmp-1) * $this->limit['size']+1; }else{ $this->Builderarr['from']=0; } $this->Builderarr['size']=$this->limit['size']; } $outputs['page']=$page==0?1:$page; $outputs['result']=$output['hits']['hits']; } } $outputs['total']=$total_str; if($this->isscroll && isset($output['_scroll_id'])){ $outputs['scrollid']=$output['_scroll_id']; } $this->result=json_encode($outputs,true); } return $this->result; } private function where($arr){ for($i=0;$i1){ if(isset($arr[$i]['sub_tree'][0]['expr_type']) && $arr[$i]['sub_tree'][0]['expr_type']=='bracket_expression'){ for($jj=0;$jjwhereor($arr[$i]['sub_tree'],$jj); } }else{ $tmp_arr=$arr[$i]['sub_tree']; for($j=0;$jwhereext($tmp_arr,$j); } } }else{ if(isset($arr[$i]['sub_tree'][0]['expr_type']) && $arr[$i]['sub_tree'][0]['expr_type']=='bracket_expression'){ $tmp_arr=$arr[$i]['sub_tree'][0]['sub_tree']; }else{ $tmp_arr=$arr[$i]['sub_tree']; } for($j=0;$jwhereext($tmp_arr,$j); } } } }else{ $this->whereext($arr,$i); } } } private function whereorext($arr){ $tmp_or=array(); for($i=0;$iversion_es=='8.x'){ $term['match_phrase'][$termk.'.keyword']['query']=$tmp_da_str; $tmp_or['bool']['must'][]=$term; }else{ $term['match_phrase'][$termk]['query']=$tmp_da_str; $tmp_or['bool']['must'][]=$term; } }else{ if(strrpos($arr[$i-1]['base_expr'],".")){ $term_tmp_arr=explode(".",$arr[$i-1]['base_expr']); if($term_tmp_arr[1]!='keyword'){ $termk=$term_tmp_arr[1]; }else{ $termk=$arr[$i-1]['base_expr']; } }else{ $termk=$arr[$i-1]['base_expr']; } $tmp_da_str=str_replace('"','',$arr[$i+1]['base_expr']); $tmp_da_str=str_replace("'","",$tmp_da_str); if(!is_numeric($arr[$i+1]['base_expr']) && $this->version_es=='8.x'){ $term['match_phrase'][$termk.'.keyword']['query']=$tmp_da_str; $tmp_or['bool']['must'][]=$term; }else{ $term['match_phrase'][$termk]['query']=$tmp_da_str; $tmp_or['bool']['must'][]=$term; } } break; case '!=': if($arr[$i-1]['base_expr']==$arr[$i+1]['base_expr']){ break; } if(isset($arr[$i+2]['base_expr']) && strtolower($arr[$i+2]['base_expr'])=='and' || isset($arr[$i-2]['base_expr']) && strtolower($arr[$i-2]['base_expr'])=='and'){ if(strrpos($arr[$i-1]['base_expr'],".")){ $term_tmp_arr=explode(".",$arr[$i-1]['base_expr']); if($term_tmp_arr[1]!='keyword'){ $termk=$term_tmp_arr[1]; }else{ $termk=$arr[$i-1]['base_expr']; } }else{ $termk=$arr[$i-1]['base_expr']; } $tmp_da_str=str_replace('"','',$arr[$i+1]['base_expr']); $tmp_da_str=str_replace("'","",$tmp_da_str); if(!is_numeric($arr[$i+1]['base_expr']) && $this->version_es=='8.x'){ $term['match_phrase'][$termk.'.keyword']['query']=$tmp_da_str; $tmp_or['bool']['must_not'][]=$term; }else{ $term['match_phrase'][$termk]['query']=$tmp_da_str; $tmp_or['bool']['must_not'][]=$term; } }else{ if(strrpos($arr[$i-1]['base_expr'],".")){ $term_tmp_arr=explode(".",$arr[$i-1]['base_expr']); if($term_tmp_arr[1]!='keyword'){ $termk=$term_tmp_arr[1]; }else{ $termk=$arr[$i-1]['base_expr']; } }else{ $termk=$arr[$i-1]['base_expr']; } $tmp_da_str=str_replace('"','',$arr[$i+1]['base_expr']); $tmp_da_str=str_replace("'","",$tmp_da_str); if(!is_numeric($arr[$i+1]['base_expr']) && $this->version_es=='8.x'){ $term['match_phrase'][$termk.'.keyword']['query']=$tmp_da_str; $tmp_or['bool']['must_not'][]=$term; }else{ $term['match_phrase'][$termk]['query']=$tmp_da_str; $tmp_or['bool']['must_not'][]=$term; } } break; case '<>': if($arr[$i-1]['base_expr']==$arr[$i+1]['base_expr']){ break; } if(isset($arr[$i+2]['base_expr']) && strtolower($arr[$i+2]['base_expr'])=='and' || isset($arr[$i-2]['base_expr']) && strtolower($arr[$i-2]['base_expr'])=='and'){ if(strrpos($arr[$i-1]['base_expr'],".")){ $term_tmp_arr=explode(".",$arr[$i-1]['base_expr']); if($term_tmp_arr[1]!='keyword'){ $termk=$term_tmp_arr[1]; }else{ $termk=$arr[$i-1]['base_expr']; } }else{ $termk=$arr[$i-1]['base_expr']; } $tmp_da_str=str_replace('"','',$arr[$i+1]['base_expr']); $tmp_da_str=str_replace("'","",$tmp_da_str); if(!is_numeric($arr[$i+1]['base_expr']) && $this->version_es=='8.x'){ $term['match_phrase'][$termk.'.keyword']['query']=$tmp_da_str; $tmp_or['bool']['must_not'][]=$term; }else{ $term['match_phrase'][$termk]['query']=$tmp_da_str; $tmp_or['bool']['must_not'][]=$term; } }else{ if(strrpos($arr[$i-1]['base_expr'],".")){ $term_tmp_arr=explode(".",$arr[$i-1]['base_expr']); if($term_tmp_arr[1]!='keyword'){ $termk=$term_tmp_arr[1]; }else{ $termk=$arr[$i-1]['base_expr']; } }else{ $termk=$arr[$i-1]['base_expr']; } $tmp_da_str=str_replace('"','',$arr[$i+1]['base_expr']); $tmp_da_str=str_replace("'","",$tmp_da_str); if(!is_numeric($arr[$i+1]['base_expr']) && $this->version_es=='8.x'){ $term['match_phrase'][$termk.'.keyword']['query']=$tmp_da_str; $tmp_or['bool']['must_not'][]=$term; }else{ $term['match_phrase'][$termk]['query']=$tmp_da_str; $tmp_or['bool']['must_not'][]=$term; } } break; case 'in': if(strtolower($arr[$i-1]['base_expr'])=='not'){ break; } if(strrpos($arr[$i-1]['base_expr'],".")){ $term_tmp_arr=explode(".",$arr[$i-1]['base_expr']); if($term_tmp_arr[1]!='keyword'){ $termk=$term_tmp_arr[1]; }else{ $termk=$arr[$i-1]['base_expr']; } }else{ $termk=$arr[$i-1]['base_expr']; } if(isset($arr[$i+1]['sub_tree']) && !empty($arr[$i+1]['sub_tree'])){ foreach ($arr[$i+1]['sub_tree'] as &$vv) { if(!is_numeric($vv['base_expr']) && $this->version_es=='8.x'){ $termk .='.keyword'; } $tmp_da_str=str_replace('"','',$vv['base_expr']); $tmp_da_str=str_replace("'","",$tmp_da_str); $tmp_or['terms'][$termk][]=$tmp_da_str; } } break; case 'not': if(strrpos($arr[$i-1]['base_expr'],".")){ $term_tmp_arr=explode(".",$arr[$i-1]['base_expr']); if($term_tmp_arr[1]!='keyword'){ if($term_tmp_arr[1]!='keyword'){ $termk=$term_tmp_arr[1]; }else{ $termk=$arr[$i-1]['base_expr']; } }else{ $termk=$arr[$i-1]['base_expr']; } }else{ $termk=$arr[$i-1]['base_expr']; } switch (strtolower($arr[$i+1]['base_expr'])) { case 'in': if(isset($arr[$i+2]['sub_tree']) && !empty($arr[$i+2]['sub_tree'])){ foreach ($arr[$i+2]['sub_tree'] as &$vv) { if(!is_numeric($vv['base_expr']) && $this->version_es=='8.x'){ $termk .='.keyword'; } $tmp_da_str=str_replace('"','',$vv['base_expr']); $tmp_da_str=str_replace("'","",$tmp_da_str); $tmp_or['bool']['must_not']['terms'][$termk][]=$tmp_da_str; } } break; case 'like': $tmp_la_str=str_replace('"','',$arr[$i+2]['base_expr']); $tmp_la_str=str_replace("'","",$tmp_la_str); if(!is_numeric($arr[$i+2]['base_expr']) && $this->version_es=='8.x'){ //$term['match_phrase'][$termk.'.keyword']=str_replace("%","",$tmp_la_str); $term['wildcard'][$termk.'.keyword']=str_replace("%","*",$tmp_la_str); $tmp_or['bool']['must_not'][]=$term; }else{ //$term['match_phrase'][$termk]=str_replace("%","",$tmp_la_str); $term['wildcard'][$termk]=str_replace("%","*",$tmp_la_str); $tmp_or['bool']['must_not'][]=$term; } break; case 'null': $tmp_or['exists']['field']=$arr[$i-2]['base_expr']; break; } break; case 'is': if($arr[$i-1]['base_expr']==$arr[$i+1]['base_expr']){ break; } if(strtolower($arr[$i+1]['base_expr'])=='not'){ break; } $tmp_or['bool']['must_not'][]['exists']['field']=$arr[$i-1]['base_expr']; break; case '>': if(strrpos($arr[$i-1]['base_expr'],".")){ $term_tmp_arr=explode(".",$arr[$i-1]['base_expr']); if($term_tmp_arr[1]!='keyword'){ $termk=$term_tmp_arr[1]; }else{ $termk=$arr[$i-1]['base_expr']; } }else{ $termk=$arr[$i-1]['base_expr']; } $tmp_da_str=str_replace('"','',$arr[$i+1]['base_expr']); $tmp_da_str=str_replace("'","",$tmp_da_str); $is_date=strtotime($tmp_da_str)?strtotime($tmp_da_str):false; $tmp_or['range'][$termk]['gt']=$tmp_da_str; if(!isset($tmp_or['range'][$termk]['time_zone']) && $is_date){ $tmp_or['range'][$termk]['time_zone']="+08:00"; } break; case '>=': if(strrpos($arr[$i-1]['base_expr'],".")){ $term_tmp_arr=explode(".",$arr[$i-1]['base_expr']); if($term_tmp_arr[1]!='keyword'){ $termk=$term_tmp_arr[1]; }else{ $termk=$arr[$i-1]['base_expr']; } }else{ $termk=$arr[$i-1]['base_expr']; } $tmp_da_str=str_replace('"','',$arr[$i+1]['base_expr']); $tmp_da_str=str_replace("'","",$tmp_da_str); $is_date=strtotime($tmp_da_str)?strtotime($tmp_da_str):false; $tmp_or['range'][$termk]['gte']=$tmp_da_str; if(!isset($tmp_or['range'][$termk]['time_zone']) && $is_date){ $tmp_or['range'][$termk]['time_zone']="+08:00"; } break; case '<': if(strrpos($arr[$i-1]['base_expr'],".")){ $term_tmp_arr=explode(".",$arr[$i-1]['base_expr']); if($term_tmp_arr[1]!='keyword'){ $termk=$term_tmp_arr[1]; }else{ $termk=$arr[$i-1]['base_expr']; } }else{ $termk=$arr[$i-1]['base_expr']; } $tmp_da_str=str_replace('"','',$arr[$i+1]['base_expr']); $tmp_da_str=str_replace("'","",$tmp_da_str); $is_date=strtotime($tmp_da_str)?strtotime($tmp_da_str):false; $tmp_or['range'][$termk]['lt']=$tmp_da_str; if(!isset($tmp_or['range'][$termk]['time_zone']) && $is_date){ $tmp_or['range'][$termk]['time_zone']="+08:00"; } break; case '<=': if(strrpos($arr[$i-1]['base_expr'],".")){ $term_tmp_arr=explode(".",$arr[$i-1]['base_expr']); if($term_tmp_arr[1]!='keyword'){ $termk=$term_tmp_arr[1]; }else{ $termk=$arr[$i-1]['base_expr']; } }else{ $termk=$arr[$i-1]['base_expr']; } $tmp_da_str=str_replace('"','',$arr[$i+1]['base_expr']); $tmp_da_str=str_replace("'","",$tmp_da_str); $is_date=strtotime($tmp_da_str)?strtotime($tmp_da_str):false; $tmp_or['range'][$termk]['lte']=$tmp_da_str; if(!isset($tmp_or['range'][$termk]['time_zone']) && $is_date){ $tmp_or['range'][$termk]['time_zone']="+08:00"; } break; case 'like': if(strtolower($arr[$i-1]['base_expr'])=='not'){ break; } if(strrpos($arr[$i-1]['base_expr'],".")){ $term_tmp_arr=explode(".",$arr[$i-1]['base_expr']); if($term_tmp_arr[1]!='keyword'){ $termk=$term_tmp_arr[1]; }else{ $termk=$arr[$i-1]['base_expr']; } }else{ $termk=$arr[$i-1]['base_expr']; } $tmp_la_str=str_replace('"','',$arr[$i+1]['base_expr']); $tmp_la_str=str_replace("'","",$tmp_la_str); if(!is_numeric($arr[$i+1]['base_expr']) && $this->version_es=='8.x'){ //$term['match_phrase'][$termk.'.keyword']=str_replace("%","",$tmp_la_str); $term['wildcard'][$termk.'.keyword']=str_replace("%","*",$tmp_la_str); $tmp_or['bool']['must'][]=$term; }else{ //$term['match_phrase'][$termk]=str_replace("%","",$tmp_la_str); $term['wildcard'][$termk]=str_replace("%","*",$tmp_la_str); $tmp_or['bool']['must'][]=$term; } break; case 'between': if(strrpos($arr[$i-1]['base_expr'],".")){ $term_tmp_arr=explode(".",$arr[$i-1]['base_expr']); if($term_tmp_arr[1]!='keyword'){ $termk=$term_tmp_arr[1]; }else{ $termk=$arr[$i-1]['base_expr']; } }else{ $termk=$arr[$i-1]['base_expr']; } $tmp_da_str=str_replace('"','',$arr[$i+1]['base_expr']); $tmp_da_str=str_replace("'","",$tmp_da_str); $is_date=strtotime($tmp_da_str)?strtotime($tmp_da_str):false; $tmp_or['range'][$termk]['gte']=$tmp_da_str; if(!isset($tmp_or['range'][$termk]['time_zone']) && $is_date){ $tmp_or['range'][$termk]['time_zone']="+08:00"; } $tmp_da_str=str_replace('"','',$arr[$i+3]['base_expr']); $tmp_da_str=str_replace("'","",$tmp_da_str); $tmp_or['range'][$termk]['lte']=$tmp_da_str; break; } } return $tmp_or; } private function whereorink($arr,$i){ $tmparrs=$arr; if(isset($tmparrs[$i]['base_expr']) && strtolower($tmparrs[$i]['base_expr'])!='or'){ $this->arrtmp[]=$arr[$i]; $i=$i+1; $this->whereorink($tmparrs,$i); } return $this->arrtmp; } private function whereor($arr,$i){ if(!is_numeric($arr[$i]['base_expr'])){ $lowerstr = strtolower($arr[$i]['base_expr']); }else{ $lowerstr = $arr[$i]['base_expr']; } switch ($lowerstr) { case 'or': if(isset($this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]) && $this->tmp_lock!='' && $this->tmp_lock!=$lowerstr){ if($this->tmp_str_filter=='' && !$this->tmp_or){ $this->count_tmp_filter++; } }else if($this->tmp_str!='' && $this->tmp_str!=$termk){ $this->count_tmp_filter++; } if(isset($this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]['bool']['must'][0]) && $this->tmp_lock_str!='' && $this->tmp_lock_str!=$lowerstr){ if($this->tmp_str==''){ $this->count_tmp++; } } if(!isset($arr[$i-2])){ $this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]['bool']['must'][0]['bool']['should'][]=$this->whereorext($arr[$i-1]['sub_tree']); } if($arr[$i+1]['expr_type']=='bracket_expression'){ $this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]['bool']['must'][0]['bool']['should'][]=$this->whereorext($arr[$i+1]['sub_tree']); }else{ $this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]['bool']['must'][0]['bool']['should'][]=$this->whereorext($this->whereorink($arr,$i+1)); $this->arrtmp=array(); } $this->tmp_or=1; break; case 'and': if(isset($this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]) && $this->tmp_lock!='' && $this->tmp_lock!=$lowerstr){ if($this->tmp_str_filter=='' && !$this->tmp_and){ $this->count_tmp_filter++; }else if($this->tmp_str_filter!='' && $this->tmp_str_filter!=$termk){ $this->count_tmp_filter++; } }else if($this->tmp_str!='' && $this->tmp_str!=$termk){ $this->count_tmp_filter++; } if(!isset($arr[$i-2])){ $this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]['bool']['must'][]=$this->whereorext($arr[$i-1]['sub_tree']); } if($arr[$i+1]['expr_type']=='bracket_expression'){ $this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]['bool']['must'][]=$this->whereorext($arr[$i+1]['sub_tree']); }else{ $this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]['bool']['must'][]=$this->whereorext($this->whereorink($arr,$i+1)); $this->arrtmp=array(); } $this->tmp_and=1; break; } } private function whereext($arr,$i){ if(!is_numeric($arr[$i]['base_expr'])){ $lowerstr = strtolower($arr[$i]['base_expr']); }else{ $lowerstr = $arr[$i]['base_expr']; } switch ($lowerstr) { case '=': if($arr[$i-1]['base_expr']==$arr[$i+1]['base_expr']){ break; } if(isset($arr[$i+2]['base_expr']) && strtolower($arr[$i+2]['base_expr'])=='or' || isset($arr[$i-2]['base_expr']) && strtolower($arr[$i-2]['base_expr'])=='or'){ if(strrpos($arr[$i-1]['base_expr'],".")){ $term_tmp_arr=explode(".",$arr[$i-1]['base_expr']); if($term_tmp_arr[1]!='keyword'){ $termk=$term_tmp_arr[1]; }else{ $termk=$arr[$i-1]['base_expr']; } }else{ $termk=$arr[$i-1]['base_expr']; } $tmp_da_str=str_replace('"','',$arr[$i+1]['base_expr']); $tmp_da_str=str_replace("'","",$tmp_da_str); if(isset($this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]) && $this->tmp_lock!='' && $this->tmp_lock!=$lowerstr){ if($this->tmp_str_filter==''){ $this->count_tmp_filter++; }else if($this->tmp_str_filter!='' && $this->tmp_str_filter!=$termk){ $this->count_tmp_filter++; } }else if($this->tmp_str!='' && $this->tmp_str!=$termk){ $this->count_tmp_filter++; } if(isset($this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]['bool']['must'][0]) && $this->tmp_lock_str!='' && $this->tmp_lock_str!=$lowerstr){ if($this->tmp_str==''){ $this->count_tmp++; }else if($this->tmp_str!='' && $this->tmp_str!=$termk){ $this->count_tmp++; } } if(isset($this->parsed['UPDATE']) && !empty($this->parsed['UPDATE'])){ $this->url .=$tmp_da_str ."/_update?pretty"; }else{ if(!is_numeric($arr[$i+1]['base_expr']) && $this->version_es=='8.x'){ $term['match_phrase'][$termk.'.keyword']['query']=$tmp_da_str; $this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]['bool']['must'][$this->count_tmp]['bool']['should'][]=$term; }else{ $term['match_phrase'][$termk]['query']=$tmp_da_str; $this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]['bool']['must'][$this->count_tmp]['bool']['should'][]=$term; } unset($term['match_phrase']); } $this->tmp_lock=$lowerstr; $this->tmp_lock_str=$lowerstr; }else if(isset($arr[$i+2]['base_expr']) && strtolower($arr[$i+2]['base_expr'])=='and' || isset($arr[$i-2]['base_expr']) && strtolower($arr[$i-2]['base_expr'])=='and'){ if(strrpos($arr[$i-1]['base_expr'],".")){ $term_tmp_arr=explode(".",$arr[$i-1]['base_expr']); if($term_tmp_arr[1]!='keyword'){ $termk=$term_tmp_arr[1]; }else{ $termk=$arr[$i-1]['base_expr']; } }else{ $termk=$arr[$i-1]['base_expr']; } $tmp_da_str=str_replace('"','',$arr[$i+1]['base_expr']); $tmp_da_str=str_replace("'","",$tmp_da_str); if(isset($this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]) && $this->tmp_lock_str!='' && $this->tmp_lock_str!=$lowerstr){ if($this->tmp_str==''){ $this->count_tmp++; }else if($this->tmp_str!='' && $this->tmp_str!=$termk){ $this->count_tmp++; } } if(isset($this->parsed['UPDATE']) && !empty($this->parsed['UPDATE'])){ $this->url .=$tmp_da_str ."/_update?pretty"; }else{ if(isset($this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]) && $this->tmp_lock!='' && $this->tmp_lock!=$lowerstr){ if($this->tmp_str_filter==''){ $this->count_tmp_filter++; }else if($this->tmp_str_filter!='' && $this->tmp_str_filter!=$termk){ $this->count_tmp_filter++; } }else if($this->tmp_str!='' && $this->tmp_str!=$termk){ $this->count_tmp_filter++; } if(!is_numeric($arr[$i+1]['base_expr']) && $this->version_es=='8.x'){ $term['match_phrase'][$termk.'.keyword']['query']=$tmp_da_str; $this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]['bool']['must'][]=$term; }else{ $term['match_phrase'][$termk]['query']=$tmp_da_str; $this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]['bool']['must'][]=$term; } unset($term['match_phrase']); } $this->tmp_lock_str=$lowerstr; }else{ if(strrpos($arr[$i-1]['base_expr'],".")){ $term_tmp_arr=explode(".",$arr[$i-1]['base_expr']); if($term_tmp_arr[1]!='keyword'){ $termk=$term_tmp_arr[1]; }else{ $termk=$arr[$i-1]['base_expr']; } }else{ $termk=$arr[$i-1]['base_expr']; } $tmp_da_str=str_replace('"','',$arr[$i+1]['base_expr']); $tmp_da_str=str_replace("'","",$tmp_da_str); if(isset($this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]) && $this->tmp_lock!='' && $this->tmp_lock!=$lowerstr){ if($this->tmp_str_filter==''){ $this->count_tmp_filter++; }else if($this->tmp_str_filter!='' && $this->tmp_str_filter!=$termk){ $this->count_tmp_filter++; } }else if($this->tmp_str!='' && $this->tmp_str!=$termk){ $this->count_tmp_filter++; } if(!is_numeric($arr[$i+1]['base_expr']) && $this->version_es=='8.x'){ $term['match_phrase'][$termk.'.keyword']['query']=$tmp_da_str; $this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]['bool']['must'][]=$term; }else{ $term['match_phrase'][$termk]['query']=$tmp_da_str; $this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]['bool']['must'][]=$term; } unset($term['match_phrase']); $this->tmp_lock_str=$lowerstr; } $this->tmp_lock=$lowerstr; $this->tmp_str=$lowerstr; break; case '!=': if($arr[$i-1]['base_expr']==$arr[$i+1]['base_expr']){ break; } if(isset($arr[$i+2]['base_expr']) && strtolower($arr[$i+2]['base_expr'])=='or' || isset($arr[$i-2]['base_expr']) && strtolower($arr[$i-2]['base_expr'])=='or'){ if(strrpos($arr[$i-1]['base_expr'],".")){ $term_tmp_arr=explode(".",$arr[$i-1]['base_expr']); if($term_tmp_arr[1]!='keyword'){ $termk=$term_tmp_arr[1]; }else{ $termk=$arr[$i-1]['base_expr']; } }else{ $termk=$arr[$i-1]['base_expr']; } $tmp_da_str=str_replace('"','',$arr[$i+1]['base_expr']); $tmp_da_str=str_replace("'","",$tmp_da_str); if(isset($this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]) && $this->tmp_lock!='' && $this->tmp_lock!=$lowerstr){ if($this->tmp_str_filter==''){ $this->count_tmp_filter++; }else if($this->tmp_str_filter!='' && $this->tmp_str_filter!=$termk){ $this->count_tmp_filter++; } }else if($this->tmp_str!='' && $this->tmp_str!=$termk){ $this->count_tmp_filter++; } if(isset($this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]['bool']['must_not'][0]) && $this->tmp_lock_str!='' && $this->tmp_lock_str!=$lowerstr){ if($this->tmp_str==''){ $this->count_tmp++; }else if($this->tmp_str!='' && $this->tmp_str!=$termk){ $this->count_tmp++; } } if(isset($this->parsed['UPDATE']) && !empty($this->parsed['UPDATE'])){ $this->url .=$tmp_da_str ."/_update?pretty"; }else{ if(!is_numeric($arr[$i+1]['base_expr']) && $this->version_es=='8.x'){ $term['match_phrase'][$termk.'.keyword']['query']=$tmp_da_str; $this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]['bool']['must_not'][$this->count_tmp]['bool']['should'][]=$term; }else{ $term['match_phrase'][$termk]['query']=$tmp_da_str; $this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]['bool']['must_not'][$this->count_tmp]['bool']['should'][]=$term; } unset($term['match_phrase']); } $this->tmp_lock=$lowerstr; $this->tmp_lock_str=$lowerstr; }else if(isset($arr[$i+2]['base_expr']) && strtolower($arr[$i+2]['base_expr'])=='and' || isset($arr[$i-2]['base_expr']) && strtolower($arr[$i-2]['base_expr'])=='and'){ if(strrpos($arr[$i-1]['base_expr'],".")){ $term_tmp_arr=explode(".",$arr[$i-1]['base_expr']); if($term_tmp_arr[1]!='keyword'){ $termk=$term_tmp_arr[1]; }else{ $termk=$arr[$i-1]['base_expr']; } }else{ $termk=$arr[$i-1]['base_expr']; } $tmp_da_str=str_replace('"','',$arr[$i+1]['base_expr']); $tmp_da_str=str_replace("'","",$tmp_da_str); if(isset($this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]) && $this->tmp_lock_str!='' && $this->tmp_lock_str!=$lowerstr){ if($this->tmp_str==''){ $this->count_tmp++; }else if($this->tmp_str!='' && $this->tmp_str!=$termk){ $this->count_tmp++; } } if(isset($this->parsed['UPDATE']) && !empty($this->parsed['UPDATE'])){ $this->url .=$tmp_da_str ."/_update?pretty"; }else{ if(isset($this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]) && $this->tmp_lock!='' && $this->tmp_lock!=$lowerstr){ if($this->tmp_str_filter==''){ $this->count_tmp_filter++; }else if($this->tmp_str_filter!='' && $this->tmp_str_filter!=$termk){ $this->count_tmp_filter++; } }else if($this->tmp_str!='' && $this->tmp_str!=$termk){ $this->count_tmp_filter++; } if(!is_numeric($arr[$i+1]['base_expr']) && $this->version_es=='8.x'){ $term['match_phrase'][$termk.'.keyword']['query']=$tmp_da_str; $this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]['bool']['must_not'][]=$term; }else{ $term['match_phrase'][$termk]['query']=$tmp_da_str; $this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]['bool']['must_not'][]=$term; } unset($term['match_phrase']); } $this->tmp_lock_str=$lowerstr; }else{ if(strrpos($arr[$i-1]['base_expr'],".")){ $term_tmp_arr=explode(".",$arr[$i-1]['base_expr']); if($term_tmp_arr[1]!='keyword'){ $termk=$term_tmp_arr[1]; }else{ $termk=$arr[$i-1]['base_expr']; } }else{ $termk=$arr[$i-1]['base_expr']; } $tmp_da_str=str_replace('"','',$arr[$i+1]['base_expr']); $tmp_da_str=str_replace("'","",$tmp_da_str); if(isset($this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]) && $this->tmp_lock!='' && $this->tmp_lock!=$lowerstr){ if($this->tmp_str_filter==''){ $this->count_tmp_filter++; }else if($this->tmp_str_filter!='' && $this->tmp_str_filter!=$termk){ $this->count_tmp_filter++; } }else if($this->tmp_str!='' && $this->tmp_str!=$termk){ $this->count_tmp_filter++; } if(!is_numeric($arr[$i+1]['base_expr']) && $this->version_es=='8.x'){ $term['match_phrase'][$termk.'.keyword']['query']=$tmp_da_str; $this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]['bool']['must_not'][]=$term; }else{ $term['match_phrase'][$termk]['query']=$tmp_da_str; $this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]['bool']['must_not'][]=$term; } unset($term['match_phrase']); $this->tmp_lock_str=$lowerstr; } $this->tmp_lock=$lowerstr; $this->tmp_str=$lowerstr; break; case '<>': if($arr[$i-1]['base_expr']==$arr[$i+1]['base_expr']){ break; } if(isset($arr[$i+2]['base_expr']) && strtolower($arr[$i+2]['base_expr'])=='or' || isset($arr[$i-2]['base_expr']) && strtolower($arr[$i-2]['base_expr'])=='or'){ if(strrpos($arr[$i-1]['base_expr'],".")){ $term_tmp_arr=explode(".",$arr[$i-1]['base_expr']); if($term_tmp_arr[1]!='keyword'){ $termk=$term_tmp_arr[1]; }else{ $termk=$arr[$i-1]['base_expr']; } }else{ $termk=$arr[$i-1]['base_expr']; } $tmp_da_str=str_replace('"','',$arr[$i+1]['base_expr']); $tmp_da_str=str_replace("'","",$tmp_da_str); if(isset($this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]) && $this->tmp_lock!='' && $this->tmp_lock!=$lowerstr){ if($this->tmp_str_filter==''){ $this->count_tmp_filter++; }else if($this->tmp_str_filter!='' && $this->tmp_str_filter!=$termk){ $this->count_tmp_filter++; } }else if($this->tmp_str!='' && $this->tmp_str!=$termk){ $this->count_tmp_filter++; } if(isset($this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]['bool']['must_not'][0]) && $this->tmp_lock_str!='' && $this->tmp_lock_str!=$lowerstr){ if($this->tmp_str==''){ $this->count_tmp++; }else if($this->tmp_str!='' && $this->tmp_str!=$termk){ $this->count_tmp++; } } if(isset($this->parsed['UPDATE']) && !empty($this->parsed['UPDATE'])){ $this->url .=$tmp_da_str ."/_update?pretty"; }else{ if(!is_numeric($arr[$i+1]['base_expr']) && $this->version_es=='8.x'){ $term['match_phrase'][$termk.'.keyword']['query']=$tmp_da_str; $this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]['bool']['must_not'][$this->count_tmp]['bool']['should'][]=$term; }else{ $term['match_phrase'][$termk]['query']=$tmp_da_str; $this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]['bool']['must_not'][$this->count_tmp]['bool']['should'][]=$term; } unset($term['match_phrase']); } $this->tmp_lock=$lowerstr; $this->tmp_lock_str=$lowerstr; }else if(isset($arr[$i+2]['base_expr']) && strtolower($arr[$i+2]['base_expr'])=='and' || isset($arr[$i-2]['base_expr']) && strtolower($arr[$i-2]['base_expr'])=='and'){ if(strrpos($arr[$i-1]['base_expr'],".")){ $term_tmp_arr=explode(".",$arr[$i-1]['base_expr']); if($term_tmp_arr[1]!='keyword'){ $termk=$term_tmp_arr[1]; }else{ $termk=$arr[$i-1]['base_expr']; } }else{ $termk=$arr[$i-1]['base_expr']; } $tmp_da_str=str_replace('"','',$arr[$i+1]['base_expr']); $tmp_da_str=str_replace("'","",$tmp_da_str); if(isset($this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]) && $this->tmp_lock_str!='' && $this->tmp_lock_str!=$lowerstr){ if($this->tmp_str==''){ $this->count_tmp++; }else if($this->tmp_str!='' && $this->tmp_str!=$termk){ $this->count_tmp++; } } if(isset($this->parsed['UPDATE']) && !empty($this->parsed['UPDATE'])){ $this->url .=$tmp_da_str ."/_update?pretty"; }else{ if(isset($this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]) && $this->tmp_lock!='' && $this->tmp_lock!=$lowerstr){ if($this->tmp_str_filter==''){ $this->count_tmp_filter++; }else if($this->tmp_str_filter!='' && $this->tmp_str_filter!=$termk){ $this->count_tmp_filter++; } }else if($this->tmp_str!='' && $this->tmp_str!=$termk){ $this->count_tmp_filter++; } if(!is_numeric($arr[$i+1]['base_expr']) && $this->version_es=='8.x'){ $term['match_phrase'][$termk.'.keyword']['query']=$tmp_da_str; $this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]['bool']['must_not'][]=$term; }else{ $term['match_phrase'][$termk]['query']=$tmp_da_str; $this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]['bool']['must_not'][]=$term; } unset($term['match_phrase']); } $this->tmp_lock_str=$lowerstr; }else{ if(strrpos($arr[$i-1]['base_expr'],".")){ $term_tmp_arr=explode(".",$arr[$i-1]['base_expr']); if($term_tmp_arr[1]!='keyword'){ $termk=$term_tmp_arr[1]; }else{ $termk=$arr[$i-1]['base_expr']; } }else{ $termk=$arr[$i-1]['base_expr']; } $tmp_da_str=str_replace('"','',$arr[$i+1]['base_expr']); $tmp_da_str=str_replace("'","",$tmp_da_str); if(isset($this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]) && $this->tmp_lock!='' && $this->tmp_lock!=$lowerstr){ if($this->tmp_str_filter==''){ $this->count_tmp_filter++; }else if($this->tmp_str_filter!='' && $this->tmp_str_filter!=$termk){ $this->count_tmp_filter++; } }else if($this->tmp_str!='' && $this->tmp_str!=$termk){ $this->count_tmp_filter++; } if(!is_numeric($arr[$i+1]['base_expr']) && $this->version_es=='8.x'){ $term['match_phrase'][$termk.'.keyword']['query']=$tmp_da_str; $this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]['bool']['must_not'][]=$term; }else{ $term['match_phrase'][$termk]['query']=$tmp_da_str; $this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]['bool']['must_not'][]=$term; } unset($term['match_phrase']); $this->tmp_lock_str=$lowerstr; } $this->tmp_lock=$lowerstr; $this->tmp_str=$lowerstr; break; case 'in': if(strtolower($arr[$i-1]['base_expr'])=='not'){ break; } if($arr[$i-1]['base_expr']==$arr[$i+1]['base_expr']){ break; } if(strrpos($arr[$i-1]['base_expr'],".")){ $term_tmp_arr=explode(".",$arr[$i-1]['base_expr']); if($term_tmp_arr[1]!='keyword'){ $termk=$term_tmp_arr[1]; }else{ $termk=$arr[$i-1]['base_expr']; } }else{ $termk=$arr[$i-1]['base_expr']; } if(isset($this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]) && $this->tmp_lock!='' && $this->tmp_lock==$lowerstr){ if($this->tmp_str_filter==''){ $this->count_tmp_filter++; }else if($this->tmp_str_filter!='' && $this->tmp_str_filter!=$termk){ $this->count_tmp_filter++; } }else if($this->tmp_str!='' && $this->tmp_str!=$termk){ $this->count_tmp_filter++; } if(isset($arr[$i+2]['base_expr']) && strtolower($arr[$i+2]['base_expr'])=='or' || isset($arr[$i-2]['base_expr']) && strtolower($arr[$i-2]['base_expr'])=='or'){ if(isset($this->Builderarr['query']['bool']['filter']['bool']['should'][$this->count_tmp]) && $this->tmp_lock_str!='' && $this->tmp_lock_str==$lowerstr){ if($this->tmp_str==''){ $this->count_tmp++; }else if($this->tmp_str!='' && $this->tmp_str!=$termk){ $this->count_tmp++; } }else if($this->tmp_str!='' && $this->tmp_str!=$termk){ $this->count_tmp++; } if(isset($arr[$i+1]['sub_tree']) && !empty($arr[$i+1]['sub_tree'])){ foreach ($arr[$i+1]['sub_tree'] as &$vv) { if(!is_numeric($vv['base_expr']) && $this->version_es=='8.x'){ $termk .='.keyword'; } $tmp_da_str=str_replace('"','',$vv['base_expr']); $tmp_da_str=str_replace("'","",$tmp_da_str); $this->Builderarr['query']['bool']['filter']['bool']['should'][$this->count_tmp]['terms'][$termk][]=$tmp_da_str; } } }else{ if(isset($arr[$i+1]['sub_tree']) && !empty($arr[$i+1]['sub_tree'])){ if ($this->version_es == '7.x'){ $this->count_tmp_filter++; } foreach ($arr[$i+1]['sub_tree'] as &$vv) { if(!is_numeric($vv['base_expr']) && $this->version_es=='8.x'){ $termk .='.keyword'; } $tmp_da_str=str_replace('"','',$vv['base_expr']); $tmp_da_str=str_replace("'","",$tmp_da_str); $this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]['terms'][$termk][]=$tmp_da_str; } } } $this->tmp_lock=$lowerstr; $this->tmp_str=$termk; unset($termk); break; case 'not': if($arr[$i-1]['base_expr']==$arr[$i+1]['base_expr']){ break; } if(strrpos($arr[$i-1]['base_expr'],".")){ $term_tmp_arr=explode(".",$arr[$i-1]['base_expr']); if($term_tmp_arr[1]!='keyword'){ if($term_tmp_arr[1]!='keyword'){ $termk=$term_tmp_arr[1]; }else{ $termk=$arr[$i-1]['base_expr']; } }else{ $termk=$arr[$i-1]['base_expr']; } }else{ $termk=$arr[$i-1]['base_expr']; } if(isset($this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]) && $this->tmp_lock!='' && $this->tmp_lock==$lowerstr){ if($this->tmp_str_filter==''){ $this->count_tmp_filter++; }else if($this->tmp_str_filter!='' && $this->tmp_str_filter!=$termk){ $this->count_tmp_filter++; } }else if($this->tmp_str!='' && $this->tmp_str!=$termk){ $this->count_tmp_filter++; } switch (strtolower($arr[$i+1]['base_expr'])) { case 'in': if(isset($arr[$i+2]['sub_tree']) && !empty($arr[$i+2]['sub_tree'])){ foreach ($arr[$i+2]['sub_tree'] as &$vv) { if(!is_numeric($vv['base_expr']) && $this->version_es=='8.x'){ $termk .='.keyword'; } $tmp_da_str=str_replace('"','',$vv['base_expr']); $tmp_da_str=str_replace("'","",$tmp_da_str); $this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]['bool']['must_not']['terms'][$termk][]=$tmp_da_str; } } break; case 'like': $tmp_la_str=str_replace('"','',$arr[$i+2]['base_expr']); $tmp_la_str=str_replace("'","",$tmp_la_str); if(!is_numeric($arr[$i+2]['base_expr']) && $this->version_es=='8.x'){ // $term['match_phrase'][$termk.'.keyword']=str_replace("%","",$tmp_la_str); $term['wildcard'][$termk.'.keyword']=str_replace("%","*",$tmp_la_str); $this->Builderarr['query']['filter'][$this->count_tmp_filter]['bool']['must_not'][]=$term; }else{ //$term['match_phrase'][$termk]=str_replace("%","",$tmp_la_str); $term['wildcard'][$termk]=str_replace("%","*",$tmp_la_str); $this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]['bool']['must_not'][]=$term; } break; case 'null': $this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]['exists']['field']=$arr[$i-2]['base_expr']; break; } $this->tmp_lock=$lowerstr; $this->tmp_str=$termk; unset($termk); break; case 'is': if($arr[$i-1]['base_expr']==$arr[$i+1]['base_expr']){ break; } if(strtolower($arr[$i+1]['base_expr'])=='not'){ break; } if(strrpos($arr[$i-1]['base_expr'],".")){ $term_tmp_arr=explode(".",$arr[$i-1]['base_expr']); if($term_tmp_arr[1]!='keyword'){ if($term_tmp_arr[1]!='keyword'){ $termk=$term_tmp_arr[1]; }else{ $termk=$arr[$i-1]['base_expr']; } }else{ $termk=$arr[$i-1]['base_expr']; } }else{ $termk=$arr[$i-1]['base_expr']; } if(isset($this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]) && $this->tmp_lock!='' && $this->tmp_lock==$lowerstr){ if($this->tmp_str_filter==''){ $this->count_tmp_filter++; }else if($this->tmp_str_filter!='' && $this->tmp_str_filter!=$termk){ $this->count_tmp_filter++; } }else if($this->tmp_str!='' && $this->tmp_str!=$termk){ $this->count_tmp_filter++; } $this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]['bool']['must_not'][]['exists']['field']=$arr[$i-1]['base_expr']; $this->tmp_lock=$lowerstr; $this->tmp_str=$termk; unset($termk); break; case '>': if($arr[$i-1]['base_expr']==$arr[$i+1]['base_expr']){ break; } if(strrpos($arr[$i-1]['base_expr'],".")){ $term_tmp_arr=explode(".",$arr[$i-1]['base_expr']); if($term_tmp_arr[1]!='keyword'){ $termk=$term_tmp_arr[1]; }else{ $termk=$arr[$i-1]['base_expr']; } }else{ $termk=$arr[$i-1]['base_expr']; } $tmp_da_str=str_replace('"','',$arr[$i+1]['base_expr']); $tmp_da_str=str_replace("'","",$tmp_da_str); $is_date=strtotime($tmp_da_str)?strtotime($tmp_da_str):false; if(isset($arr[$i+2]['base_expr']) && strtolower($arr[$i+2]['base_expr'])=='or' || isset($arr[$i-2]['base_expr']) && strtolower($arr[$i-2]['base_expr'])=='or'){ if(isset($this->Builderarr['query']['bool']['filter'][0]) && $this->tmp_lock!='' && $this->tmp_lock==$lowerstr){ if($this->tmp_str_filter==''){ $this->count_tmp_filter++; }else if($this->tmp_str_filter!='' && $this->tmp_str_filter!=$termk){ $this->count_tmp_filter++; } } if(isset($this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]['bool']['must'][0]) && $this->tmp_lock_fi!='' && $this->tmp_lock_fi==$lowerstr){ if($this->tmp_fi==''){ $this->count_fi++; }else if($this->tmp_fi!='' && $this->tmp_fi!=$termk){ $this->count_fi++; } } if(isset($this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]['bool']['must'][$this->count_fi]['bool']['should'][0]) && $this->tmp_lock_range!=''){ if($this->tmp_str_range==''){ $this->count_tmp_range++; }else if($this->tmp_str_range!='' && $this->tmp_str_range!=$termk){ $this->count_tmp_range++; } } $this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]['bool']['must'][$this->count_fi]['bool']['should'][$this->count_tmp_range]['range'][$termk]['gt']=$tmp_da_str; if(!isset($this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]['bool']['must'][$this->count_fi]['bool']['should'][$this->count_tmp_range]['range'][$termk]['time_zone']) && $is_date){ $this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]['bool']['must'][$this->count_fi]['bool']['should'][$this->count_tmp_range]['range'][$termk]['time_zone']="+08:00"; } }else{ if(isset($this->Builderarr['query']['bool']['filter'][0]) && $this->tmp_lock_str!='' && $this->tmp_lock_str!=$lowerstr){ if($this->tmp_str==''){ $this->count_tmp++; }else if($this->tmp_str!='' && $this->tmp_str!=$termk){ $this->count_tmp++; } } if(!isset($this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]['range']) && $this->tmp_lock!='' ){ if($this->tmp_str_filter==''){ $this->count_tmp_filter++; }else if($this->tmp_str_filter!='' && $this->tmp_str_filter!=$termk){ $this->count_tmp_filter++; } }else if($this->tmp_str!='' && $this->tmp_str!=$termk){ $this->count_tmp_filter++; } $this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]['range'][$termk]['gt']=$tmp_da_str; if(!isset($this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]['range'][$termk]['time_zone']) && $is_date){ $this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]['range'][$termk]['time_zone']="+08:00"; } } $this->tmp_str=$termk; $this->tmp_lock_str=$lowerstr; $this->tmp_lock=$lowerstr; $this->tmp_lock_range=$lowerstr; $this->tmp_lock_fi=$lowerstr; break; case '>=': if($arr[$i-1]['base_expr']==$arr[$i+1]['base_expr']){ break; } if(strrpos($arr[$i-1]['base_expr'],".")){ $term_tmp_arr=explode(".",$arr[$i-1]['base_expr']); if($term_tmp_arr[1]!='keyword'){ $termk=$term_tmp_arr[1]; }else{ $termk=$arr[$i-1]['base_expr']; } }else{ $termk=$arr[$i-1]['base_expr']; } $tmp_da_str=str_replace('"','',$arr[$i+1]['base_expr']); $tmp_da_str=str_replace("'","",$tmp_da_str); $is_date=strtotime($tmp_da_str)?strtotime($tmp_da_str):false; if(isset($arr[$i+2]['base_expr']) && strtolower($arr[$i+2]['base_expr'])=='or' || isset($arr[$i-2]['base_expr']) && strtolower($arr[$i-2]['base_expr'])=='or'){ if(isset($this->Builderarr['query']['bool']['filter'][0]) && $this->tmp_lock!='' && $this->tmp_lock==$lowerstr){ if($this->tmp_str_filter==''){ $this->count_tmp_filter++; }else if($this->tmp_str_filter!='' && $this->tmp_str_filter!=$termk){ $this->count_tmp_filter++; } } if(isset($this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]['bool']['must'][0]) && $this->tmp_lock_fi!='' && $this->tmp_lock_fi==$lowerstr){ if($this->tmp_fi==''){ $this->count_fi++; }else if($this->tmp_fi!='' && $this->tmp_fi!=$termk){ $this->count_fi++; } } if(isset($this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]['bool']['must'][$this->count_fi]['bool']['should'][0]) && $this->tmp_lock_range!='' ){ if($this->tmp_str_range==''){ $this->count_tmp_range++; }else if($this->tmp_str_range!='' && $this->tmp_str_range!=$termk){ $this->count_tmp_range++; } } $this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]['bool']['must'][$this->count_fi]['bool']['should'][$this->count_tmp_range]['range'][$termk]['gte']=$tmp_da_str; if(!isset($this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]['bool']['must'][$this->count_fi]['bool']['should'][$this->count_tmp_range]['range'][$termk]['time_zone']) && $is_date){ $this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]['bool']['must'][$this->count_fi]['bool']['should'][$this->count_tmp_range]['range'][$termk]['time_zone']="+08:00"; } }else{ if(isset($this->Builderarr['query']['bool']['filter'][0]) && $this->tmp_lock_str!='' && $this->tmp_lock_str!=$lowerstr){ if($this->tmp_str==''){ $this->count_tmp++; }else if($this->tmp_str!='' && $this->tmp_str!=$termk){ $this->count_tmp++; } } if(!isset($this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]['range']) && $this->tmp_lock!='' ){ if($this->tmp_str_filter==''){ $this->count_tmp_filter++; }else if($this->tmp_str_filter!='' && $this->tmp_str_filter!=$termk){ $this->count_tmp_filter++; } }else if($this->tmp_str!='' && $this->tmp_str!=$termk){ $this->count_tmp_filter++; } $this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]['range'][$termk]['gte']=$tmp_da_str; if(!isset($this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]['range'][$termk]['time_zone']) && $is_date){ $this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]['range'][$termk]['time_zone']="+08:00"; } } $this->tmp_str=$termk; $this->tmp_lock_str=$lowerstr; $this->tmp_lock=$lowerstr; $this->tmp_lock_range=$lowerstr; $this->tmp_lock_fi=$lowerstr; break; case '<': if($arr[$i-1]['base_expr']==$arr[$i+1]['base_expr']){ break; } if(strrpos($arr[$i-1]['base_expr'],".")){ $term_tmp_arr=explode(".",$arr[$i-1]['base_expr']); if($term_tmp_arr[1]!='keyword'){ $termk=$term_tmp_arr[1]; }else{ $termk=$arr[$i-1]['base_expr']; } }else{ $termk=$arr[$i-1]['base_expr']; } $tmp_da_str=str_replace('"','',$arr[$i+1]['base_expr']); $tmp_da_str=str_replace("'","",$tmp_da_str); $is_date=strtotime($tmp_da_str)?strtotime($tmp_da_str):false; if(isset($arr[$i+2]['base_expr']) && strtolower($arr[$i+2]['base_expr'])=='or' || isset($arr[$i-2]['base_expr']) && strtolower($arr[$i-2]['base_expr'])=='or'){ if(isset($this->Builderarr['query']['bool']['filter'][0]) && $this->tmp_lock!='' && $this->tmp_lock==$lowerstr){ if($this->tmp_str_filter==''){ $this->count_tmp_filter++; }else if($this->tmp_str_filter!='' && $this->tmp_str_filter!=$termk){ $this->count_tmp_filter++; } } if(isset($this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]['bool']['must'][0]) && $this->tmp_lock_fi!='' && $this->tmp_lock_fi==$lowerstr){ if($this->tmp_fi==''){ $this->count_fi++; }else if($this->tmp_fi!='' && $this->tmp_fi!=$termk){ $this->count_fi++; } } if(isset($this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]['bool']['must'][$this->count_fi]['bool']['should'][0]) && $this->tmp_lock_range!=''){ if($this->tmp_str_range==''){ $this->count_tmp_range++; }else if($this->tmp_str_range!='' && $this->tmp_str_range!=$termk){ $this->count_tmp_range++; } } $this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]['bool']['must'][$this->count_fi]['bool']['should'][$this->count_tmp_range]['range'][$termk]['lt']=$tmp_da_str; if(!isset($this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]['bool']['must'][$this->count_fi]['bool']['should'][$this->count_tmp_range]['range'][$termk]['time_zone']) && $is_date){ $this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]['bool']['must'][$this->count_fi]['bool']['should'][$this->count_tmp_range]['range'][$termk]['time_zone']="+08:00"; } }else{ if(isset($this->Builderarr['query']['bool']['filter'][0]) && $this->tmp_lock_str!='' && $this->tmp_lock_str==$lowerstr){ if($this->tmp_str==''){ $this->count_tmp++; } } if(!isset($this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]['range']) && $this->tmp_lock!='' ){ if($this->tmp_str_filter==''){ $this->count_tmp_filter++; }else if($this->tmp_str_filter!='' && $this->tmp_str_filter!=$termk){ $this->count_tmp_filter++; } }else if($this->tmp_str!='' && $this->tmp_str!=$termk){ $this->count_tmp_filter++; } $this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]['range'][$termk]['lt']=$tmp_da_str; if(!isset($this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]['range'][$termk]['time_zone']) && $is_date){ $this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]['range'][$termk]['time_zone']="+08:00"; } } $this->tmp_str=$termk; $this->tmp_lock_str=$lowerstr; $this->tmp_lock=$lowerstr; $this->tmp_lock_range=$lowerstr; $this->tmp_lock_fi=$lowerstr; break; case '<=': if($arr[$i-1]['base_expr']==$arr[$i+1]['base_expr']){ break; } if(strrpos($arr[$i-1]['base_expr'],".")){ $term_tmp_arr=explode(".",$arr[$i-1]['base_expr']); if($term_tmp_arr[1]!='keyword'){ $termk=$term_tmp_arr[1]; }else{ $termk=$arr[$i-1]['base_expr']; } }else{ $termk=$arr[$i-1]['base_expr']; } $tmp_da_str=str_replace('"','',$arr[$i+1]['base_expr']); $tmp_da_str=str_replace("'","",$tmp_da_str); $is_date=strtotime($tmp_da_str)?strtotime($tmp_da_str):false; if(isset($arr[$i+2]['base_expr']) && strtolower($arr[$i+2]['base_expr'])=='or' || isset($arr[$i-2]['base_expr']) && strtolower($arr[$i-2]['base_expr'])=='or'){ if(isset($this->Builderarr['query']['bool']['filter'][0]) && $this->tmp_lock!='' && $this->tmp_lock==$lowerstr){ if($this->tmp_str_filter==''){ $this->count_tmp_filter++; }else if($this->tmp_str_filter!='' && $this->tmp_str_filter!=$termk){ $this->count_tmp_filter++; } } if(isset($this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]['bool']['must'][0]) && $this->tmp_lock_fi!='' && $this->tmp_lock_fi==$lowerstr){ if($this->tmp_fi==''){ $this->count_fi++; }else if($this->tmp_fi!='' && $this->tmp_fi!=$termk){ $this->count_fi++; } } if(isset($this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]['bool']['must'][$this->count_fi]['bool']['should'][0]) && $this->tmp_lock_range!='' ){ if($this->tmp_str_range==''){ $this->count_tmp_range++; }else if($this->tmp_str_range!='' && $this->tmp_str_range!=$termk){ $this->count_tmp_range++; } } $this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]['bool']['must'][$this->count_fi]['bool']['should'][$this->count_tmp_range]['range'][$termk]['lte']=$tmp_da_str; if(!isset($this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]['bool']['must'][$this->count_fi]['bool']['should'][$this->count_tmp_range]['range'][$termk]['time_zone']) && $is_date){ $this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]['bool']['must'][$this->count_fi]['bool']['should'][$this->count_tmp_range]['range'][$termk]['time_zone']="+08:00"; } }else{ if(isset($this->Builderarr['query']['bool']['filter'][0]) && $this->tmp_lock_str!='' && $this->tmp_lock_str==$lowerstr){ if($this->tmp_str==''){ $this->count_tmp++; }else if($this->tmp_str!='' && $this->tmp_str!=$termk){ $this->count_tmp++; } } if(!isset($this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]['range']) && $this->tmp_lock!=''){ if($this->tmp_str_filter==''){ $this->count_tmp_filter++; }else if($this->tmp_str_filter!='' && $this->tmp_str_filter!=$termk){ $this->count_tmp_filter++; } }else if($this->tmp_str!='' && $this->tmp_str!=$termk){ $this->count_tmp_filter++; } $this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]['range'][$termk]['lte']=$tmp_da_str; if(!isset($this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]['range'][$termk]['time_zone']) && $is_date){ $this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]['range'][$termk]['time_zone']="+08:00"; } } $this->tmp_str=$termk; $this->tmp_lock_str=$lowerstr; $this->tmp_lock=$lowerstr; $this->tmp_lock_range=$lowerstr; $this->tmp_lock_fi=$lowerstr; break; case 'like': if(strtolower($arr[$i-1]['base_expr'])=='not'){ break; } if($arr[$i-1]['base_expr']==$arr[$i+1]['base_expr']){ break; } if(strrpos($arr[$i-1]['base_expr'],".")){ $term_tmp_arr=explode(".",$arr[$i-1]['base_expr']); if($term_tmp_arr[1]!='keyword'){ $termk=$term_tmp_arr[1]; }else{ $termk=$arr[$i-1]['base_expr']; } }else{ $termk=$arr[$i-1]['base_expr']; } $tmp_la_str=str_replace('"','',$arr[$i+1]['base_expr']); $tmp_la_str=str_replace("'","",$tmp_la_str); if(isset($arr[$i+2]['base_expr']) && strtolower($arr[$i+2]['base_expr'])=='or' || isset($arr[$i-2]['base_expr']) && strtolower($arr[$i-2]['base_expr'])=='or'){ if(isset($this->Builderarr['query']['bool']['filter'][0]) && $this->tmp_lock!='' && $this->tmp_lock!=$lowerstr){ if($this->tmp_str_filter==''){ $this->count_tmp_filter++; }else if($this->tmp_str_filter!='' && $this->tmp_str_filter!=$termk){ $this->count_tmp_filter++; } } if(isset($this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]['bool']['must'][0]) && $this->tmp_lock_fi!='' && $this->tmp_lock_fi!=$lowerstr){ if($this->tmp_fi==''){ $this->count_fi++; }else if($this->tmp_fi!='' && $this->tmp_fi!=$termk){ $this->count_fi++; } } if(!is_numeric($arr[$i+1]['base_expr']) && $this->version_es=='8.x'){ //$term['match_phrase'][$termk.'.keyword']=str_replace("%","",$tmp_la_str); $term['wildcard'][$termk.'.keyword']=str_replace("%","*",$tmp_la_str); $this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]['bool']['must'][$this->count_fi]['bool']['should'][]=$term; }else{ //$term['match_phrase'][$termk]=str_replace("%","",$tmp_la_str); $term['wildcard'][$termk]=str_replace("%","*",$tmp_la_str); $this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]['bool']['must'][$this->count_fi]['bool']['should'][]=$term; } }else{ if(isset($this->Builderarr['query']['bool']['filter'][0]) && $this->tmp_lock_str!='' && $this->tmp_lock_str!=$lowerstr){ if($this->tmp_str==''){ $this->count_tmp++; }else if($this->tmp_str!='' && $this->tmp_str!=$termk){ $this->count_tmp++; } } if(isset($this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]) && $this->tmp_lock!='' && $this->tmp_lock!=$lowerstr){ if($this->tmp_str_filter==''){ $this->count_tmp_filter++; }else if($this->tmp_str_filter!='' && $this->tmp_str_filter!=$termk){ $this->count_tmp_filter++; } } if(!is_numeric($arr[$i+1]['base_expr']) && $this->version_es=='8.x'){ //$term['match_phrase'][$termk.'.keyword']=str_replace("%","",$tmp_la_str); $term['wildcard'][$termk.'.keyword']=str_replace("%","*",$tmp_la_str); $this->Builderarr['query']['filter'][$this->count_tmp_filter]['must'][$this->count_tmp]['bool']['must'][]=$term; }else{ //$term['match_phrase'][$termk]=str_replace("%","",$tmp_la_str); $term['wildcard'][$termk]=str_replace("%","*",$tmp_la_str); $this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]['bool']['must'][]=$term; } } unset($term['wildcard']); $this->tmp_lock_str=$lowerstr; $this->tmp_lock=$lowerstr; $this->tmp_lock_fi=$lowerstr; break; case 'between': if($arr[$i-1]['base_expr']==$arr[$i+1]['base_expr']){ break; } if(strrpos($arr[$i-1]['base_expr'],".")){ $term_tmp_arr=explode(".",$arr[$i-1]['base_expr']); if($term_tmp_arr[1]!='keyword'){ $termk=$term_tmp_arr[1]; }else{ $termk=$arr[$i-1]['base_expr']; } }else{ $termk=$arr[$i-1]['base_expr']; } if(isset($this->Builderarr['query']['bool']['filter'][0]) && $this->tmp_lock_str!='' && $this->tmp_lock_str!=$lowerstr){ if($this->tmp_str==''){ $this->count_tmp++; }else if($this->tmp_str!='' && $this->tmp_str!=$termk){ $this->count_tmp++; } } if(isset($this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]) && $this->tmp_lock!='' && $this->tmp_lock!=$lowerstr){ if($this->tmp_str_filter==''){ $this->count_tmp_filter++; }else if($this->tmp_str_filter!='' && $this->tmp_str_filter!=$termk){ $this->count_tmp_filter++; } } $tmp_da_str=str_replace('"','',$arr[$i+1]['base_expr']); $tmp_da_str=str_replace("'","",$tmp_da_str); $is_date=strtotime($tmp_da_str)?strtotime($tmp_da_str):false; $this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]['range'][$termk]['gte']=$tmp_da_str; if(!isset($this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]['range'][$termk]['time_zone']) && $is_date){ $this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]['range'][$termk]['time_zone']="+08:00"; } $tmp_da_str=str_replace('"','',$arr[$i+3]['base_expr']); $tmp_da_str=str_replace("'","",$tmp_da_str); $this->Builderarr['query']['bool']['filter'][$this->count_tmp_filter]['range'][$termk]['lte']=$tmp_da_str; $this->tmp_str=$termk; $this->tmp_lock_str=$lowerstr; $this->tmp_lock=$lowerstr; break; } } private function listtree($arr,$aggs,$order){ $countmp=0; for($i=count($arr)-1;$i>=0;$i--){ if(isset($arr[$i-1])){ $key_arr=array_keys($arr[$i]); if($countmp==0){ if(!isset($arr[$i][$key_arr[0]]['date_histogram'])){ $arr[$i][$key_arr[0]]['terms']['size']=($this->limit['from'] + 1 )*$this->limit['size']; if($order){ $arr[$i][$key_arr[0]]['terms']['order']=$order['order']; } } if(isset($aggs['aggs'])){ if(isset($this->havingagg['having']) && !empty($this->havingagg['having'])){ $aggs['aggs']['having']=$this->havingagg['having']; } $arr[$i][$key_arr[0]]['aggs']=$aggs['aggs']; } $arr[$i][$key_arr[0]]['aggs']['top']['top_hits']['size']=$this->top_hits; $countmp=1; } $key_pre=array_keys($arr[$i-1]); $arr[$i-1][$key_pre[0]]['aggs']=$arr[$i]; unset($arr[$i]); }else{ if(count($arr)==1 && $countmp==0){ $key_arrs=array_keys($arr[$i]); if(!isset($arr[$i][$key_arrs[0]]['date_histogram'])){ $arr[$i][$key_arrs[0]]['terms']['size']=($this->limit['from'] + 1 )*$this->limit['size']; if($order){ $arr[$i][$key_arrs[0]]['terms']['order']=$order['order']; } } if(isset($aggs['aggs'])){ if(isset($this->havingagg['having']) && !empty($this->havingagg['having'])){ $aggs['aggs']['having']=$this->havingagg['having']; } $arr[$i][$key_arrs[0]]['aggs']=$aggs['aggs']; } $arr[$i][$key_arrs[0]]['aggs']['top']['top_hits']['size']=$this->top_hits; $countmp=1; } } } return $arr; } private function groupby($arr){ $aggs= array(); $agg= array(); $agg_orderby=array(); for($i=0; $i fistgroup) && $this->fistgroup==''){ $this->fistgroup=$termk_tmp; } $agg[$i][$termk_tmp]['terms']['field']=$termk; $agg[$i][$termk_tmp]['terms']['size']=($this->limit['from'] + 1 )*$this->limit['size']; } if(isset($this->parsed['SELECT']) && !empty($this->parsed['SELECT'])){ foreach ($this->parsed['SELECT'] as $v) { $this->top_hits=1; if(strrpos($v['base_expr'],"*")){ //$this->top_hits=1; }else{ if($v['expr_type']=='aggregate_function' || $v['expr_type']=='function'){ $lowerstr = strtolower($v['base_expr']); switch ($lowerstr) { case 'count': if(strrpos($v['sub_tree'][0]['base_expr'],".")){ $term_tmp_arrs=explode(".",$v['sub_tree'][0]['base_expr']); if($term_tmp_arrs[1]!='keyword'){ $cardinalitys[$v['alias']['name']]['cardinality']['field']=$term_tmp_arrs[1]; }else{ $cardinalitys[$v['alias']['name']]['cardinality']['field']=$v['sub_tree'][0]['base_expr']; } }else{ $cardinalitys[$v['alias']['name']]['cardinality']['field']=$v['sub_tree'][0]['base_expr']; } $tmmp=1; $agggs['aggs']=$cardinalitys; $aggs=array_merge_recursive($aggs, $agggs); unset($cardinalitys); break; case 'sum': if(strrpos($v['sub_tree'][0]['base_expr'],".")){ $term_tmp_arrs=explode(".",$v['sub_tree'][0]['base_expr']); if (!isset($v['alias']['name'])) { $v['alias']['name']='sum'.$term_tmp_arrs[1]; } $cardinalitys[$v['alias']['name']]['sum']['field']=$term_tmp_arrs[1]; }else{ if (!isset($v['alias']['name'])) { $v['alias']['name']='sum'.$v['sub_tree'][0]['base_expr']; } $cardinalitys[$v['alias']['name']]['sum']['field']=$v['sub_tree'][0]['base_expr']; } $tmmp=1; $agggs['aggs']=$cardinalitys; $aggs=array_merge_recursive($aggs, $agggs); unset($cardinalitys); break; case 'min': if(strrpos($v['sub_tree'][0]['base_expr'],".")){ $term_tmp_arrs=explode(".",$v['sub_tree'][0]['base_expr']); $cardinalitys[$v['alias']['name']]['min']['field']=$term_tmp_arrs[1]; }else{ $cardinalitys[$v['alias']['name']]['min']['field']=$v['sub_tree'][0]['base_expr']; } $tmmp=1; $agggs['aggs']=$cardinalitys; $aggs=array_merge_recursive($aggs, $agggs); unset($cardinalitys); break; case 'max': if(strrpos($v['sub_tree'][0]['base_expr'],".")){ $term_tmp_arrs=explode(".",$v['sub_tree'][0]['base_expr']); $cardinalitys[$v['alias']['name']]['max']['field']=$term_tmp_arrs[1]; }else{ $cardinalitys[$v['alias']['name']]['max']['field']=$v['sub_tree'][0]['base_expr']; } $tmmp=1; $agggs['aggs']=$cardinalitys; $aggs=array_merge_recursive($aggs, $agggs); unset($cardinalitys); break; case 'avg': if(strrpos($v['sub_tree'][0]['base_expr'],".")){ $term_tmp_arrs=explode(".",$v['sub_tree'][0]['base_expr']); $cardinalitys[$v['alias']['name']]['avg']['field']=$term_tmp_arrs[1]; }else{ $cardinalitys[$v['alias']['name']]['avg']['field']=$v['sub_tree'][0]['base_expr']; } $tmmp=1; $agggs['aggs']=$cardinalitys; $aggs=array_merge_recursive($aggs, $agggs); unset($cardinalitys); break; case 'concat_ws': $tmp_script=''; $tmp_ps=''; if(isset($v['alias']) && !empty($v['alias'])){ foreach ($agg as $kk => $ve) { $key_arr=array_keys($ve); if(isset($ve[$key_arr[0]]['terms']['field']) && $v['alias']['name']==$ve[$key_arr[0]]['terms']['field']){ foreach ($v['sub_tree'] as $ke => $va) { if($va['expr_type']=='const'){ $tmp_ps=str_replace('"','',$va['base_expr']); $tmp_ps=str_replace("'","",$tmp_ps); } if($va['expr_type']=='colref'){ $tmp_script .="'".$tmp_ps."' + doc['".$va['base_expr']."'].value + "; } } $tmp_script=substr($tmp_script,6,strlen($tmp_script)-8); $agg[$kk][$key_arr[0]]['terms']['script']['source']=$tmp_script; $agg[$kk][$key_arr[0]]['terms']['script']['lang']='painless'; unset($agg[$kk][$key_arr[0]]['terms']['field']); } } } break; case 'date_format': $tmp_script=''; $tmp_ps=''; if(isset($v['alias']) && !empty($v['alias'])){ foreach ($agg as $kk => $ve) { $key_arr=array_keys($ve); if(isset($ve[$key_arr[0]]['terms']['field']) && $v['alias']['name']==$ve[$key_arr[0]]['terms']['field']){ for ($jj=0;$jj<=count($v['sub_tree'])-1;$jj++) { if($v['sub_tree'][$jj]['expr_type']=='const'){ $tmp_ps=str_replace('"','',$v['sub_tree'][$jj]['base_expr']); $tmp_ps=str_replace("'","",$tmp_ps); $tmp_ps=str_replace("%","",$tmp_ps); $tmp_ps=str_replace("/","",$tmp_ps); $tmp_ps=str_replace("-","",$tmp_ps); switch ($tmp_ps) { case 'Ymd': $agg[$kk][$key_arr[0]]['date_histogram']['interval']="day"; break; case 'Ym': $agg[$kk][$key_arr[0]]['date_histogram']['interval']="month"; $agg[$kk][$key_arr[0]]['date_histogram']['format']="yyyy-MM"; break; case 'Y': $agg[$kk][$key_arr[0]]['date_histogram']['interval']="year"; $agg[$kk][$key_arr[0]]['date_histogram']['format']="yyyy"; break; case 'Yu': $agg[$kk][$key_arr[0]]['date_histogram']['interval']="week"; break; case 'H': $agg[$kk][$key_arr[0]]['date_histogram']['interval']="hour"; break; case 'i': $agg[$kk][$key_arr[0]]['date_histogram']['interval']="minute"; break; } } if($v['sub_tree'][$jj]['expr_type']=='colref'){ $agg[$kk][$key_arr[0]]['date_histogram']['field']=$v['sub_tree'][$jj]['base_expr']; $agg[$kk][$key_arr[0]]['date_histogram']['format']="yyyy-MM-dd"; $agg[$kk][$key_arr[0]]['date_histogram']['time_zone']="+08:00"; unset($agg[$kk][$key_arr[0]]['terms']); } } } } } break; } if(isset($this->parsed['ORDER']) && !empty($this->parsed['ORDER'])){ foreach ($this->parsed['ORDER'] as $vv) { if($vv['base_expr']==$v['alias']['name']){ $agg_orderby['order'][$vv['base_expr']]=$vv['direction']; } } } } } } } $tmp_tree=$this->listtree($agg,$aggs,$agg_orderby); $this->agg['aggs']=$tmp_tree[0]; } private function orderby($arr){ if(isset($this->parsed['SELECT']) && !empty($this->parsed['SELECT'])){ foreach ($this->parsed['SELECT'] as $v) { foreach ($arr as $kk=>$vv) { if($v['alias']){ if($v['alias']['name']==$vv['base_expr']){ unset($arr[$kk]); } } } } } foreach ($arr as &$va) { if(strrpos($va['base_expr'],".")){ $term_tmp_arr=explode(".",$va['base_expr']); if($term_tmp_arr[1]!='keyword'){ $termk=$term_tmp_arr[1]; }else{ $termk=$va['base_expr']; } }else{ $termk=$va['base_expr']; } $this->sort['sort'][][$termk]['order']=$va['direction']; } } private function limit($arr){ if(!isset($arr['offset'])){ $this->limit['from']=0; }else{ $this->limit['from']=$arr['offset']; } if(!isset($arr['rowcount'])){ $this->limit['size']=10; }else{ $this->limit['size']=$arr['rowcount']; } } private function haveext($arr,$i){ if(!is_numeric($arr[$i]['base_expr'])){ $lowerstr = strtolower($arr[$i]['base_expr']); }else{ $lowerstr = $arr[$i]['base_expr']; } switch ($lowerstr) { case '=': if($arr[$i-1]['base_expr']==$arr[$i+1]['base_expr']){ break; } if(isset($arr[$i+2]['base_expr']) && strtolower($arr[$i+2]['base_expr'])=='or' || isset($arr[$i-2]['base_expr']) && strtolower($arr[$i-2]['base_expr'])=='or'){ if(strrpos($arr[$i-1]['base_expr'],".")){ $term_tmp_arr=explode(".",$arr[$i-1]['base_expr']); $termk=$term_tmp_arr[1]; }else{ $termk=$arr[$i-1]['base_expr']; } $tmp_da_str=str_replace('"','',$arr[$i+1]['base_expr']); $tmp_da_str=str_replace("'","",$tmp_da_str); if(isset($this->havingagg['having']['filter']) && $this->tmp_lock_have!='' && $this->tmp_lock_have!=$lowerstr){ if($this->tmp_str_filter_have==''){ $this->count_tmp_filter_have++; }else if($this->tmp_str_filter_have!='' && $this->tmp_str_filter_have!=$termk){ $this->count_tmp_filter_have++; } }else if($this->tmp_str_have!='' && $this->tmp_str_have!=$termk){ $this->count_tmp_filter_have++; } if(isset($this->havingagg['having']['filter']['bool']['must'][0]) && $this->tmp_lock_str_have!='' && $this->tmp_lock_str_have!=$lowerstr){ if($this->tmp_str_have==''){ $this->count_tmp_have++; }else if($this->tmp_str_have!='' && $this->tmp_str_have!=$termk){ $this->count_tmp_have++; } } if(isset($this->parsed['UPDATE']) && !empty($this->parsed['UPDATE'])){ $this->url .=$tmp_da_str ."/_update?pretty"; }else{ if(!is_numeric($arr[$i+1]['base_expr']) && $this->version_es=='8.x'){ $term['match_phrase'][$termk.'.keyword']['query']=$tmp_da_str; $this->havingagg['having']['filter']['bool']['must'][$this->count_tmp_have]['bool']['should'][]=$term; }else{ $term['match_phrase'][$termk]['query']=$tmp_da_str; $this->havingagg['having']['filter']['bool']['must'][$this->count_tmp_have]['bool']['should'][]=$term; } unset($term['match_phrase']); } $this->tmp_lock=$lowerstr; $this->tmp_lock_str=$lowerstr; }else if(isset($arr[$i+2]['base_expr']) && strtolower($arr[$i+2]['base_expr'])=='and' || isset($arr[$i-2]['base_expr']) && strtolower($arr[$i-2]['base_expr'])=='and'){ if(strrpos($arr[$i-1]['base_expr'],".")){ $term_tmp_arr=explode(".",$arr[$i-1]['base_expr']); $termk=$term_tmp_arr[1]; }else{ $termk=$arr[$i-1]['base_expr']; } $tmp_da_str=str_replace('"','',$arr[$i+1]['base_expr']); $tmp_da_str=str_replace("'","",$tmp_da_str); if(isset($this->havingagg['having']['filter']) && $this->tmp_lock_str_have!='' && $this->tmp_lock_str_have!=$lowerstr){ if($this->tmp_str_have==''){ $this->count_tmp_have++; }else if($this->tmp_str_have!='' && $this->tmp_str_have!=$termk){ $this->count_tmp_have++; } } if(isset($this->parsed['UPDATE']) && !empty($this->parsed['UPDATE'])){ $this->url .=$tmp_da_str ."/_update?pretty"; }else{ if(isset($this->havingagg['having']['filter']) && $this->tmp_lock_have!='' && $this->tmp_lock_have!=$lowerstr){ if($this->tmp_str_filter_have==''){ $this->count_tmp_filter_have++; }else if($this->tmp_str_filter_have!='' && $this->tmp_str_filter_have!=$termk){ $this->count_tmp_filter_have++; } }else if($this->tmp_str_have!='' && $this->tmp_str_have!=$termk){ $this->count_tmp_filter_have++; } if(!is_numeric($arr[$i+1]['base_expr']) && $this->version_es=='8.x'){ $term['match_phrase'][$termk.'.keyword']['query']=$tmp_da_str; $this->havingagg['having']['filter']['bool']['must'][]=$term; }else{ $term['match_phrase'][$termk]['query']=$tmp_da_str; $this->havingagg['having']['filter']['bool']['must'][]=$term; } unset($term['match_phrase']); } $this->tmp_lock_str_have=$lowerstr; } $this->tmp_lock_have=$lowerstr; $this->tmp_str_have=$lowerstr; break; case 'in': if(strtolower($arr[$i-1]['base_expr'])=='not'){ break; } if(strrpos($arr[$i-1]['base_expr'],".")){ $term_tmp_arr=explode(".",$arr[$i-1]['base_expr']); $termk=$term_tmp_arr[1]; }else{ $termk=$arr[$i-1]['base_expr']; } if(isset($this->havingagg['having']['filter']) && $this->tmp_lock_have!='' && $this->tmp_lock_have==$lowerstr){ if($this->tmp_str_filter_have==''){ $this->count_tmp_filter_have++; }else if($this->tmp_str_filter_have!='' && $this->tmp_str_filter_have!=$termk){ $this->count_tmp_filter_have++; } }else if($this->tmp_str_have!='' && $this->tmp_str_have!=$termk){ $this->count_tmp_filter_have++; } if(isset($arr[$i+1]['sub_tree']) && !empty($arr[$i+1]['sub_tree'])){ foreach ($arr[$i+1]['sub_tree'] as &$vv) { if(!is_numeric($vv['base_expr']) && $this->version_es=='5.x'){ $termk .='.keyword'; } $tmp_da_str=str_replace('"','',$vv['base_expr']); $tmp_da_str=str_replace("'","",$tmp_da_str); $this->havingagg['having']['filter']['terms'][$termk][]=$tmp_da_str; } } $this->tmp_lock_have=$lowerstr; $this->tmp_str_have=$termk; unset($termk); break; case 'not': if(strrpos($arr[$i-1]['base_expr'],".")){ $term_tmp_arr=explode(".",$arr[$i-1]['base_expr']); $termk=$term_tmp_arr[1]; }else{ $termk=$arr[$i-1]['base_expr']; } if(isset($this->havingagg['having']['filter']) && $this->tmp_lock_have!='' && $this->tmp_lock_have==$lowerstr){ if($this->tmp_str_filter_have==''){ $this->count_tmp_filter_have++; }else if($this->tmp_str_filter_have!='' && $this->tmp_str_filter_have!=$termk){ $this->count_tmp_filter_have++; } }else if($this->tmp_str_have!='' && $this->tmp_str_have!=$termk){ $this->count_tmp_filter_have++; } if(isset($arr[$i+2]['sub_tree']) && !empty($arr[$i+2]['sub_tree'])){ foreach ($arr[$i+2]['sub_tree'] as &$vv) { if(!is_numeric($vv['base_expr']) && $this->version_es=='5.x'){ $termk .='.keyword'; } $tmp_da_str=str_replace('"','',$vv['base_expr']); $tmp_da_str=str_replace("'","",$tmp_da_str); $this->havingagg['having']['filter']['bool']['must_not']['terms'][$termk][]=$tmp_da_str; } } $this->tmp_lock_have=$lowerstr; $this->tmp_str_have=$termk; unset($termk); break; case '>': if(strrpos($arr[$i-1]['base_expr'],".")){ $term_tmp_arr=explode(".",$arr[$i-1]['base_expr']); $termk=$term_tmp_arr[1]; }else{ $termk=$arr[$i-1]['base_expr']; } $tmp_da_str=str_replace('"','',$arr[$i+1]['base_expr']); $tmp_da_str=str_replace("'","",$tmp_da_str); $is_date=strtotime($tmp_da_str)?strtotime($tmp_da_str):false; if(isset($arr[$i+2]['base_expr']) && strtolower($arr[$i+2]['base_expr'])=='or' || isset($arr[$i-2]['base_expr']) && strtolower($arr[$i-2]['base_expr'])=='or'){ if(isset($this->havingagg['having']['filter']) && $this->tmp_lock_have!='' && $this->tmp_lock_have==$lowerstr){ if($this->tmp_str_filter_have==''){ $this->count_tmp_filter_have++; }else if($this->tmp_str_filter_have!='' && $this->tmp_str_filter_have!=$termk){ $this->count_tmp_filter_have++; } } if(isset($this->havingagg['having']['filter']['bool']['must'][0]) && $this->tmp_lock_fi_have!='' && $this->tmp_lock_fi_have==$lowerstr){ if($this->tmp_fi_have==''){ $this->count_fi_have++; }else if($this->tmp_fi_have!='' && $this->tmp_fi_have!=$termk){ $this->count_fi_have++; } } if(isset($this->havingagg['having']['filter']['bool']['must'][$this->count_fi_have]['bool']['should'][0]) && $this->tmp_lock_range_have!=''){ if($this->tmp_str_range_have==''){ $this->count_tmp_range_have++; }else if($this->tmp_str_range_have!='' && $this->tmp_str_range_have!=$termk){ $this->count_tmp_range_have++; } } $this->havingagg['having']['filter']['bool']['must'][$this->count_fi_have]['bool']['should'][$this->count_tmp_range_have]['range'][$termk]['gt']=$tmp_da_str; if(!isset($this->havingagg['having']['filter']['bool']['must'][$this->count_fi_have]['bool']['should'][$this->count_tmp_range_have]['range'][$termk]['time_zone']) && $is_date){ $this->havingagg['having']['filter']['bool']['must'][$this->count_fi_have]['bool']['should'][$this->count_tmp_range_have]['range'][$termk]['time_zone']="+08:00"; } }else{ if(isset($this->havingagg['having']['filter']) && $this->tmp_lock_str_have!='' && $this->tmp_lock_str_have!=$lowerstr){ if($this->tmp_str_have==''){ $this->count_tmp_have++; }else if($this->tmp_str_have!='' && $this->tmp_str_have!=$termk){ $this->count_tmp_have++; } } if(!isset($this->havingagg['having']['filter']['range']) && $this->tmp_lock_have!='' ){ if($this->tmp_str_filter_have==''){ $this->count_tmp_filter_have++; }else if($this->tmp_str_filter_have!='' && $this->tmp_str_filter_have!=$termk){ $this->count_tmp_filter_have++; } }else if($this->tmp_str_have!='' && $this->tmp_str_have!=$termk){ $this->count_tmp_filter_have++; } $this->havingagg['having']['filter']['range'][$termk]['gt']=$tmp_da_str; if(!isset($this->havingagg['having']['filter']['range'][$termk]['time_zone']) && $is_date){ $this->havingagg['having']['filter']['range'][$termk]['time_zone']="+08:00"; } } $this->tmp_str_have=$termk; $this->tmp_lock_str_have=$lowerstr; $this->tmp_lock_have=$lowerstr; $this->tmp_lock_range_have=$lowerstr; $this->tmp_lock_fi_have=$lowerstr; break; case '>=': if(strrpos($arr[$i-1]['base_expr'],".")){ $term_tmp_arr=explode(".",$arr[$i-1]['base_expr']); $termk=$term_tmp_arr[1]; }else{ $termk=$arr[$i-1]['base_expr']; } $tmp_da_str=str_replace('"','',$arr[$i+1]['base_expr']); $tmp_da_str=str_replace("'","",$tmp_da_str); $is_date=strtotime($tmp_da_str)?strtotime($tmp_da_str):false; if(isset($arr[$i+2]['base_expr']) && strtolower($arr[$i+2]['base_expr'])=='or' || isset($arr[$i-2]['base_expr']) && strtolower($arr[$i-2]['base_expr'])=='or'){ if(isset($this->havingagg['having']['filter']) && $this->tmp_lock_have!='' && $this->tmp_lock_have==$lowerstr){ if($this->tmp_str_filter_have==''){ $this->count_tmp_filter_have++; }else if($this->tmp_str_filter_have!='' && $this->tmp_str_filter_have!=$termk){ $this->count_tmp_filter_have++; } } if(isset($this->havingagg['having']['filter']['bool']['must'][0]) && $this->tmp_lock_fi_have!='' && $this->tmp_lock_fi_have==$lowerstr){ if($this->tmp_fi_have==''){ $this->count_fi_have++; }else if($this->tmp_fi_have!='' && $this->tmp_fi_have!=$termk){ $this->count_fi_have++; } } if(isset($this->havingagg['having']['filter']['bool']['must'][$this->count_fi_have]['bool']['should'][0]) && $this->tmp_lock_range_have!='' ){ if($this->tmp_str_range_have==''){ $this->count_tmp_range_have++; }else if($this->tmp_str_range_have!='' && $this->tmp_str_range_have!=$termk){ $this->count_tmp_range_have++; } } $this->havingagg['having']['filter']['bool']['must'][$this->count_fi_have]['bool']['should'][$this->count_tmp_range_have]['range'][$termk]['gte']=$tmp_da_str; if(!isset($this->havingagg['having']['filter']['bool']['must'][$this->count_fi_have]['bool']['should'][$this->count_tmp_range_have]['range'][$termk]['time_zone']) && $is_date){ $this->havingagg['having']['filter']['bool']['must'][$this->count_fi_have]['bool']['should'][$this->count_tmp_range_have]['range'][$termk]['time_zone']="+08:00"; } }else{ if(isset($this->havingagg['having']['filter']) && $this->tmp_lock_str_have!='' && $this->tmp_lock_str_have!=$lowerstr){ if($this->tmp_str_have==''){ $this->count_tmp_have++; }else if($this->tmp_str_have!='' && $this->tmp_str_have!=$termk){ $this->count_tmp_have++; } } if(!isset($this->havingagg['having']['filter']['range']) && $this->tmp_lock_have!='' ){ if($this->tmp_str_filter_have==''){ $this->count_tmp_filter_have++; }else if($this->tmp_str_filter_have!='' && $this->tmp_str_filter_have!=$termk){ $this->count_tmp_filter_have++; } }else if($this->tmp_str_have!='' && $this->tmp_str_have!=$termk){ $this->count_tmp_filter_have++; } $this->havingagg['having']['filter']['range'][$termk]['gte']=$tmp_da_str; if(!isset($this->havingagg['having']['filter']['range'][$termk]['time_zone']) && $is_date){ $this->havingagg['having']['filter']['range'][$termk]['time_zone']="+08:00"; } } $this->tmp_str_have=$termk; $this->tmp_lock_str_have=$lowerstr; $this->tmp_lock_have=$lowerstr; $this->tmp_lock_range_have=$lowerstr; $this->tmp_lock_fi_have=$lowerstr; break; case '<': if(strrpos($arr[$i-1]['base_expr'],".")){ $term_tmp_arr=explode(".",$arr[$i-1]['base_expr']); $termk=$term_tmp_arr[1]; }else{ $termk=$arr[$i-1]['base_expr']; } $tmp_da_str=str_replace('"','',$arr[$i+1]['base_expr']); $tmp_da_str=str_replace("'","",$tmp_da_str); $is_date=strtotime($tmp_da_str)?strtotime($tmp_da_str):false; if(isset($arr[$i+2]['base_expr']) && strtolower($arr[$i+2]['base_expr'])=='or' || isset($arr[$i-2]['base_expr']) && strtolower($arr[$i-2]['base_expr'])=='or'){ if(isset($this->havingagg['having']['filter']) && $this->tmp_lock_have!='' && $this->tmp_lock_have==$lowerstr){ if($this->tmp_str_filter_have==''){ $this->count_tmp_filter_have++; }else if($this->tmp_str_filter_have!='' && $this->tmp_str_filter_have!=$termk){ $this->count_tmp_filter_have++; } } if(isset($this->havingagg['having']['filter']['bool']['must'][0]) && $this->tmp_lock_fi_have!='' && $this->tmp_lock_fi_have==$lowerstr){ if($this->tmp_fi_have==''){ $this->count_fi_have++; }else if($this->tmp_fi_have!='' && $this->tmp_fi_have!=$termk){ $this->count_fi_have++; } } if(isset($this->havingagg['having']['filter']['bool']['must'][$this->count_fi_have]['bool']['should'][0]) && $this->tmp_lock_range_have!=''){ if($this->tmp_str_range_have==''){ $this->count_tmp_range_have++; }else if($this->tmp_str_range_have!='' && $this->tmp_str_range_have!=$termk){ $this->count_tmp_range_have++; } } $this->havingagg['having']['filter']['must'][$this->count_fi_have]['bool']['should'][$this->count_tmp_range_have]['range'][$termk]['lt']=$tmp_da_str; if(!isset($this->havingagg['having']['filter']['bool']['must'][$this->count_fi_have]['bool']['should'][$this->count_tmp_range_have]['range'][$termk]['time_zone']) && $is_date){ $this->havingagg['having']['filter']['bool']['must'][$this->count_fi_have]['bool']['should'][$this->count_tmp_range_have]['range'][$termk]['time_zone']="+08:00"; } }else{ if(isset($this->havingagg['having']['filter']) && $this->tmp_lock_str_have!='' && $this->tmp_lock_str_have==$lowerstr){ if($this->tmp_str_have==''){ $this->count_tmp_have++; } } if(!isset($this->havingagg['having']['filter']['range']) && $this->tmp_lock_have!='' ){ if($this->tmp_str_filter_have==''){ $this->count_tmp_filter_have++; }else if($this->tmp_str_filter_have!='' && $this->tmp_str_filter_have!=$termk){ $this->count_tmp_filter_have++; } }else if($this->tmp_str_have!='' && $this->tmp_str_have!=$termk){ $this->count_tmp_filter_have++; } $this->havingagg['having']['filter']['range'][$termk]['lt']=$tmp_da_str; if(!isset($this->havingagg['having']['filter']['range'][$termk]['time_zone']) && $is_date){ $this->havingagg['having']['filter']['range'][$termk]['time_zone']="+08:00"; } } $this->tmp_str_have=$termk; $this->tmp_lock_str_have=$lowerstr; $this->tmp_lock_have=$lowerstr; $this->tmp_lock_range_have=$lowerstr; $this->tmp_lock_fi_have=$lowerstr; break; case '<=': if(strrpos($arr[$i-1]['base_expr'],".")){ $term_tmp_arr=explode(".",$arr[$i-1]['base_expr']); $termk=$term_tmp_arr[1]; }else{ $termk=$arr[$i-1]['base_expr']; } $tmp_da_str=str_replace('"','',$arr[$i+1]['base_expr']); $tmp_da_str=str_replace("'","",$tmp_da_str); $is_date=strtotime($tmp_da_str)?strtotime($tmp_da_str):false; if(isset($arr[$i+2]['base_expr']) && strtolower($arr[$i+2]['base_expr'])=='or' || isset($arr[$i-2]['base_expr']) && strtolower($arr[$i-2]['base_expr'])=='or'){ if(isset($this->havingagg['having']['filter']) && $this->tmp_lock_have!='' && $this->tmp_lock_have==$lowerstr){ if($this->tmp_str_filter_have==''){ $this->count_tmp_filter_have++; }else if($this->tmp_str_filter_have!='' && $this->tmp_str_filter_have!=$termk){ $this->count_tmp_filter_have++; } } if(isset($this->havingagg['having']['filter']['bool']['must'][0]) && $this->tmp_lock_fi_have!='' && $this->tmp_lock_fi_have==$lowerstr){ if($this->tmp_fi_have==''){ $this->count_fi_have++; }else if($this->tmp_fi_have!='' && $this->tmp_fi_have!=$termk){ $this->count_fi_have++; } } if(isset($this->havingagg['having']['filter']['bool']['must'][$this->count_fi_have]['bool']['should'][0]) && $this->tmp_lock_range_have!='' ){ if($this->tmp_str_range_have==''){ $this->count_tmp_range_have++; }else if($this->tmp_str_range_have!='' && $this->tmp_str_range_have!=$termk){ $this->count_tmp_range_have++; } } $this->havingagg['having']['filter']['bool']['must'][$this->count_fi_have]['bool']['should'][$this->count_tmp_range_have]['range'][$termk]['lte']=$tmp_da_str; if(!isset($this->havingagg['having']['filter']['bool']['must'][$this->count_fi_have]['bool']['should'][$this->count_tmp_range_have]['range'][$termk]['time_zone']) && $is_date){ $this->havingagg['having']['bool']['must'][$this->count_fi_have]['bool']['should'][$this->count_tmp_range_have]['range'][$termk]['time_zone']="+08:00"; } }else{ if(isset($this->havingagg['having']['filter']) && $this->tmp_lock_str_have!='' && $this->tmp_lock_str_have==$lowerstr){ if($this->tmp_str_have==''){ $this->count_tmp_have++; }else if($this->tmp_str_have!='' && $this->tmp_str_have!=$termk){ $this->count_tmp_have++; } } if(!isset($this->havingagg['having']['filter']['range']) && $this->tmp_lock_have!=''){ if($this->tmp_str_filter_have==''){ $this->count_tmp_filter_have++; }else if($this->tmp_str_filter_have!='' && $this->tmp_str_filter_have!=$termk){ $this->count_tmp_filter_have++; } }else if($this->tmp_str_have!='' && $this->tmp_str_have!=$termk){ $this->count_tmp_filter_have++; } $this->havingagg['having']['filter']['range'][$termk]['lte']=$tmp_da_str; if(!isset($this->havingagg['having']['filter']['range'][$termk]['time_zone']) && $is_date){ $this->havingagg['having']['filter']['range'][$termk]['time_zone']="+08:00"; } } $this->tmp_str_have=$termk; $this->tmp_lock_str_have=$lowerstr; $this->tmp_lock_have=$lowerstr; $this->tmp_lock_range_have=$lowerstr; $this->tmp_lock_fi_have=$lowerstr; break; case 'like': if(strrpos($arr[$i-1]['base_expr'],".")){ $term_tmp_arr=explode(".",$arr[$i-1]['base_expr']); $termk=$term_tmp_arr[1]; }else{ $termk=$arr[$i-1]['base_expr']; } $tmp_la_str=str_replace('"','',$arr[$i+1]['base_expr']); $tmp_la_str=str_replace("'","",$tmp_la_str); if(isset($arr[$i+2]['base_expr']) && strtolower($arr[$i+2]['base_expr'])=='or' || isset($arr[$i-2]['base_expr']) && strtolower($arr[$i-2]['base_expr'])=='or'){ if(isset($this->havingagg['having']['filter']) && $this->tmp_lock_have!='' && $this->tmp_lock_have!=$lowerstr){ if($this->tmp_str_filter_have==''){ $this->count_tmp_filter_have++; }else if($this->tmp_str_filter_have!='' && $this->tmp_str_filter_have!=$termk){ $this->count_tmp_filter_have++; } } if(isset($this->havingagg['having']['filter']['bool']['must'][0]) && $this->tmp_lock_fi_have!='' && $this->tmp_lock_fi_have!=$lowerstr){ if($this->tmp_fi_have==''){ $this->count_fi_have++; }else if($this->tmp_fi_have!='' && $this->tmp_fi_have!=$termk){ $this->count_fi_have++; } } if(!is_numeric($arr[$i+1]['base_expr']) && $this->version_es=='8.x'){ //$term['match_phrase'][$termk.'.keyword']=str_replace("%","",$tmp_la_str); $term['wildcard'][$termk.'.keyword']=str_replace("%","*",$tmp_la_str); $this->havingagg['having']['filter']['bool']['must'][$this->count_fi_have]['bool']['should'][]=$term; }else{ //$term['match_phrase'][$termk]=str_replace("%","",$tmp_la_str);\ $term['wildcard'][$termk]=str_replace("%","*",$tmp_la_str); $this->havingagg['having']['filter']['bool']['must'][$this->count_fi_have]['bool']['should'][]=$term; } }else{ if(isset($this->havingagg['having']['filter']) && $this->tmp_lock_str_have!='' && $this->tmp_lock_str_have!=$lowerstr){ if($this->tmp_str_have==''){ $this->count_tmp_have++; }else if($this->tmp_str_have!='' && $this->tmp_str_have!=$termk){ $this->count_tmp_have++; } } if(isset($this->havingagg['having']['filter']) && $this->tmp_lock_have!='' && $this->tmp_lock_have!=$lowerstr){ if($this->tmp_str_filter_have==''){ $this->count_tmp_filter_have++; }else if($this->tmp_str_filter_have!='' && $this->tmp_str_filter_have!=$termk){ $this->count_tmp_filter_have++; } } if(!is_numeric($arr[$i+1]['base_expr']) && $this->version_es=='8.x'){ //$term['match_phrase'][$termk.'.keyword']=str_replace("%","",$tmp_la_str); //wildcard $term['wildcard'][$termk.'.keyword']=str_replace("%","*",$tmp_la_str); $this->havingagg['having']['filter']['must'][$this->count_tmp_have]['bool']['must'][]=$term; }else{ //$term['match_phrase'][$termk]=str_replace("%","",$tmp_la_str); $term['wildcard'][$termk]=str_replace("%","*",$tmp_la_str); $this->havingagg['having']['filter']['bool']['must'][]=$term; } } unset($term['wildcard']); $this->tmp_lock_str_have=$lowerstr; $this->tmp_lock_have=$lowerstr; $this->tmp_lock_fi_have=$lowerstr; break; case 'between': if(strrpos($arr[$i-1]['base_expr'],".")){ $term_tmp_arr=explode(".",$arr[$i-1]['base_expr']); $termk=$term_tmp_arr[1]; }else{ $termk=$arr[$i-1]['base_expr']; } if(isset($this->havingagg['having']['filter']) && $this->tmp_lock_str_have!='' && $this->tmp_lock_str_have!=$lowerstr){ if($this->tmp_str_have==''){ $this->count_tmp_have++; }else if($this->tmp_str_have!='' && $this->tmp_str_have!=$termk){ $this->count_tmp_have++; } } if(isset($this->havingagg['having']['filter']) && $this->tmp_lock_have!='' && $this->tmp_lock_have!=$lowerstr){ if($this->tmp_str_filter_have==''){ $this->count_tmp_filter_have++; }else if($this->tmp_str_filter_have!='' && $this->tmp_str_filter_have!=$termk){ $this->count_tmp_filter_have++; } } $tmp_da_str=str_replace('"','',$arr[$i+1]['base_expr']); $tmp_da_str=str_replace("'","",$tmp_da_str); $is_date=strtotime($tmp_da_str)?strtotime($tmp_da_str):false; $this->havingagg['having']['filter']['range'][$termk]['gte']=$tmp_da_str; if(!isset($this->havingagg['having']['filter']['range'][$termk]['time_zone']) && $is_date){ $this->havingagg['having']['filter']['range'][$termk]['time_zone']="+08:00"; } $tmp_da_str=str_replace('"','',$arr[$i+3]['base_expr']); $tmp_da_str=str_replace("'","",$tmp_da_str); $this->havingagg['having']['filter']['range'][$termk]['lte']=$tmp_da_str; $this->tmp_str_have=$termk; $this->tmp_lock_str_have=$lowerstr; $this->tmp_lock_have=$lowerstr; break; } } private function having($arr){ if(isset($this->parsed['HAVING']) && !empty($this->parsed['HAVING'])){ for ($i=0; $i haveext($arr,$i); } if(isset($this->parsed['GROUP']) && !empty($this->parsed['GROUP'])){ }else{ $this->Builderarr['aggs']['having']=$this->havingagg['having']; } } } private function select($arr){ if(isset($this->parsed['GROUP']) && !empty($this->parsed['GROUP'])){ }else{ $tmp_source=array(); foreach ($arr as $k => $v) { if($v['expr_type']=='aggregate_function'){ if(strrpos($v['sub_tree'][0]['base_expr'],".")){ $term_tmp_arrs=explode(".",$v['sub_tree'][0]['base_expr']); if($term_tmp_arrs[1]=='*'){ continue; } if($term_tmp_arrs[1]!='keyword'){ array_push($tmp_source,$term_tmp_arrs[1]); if(isset($v['alias']['name'])){ $this->Builderarr['aggs'][$v['alias']['name']]['stats']['field']=$term_tmp_arrs[1]; }else{ $this->Builderarr['aggs'][$v['sub_tree'][0]['base_expr']]['stats']['field']=$term_tmp_arrs[1]; } }else{ array_push($tmp_source,$v['sub_tree'][0]['base_expr']); if(isset($v['alias']['name'])){ $this->Builderarr['aggs'][$v['alias']['name']]['cardinality']['field']=$v['sub_tree'][0]['base_expr']; }else{ $this->Builderarr['aggs'][$v['sub_tree'][0]['base_expr']]['cardinality']['field']=$v['sub_tree'][0]['base_expr']; } } }else{ if($v['sub_tree'][0]['base_expr']=='*'){ continue; } array_push($tmp_source,$v['sub_tree'][0]['base_expr']); if(isset($v['alias']['name'])){ $this->Builderarr['aggs'][$v['alias']['name']]['stats']['field']=$v['sub_tree'][0]['base_expr']; }else{ $this->Builderarr['aggs'][$v['sub_tree'][0]['base_expr']]['stats']['field']=$v['sub_tree'][0]['base_expr']; } } }else{ array_push($tmp_source,$v['base_expr']); } } if(!empty($tmp_source)){ $this->Builderarr['_source']['include']=$tmp_source; } } } private function updateset($arr){ foreach ($arr as &$v) { if($v['sub_tree']){ $tmp_sub[$v['sub_tree'][0]['base_expr']]=$v['sub_tree'][2]['base_expr']; $this->Builderarr['doc']=$tmp_sub; unset($tmp_sub); } } } } ?> ================================================ FILE: src/library/builders/AliasBuilder.php ================================================ * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * @version SVN: $Id: AliasBuilder.php 830 2013-12-18 09:35:42Z phosco@gmx.de $ * */ /** * This class implements the builder for aliases. * You can overwrite all functions to achieve another handling. * * @author André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ class AliasBuilder { public function hasAlias($parsed) { return isset($parsed['alias']); } public function build($parsed) { if (!isset($parsed['alias']) || $parsed['alias'] === false) { return ""; } $sql = ""; if ($parsed['alias']['as']) { $sql .= " as"; } $sql .= " " . $parsed['alias']['name']; return $sql; } } ?> ================================================ FILE: src/library/builders/CharacterSetBuilder.php ================================================ * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * @version SVN: $Id: CharacterSetBuilder.php 914 2014-01-08 11:33:25Z phosco@gmx.de $ * */ require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; require_once dirname(__FILE__) . '/../exceptions/UnableToCreateSQLException.php'; require_once dirname(__FILE__) . '/ColumnListBuilder.php'; require_once dirname(__FILE__) . '/ConstraintBuilder.php'; require_once dirname(__FILE__) . '/ReservedBuilder.php'; require_once dirname(__FILE__) . '/IndexTypeBuilder.php'; /** * This class implements the builder for the CHARACTER SET statement part of CREATE TABLE. * You can overwrite all functions to achieve another handling. * * @author André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ class CharacterSetBuilder { protected function buildConstant($parsed) { $builder = new ConstantBuilder(); return $builder->build($parsed); } protected function buildOperator($parsed) { $builder = new OperatorBuilder(); return $builder->build($parsed); } protected function buildReserved($parsed) { $builder = new ReservedBuilder(); return $builder->build($parsed); } public function build($parsed) { if ($parsed['expr_type'] !== ExpressionType::CHARSET) { return ""; } $sql = ""; foreach ($parsed['sub_tree'] as $k => $v) { $len = strlen($sql); $sql .= $this->buildOperator($v); $sql .= $this->buildReserved($v); $sql .= $this->buildConstant($v); if ($len == strlen($sql)) { throw new UnableToCreateSQLException('CREATE TABLE options CHARACTER SET subtree', $k, $v, 'expr_type'); } $sql .= " "; } return substr($sql, 0, -1); } } ?> ================================================ FILE: src/library/builders/CheckBuilder.php ================================================ * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * @version SVN: $Id: CheckBuilder.php 830 2013-12-18 09:35:42Z phosco@gmx.de $ * */ require_once dirname(__FILE__) . '/../exceptions/UnableToCreateSQLException.php'; require_once dirname(__FILE__) . '/ReservedBuilder.php'; require_once dirname(__FILE__) . '/SelectBracketExpressionBuilder.php'; require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; /** * This class implements the builder for the CHECK statement part of CREATE TABLE. * You can overwrite all functions to achieve another handling. * * @author André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ class CheckBuilder { protected function buildSelectBracketExpression($parsed) { $builder = new SelectBracketExpressionBuilder(); return $builder->build($parsed); } protected function buildReserved($parsed) { $builder = new ReservedBuilder(); return $builder->build($parsed); } public function build($parsed) { if ($parsed['expr_type'] !== ExpressionType::CHECK) { return ""; } $sql = ""; foreach ($parsed['sub_tree'] as $k => $v) { $len = strlen($sql); $sql .= $this->buildReserved($v); $sql .= $this->buildSelectBracketExpression($v); if ($len == strlen($sql)) { throw new UnableToCreateSQLException('CREATE TABLE check subtree', $k, $v, 'expr_type'); } $sql .= " "; } return substr($sql, 0, -1); } } ?> ================================================ FILE: src/library/builders/CollationBuilder.php ================================================ * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * @version SVN: $Id: CollationBuilder.php 922 2014-01-08 12:19:35Z phosco@gmx.de $ * */ require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; require_once dirname(__FILE__) . '/../exceptions/UnableToCreateSQLException.php'; require_once dirname(__FILE__) . '/ConstantBuilder.php'; require_once dirname(__FILE__) . '/OperatorBuilder.php'; require_once dirname(__FILE__) . '/ReservedBuilder.php'; /** * This class implements the builder for the collation statement part of CREATE TABLE. * You can overwrite all functions to achieve another handling. * * @author André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ class CollationBuilder { protected function buildOperator($parsed) { $builder = new OperatorBuilder(); return $builder->build($parsed); } protected function buildConstant($parsed) { $builder = new ConstantBuilder(); return $builder->build($parsed); } protected function buildReserved($parsed) { $builder = new ReservedBuilder(); return $builder->build($parsed); } public function build($parsed) { if ($parsed['expr_type'] !== ExpressionType::COLLATE) { return ""; } $sql = ""; foreach ($parsed['sub_tree'] as $k => $v) { $len = strlen($sql); $sql .= $this->buildReserved($v); $sql .= $this->buildOperator($v); $sql .= $this->buildConstant($v); if ($len == strlen($sql)) { throw new UnableToCreateSQLException('CREATE TABLE options collation subtree', $k, $v, 'expr_type'); } $sql .= " "; } return substr($sql, 0, -1); } } ?> ================================================ FILE: src/library/builders/ColumnDefinitionBuilder.php ================================================ * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * @version SVN: $Id: ColumnDefinitionBuilder.php 830 2013-12-18 09:35:42Z phosco@gmx.de $ * */ require_once dirname(__FILE__) . '/../exceptions/UnableToCreateSQLException.php'; require_once dirname(__FILE__) . '/ColumnReferenceBuilder.php'; require_once dirname(__FILE__) . '/ColumnTypeBuilder.php'; require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; /** * This class implements the builder for the columndefinition statement part * of CREATE TABLE. You can overwrite all functions to achieve another handling. * * @author André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ class ColumnDefinitionBuilder { protected function buildColRef($parsed) { $builder = new ColumnReferenceBuilder(); return $builder->build($parsed); } protected function buildColumnType($parsed) { $builder = new ColumnTypeBuilder(); return $builder->build($parsed); } public function build($parsed) { if ($parsed['expr_type'] !== ExpressionType::COLDEF) { return ""; } $sql = ""; foreach ($parsed['sub_tree'] as $k => $v) { $len = strlen($sql); $sql .= $this->buildColRef($v); $sql .= $this->buildColumnType($v); if ($len == strlen($sql)) { throw new UnableToCreateSQLException('CREATE TABLE primary key subtree', $k, $v, 'expr_type'); } $sql .= " "; } return substr($sql, 0, -1); } } ?> ================================================ FILE: src/library/builders/ColumnListBuilder.php ================================================ * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * @version SVN: $Id: ColumnListBuilder.php 894 2013-12-31 00:27:03Z phosco@gmx.de $ * */ require_once dirname(__FILE__) . '/../exceptions/UnableToCreateSQLException.php'; require_once dirname(__FILE__) . '/IndexColumnBuilder.php'; require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; /** * This class implements the builder for column-list parts of CREATE TABLE. * You can overwrite all functions to achieve another handling. * * @author André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ class ColumnListBuilder { protected function buildIndexColumn($parsed) { $builder = new IndexColumnBuilder(); return $builder->build($parsed); } public function build($parsed) { if ($parsed['expr_type'] !== ExpressionType::COLUMN_LIST) { return ""; } $sql = ""; foreach ($parsed['sub_tree'] as $k => $v) { $len = strlen($sql); $sql .= $this->buildIndexColumn($v); if ($len == strlen($sql)) { throw new UnableToCreateSQLException('CREATE TABLE column-list subtree', $k, $v, 'expr_type'); } $sql .= " "; } return "(" . substr($sql, 0, -1) . ")"; } } ?> ================================================ FILE: src/library/builders/ColumnReferenceBuilder.php ================================================ * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * @version SVN: $Id: ColumnReferenceBuilder.php 830 2013-12-18 09:35:42Z phosco@gmx.de $ * */ require_once dirname(__FILE__) . '/AliasBuilder.php'; require_once dirname(__FILE__) . '/DirectionBuilder.php'; require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; /** * This class implements the builder for column references. * You can overwrite all functions to achieve another handling. * * @author André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ class ColumnReferenceBuilder { protected function buildDirection($parsed) { $builder = new DirectionBuilder(); return $builder->build($parsed); } protected function buildAlias($parsed) { $builder = new AliasBuilder(); return $builder->build($parsed); } public function build($parsed) { if ($parsed['expr_type'] !== ExpressionType::COLREF) { return ""; } $sql = $parsed['base_expr']; $sql .= $this->buildAlias($parsed); $sql .= $this->buildDirection($parsed); return $sql; } } ?> ================================================ FILE: src/library/builders/ColumnTypeBracketExpressionBuilder.php ================================================ * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * @version SVN: $Id: ColumnTypeBracketExpressionBuilder.php 934 2014-01-08 13:57:16Z phosco@gmx.de $ * */ require_once dirname(__FILE__) . '/SubTreeBuilder.php'; require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; /** * This class implements the builder for bracket expressions within a column type. * You can overwrite all functions to achieve another handling. * * @author André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ class ColumnTypeBracketExpressionBuilder { protected function buildSubTree($parsed, $delim) { $builder = new SubTreeBuilder(); return $builder->build($parsed, $delim); } public function build($parsed) { if ($parsed['expr_type'] !== ExpressionType::BRACKET_EXPRESSION) { return ""; } $sql = $this->buildSubTree($parsed, ","); $sql = "(" . $sql . ")"; return $sql; } } ?> ================================================ FILE: src/library/builders/ColumnTypeBuilder.php ================================================ * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * @version SVN: $Id: ColumnTypeBuilder.php 935 2014-01-08 13:58:11Z phosco@gmx.de $ * */ require_once dirname(__FILE__) . '/../exceptions/UnableToCreateSQLException.php'; require_once dirname(__FILE__) . '/ReservedBuilder.php'; require_once dirname(__FILE__) . '/ColumnTypeBracketExpressionBuilder.php'; require_once dirname(__FILE__) . '/DataTypeBuilder.php'; require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; /** * This class implements the builder for the column type statement part of CREATE TABLE. * You can overwrite all functions to achieve another handling. * * @author André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ class ColumnTypeBuilder { protected function buildColumnTypeBracketExpression($parsed) { $builder = new ColumnTypeBracketExpressionBuilder(); return $builder->build($parsed); } protected function buildReserved($parsed) { $builder = new ReservedBuilder(); return $builder->build($parsed); } protected function buildDataType($parsed) { $builder = new DataTypeBuilder(); return $builder->build($parsed); } public function build($parsed) { if ($parsed['expr_type'] !== ExpressionType::COLUMN_TYPE) { return ""; } $sql = ""; foreach ($parsed['sub_tree'] as $k => $v) { $len = strlen($sql); $sql .= $this->buildDataType($v); $sql .= $this->buildColumnTypeBracketExpression($v); $sql .= $this->buildReserved($v); if ($len == strlen($sql)) { throw new UnableToCreateSQLException('CREATE TABLE column-type subtree', $k, $v, 'expr_type'); } $sql .= " "; } return substr($sql, 0, -1); } } ?> ================================================ FILE: src/library/builders/ConstantBuilder.php ================================================ * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * @version SVN: $Id: ConstantBuilder.php 830 2013-12-18 09:35:42Z phosco@gmx.de $ * */ require_once dirname(__FILE__) . '/AliasBuilder.php'; require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; /** * This class implements the builder for constants. * You can overwrite all functions to achieve another handling. * * @author André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ class ConstantBuilder { protected function buildAlias($parsed) { $builder = new AliasBuilder(); return $builder->build($parsed); } public function build($parsed) { if ($parsed['expr_type'] !== ExpressionType::CONSTANT) { return ""; } $sql = $parsed['base_expr']; $sql .= $this->buildAlias($parsed); return $sql; } } ?> ================================================ FILE: src/library/builders/ConstraintBuilder.php ================================================ * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * @version SVN: $Id: ConstraintBuilder.php 891 2013-12-31 00:20:19Z phosco@gmx.de $ * */ require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; require_once dirname(__FILE__) . '/ConstantBuilder.php'; /** * This class implements the builder for the constraint statement part of CREATE TABLE. * You can overwrite all functions to achieve another handling. * * @author André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ class ConstraintBuilder { protected function buildConstant($parsed) { $builder = new ConstantBuilder(); return $builder->build($parsed); } public function build($parsed) { if ($parsed['expr_type'] !== ExpressionType::CONSTRAINT) { return ""; } $sql = $this->buildConstant($parsed['sub_tree']); return "CONSTRAINT" . (empty($sql) ? '' : (' ' . $sql)); } } ?> ================================================ FILE: src/library/builders/CreateBuilder.php ================================================ * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * @version SVN: $Id: CreateBuilder.php 833 2013-12-18 10:13:59Z phosco@gmx.de $ * */ require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; require_once dirname(__FILE__) . '/CreateTableBuilder.php'; require_once dirname(__FILE__) . '/SubTreeBuilder.php'; /** * This class implements the builder for the [CREATE] part. You can overwrite * all functions to achieve another handling. * * @author André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ class CreateBuilder { protected function buildCreateTable($parsed) { $builder = new CreateTableBuilder(); return $builder->build($parsed); } protected function buildSubTree($parsed) { $builder = new SubTreeBuilder(); return $builder->build($parsed); } public function build($parsed) { $create = $parsed['CREATE']; $sql = $this->buildSubTree($create); if (($create['expr_type'] === ExpressionType::TABLE) || ($create['expr_type'] === ExpressionType::TEMPORARY_TABLE)) { $sql .= " " . $this->buildCreateTable($parsed['TABLE']); } // TODO: add more expr_types here (like VIEW), if available return "CREATE " . $sql; } } ?> ================================================ FILE: src/library/builders/CreateStatementBuilder.php ================================================ * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * @version SVN: $Id: CreateStatementBuilder.php 930 2014-01-08 13:07:55Z phosco@gmx.de $ * */ require_once dirname(__FILE__) . '/LikeBuilder.php'; require_once dirname(__FILE__) . '/SelectStatementBuilder.php'; require_once dirname(__FILE__) . '/CreateBuilder.php'; /** * This class implements the builder for the whole Create statement. You can overwrite * all functions to achieve another handling. * * @author André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ class CreateStatementBuilder { protected function buildLIKE($parsed) { $builder = new LikeBuilder(); return $builder->build($parsed); } protected function buildSelectStatement($parsed) { $builder = new SelectStatementBuilder(); return $builder->build($parsed); } protected function buildCREATE($parsed) { $builder = new CreateBuilder(); return $builder->build($parsed); } public function build($parsed) { $sql = $this->buildCREATE($parsed); if (isset($parsed['LIKE'])) { $sql .= " " . $this->buildLIKE($parsed['LIKE']); } if (isset($parsed['SELECT'])) { $sql .= " " . $this->buildSelectStatement($parsed); } return $sql; } } ?> ================================================ FILE: src/library/builders/CreateTableBuilder.php ================================================ * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * @version SVN: $Id: CreateTableBuilder.php 892 2013-12-31 00:21:33Z phosco@gmx.de $ * */ require_once dirname(__FILE__) . '/../exceptions/UnableToCreateSQLException.php'; require_once dirname(__FILE__) . '/CreateTableDefinitionBuilder.php'; require_once dirname(__FILE__) . '/CreateTableSelectOptionBuilder.php'; require_once dirname(__FILE__) . '/CreateTableOptionsBuilder.php'; /** * This class implements the builder for the CREATE TABLE statement. You can overwrite * all functions to achieve another handling. * * @author André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ class CreateTableBuilder { protected function buildCreateTableDefinition($parsed) { $builder = new CreateTableDefinitionBuilder(); return $builder->build($parsed); } protected function buildCreateTableOptions($parsed) { $builder = new CreateTableOptionsBuilder(); return $builder->build($parsed); } protected function buildCreateTableSelectOption($parsed) { $builder = new CreateTableSelectOptionBuilder(); return $builder->build($parsed); } public function build($parsed) { $sql = $parsed['name']; $sql .= $this->buildCreateTableDefinition($parsed); $sql .= $this->buildCreateTableOptions($parsed); $sql .= $this->buildCreateTableSelectOption($parsed); return $sql; } } ?> ================================================ FILE: src/library/builders/CreateTableDefinitionBuilder.php ================================================ * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * @version SVN: $Id: CreateTableDefinitionBuilder.php 830 2013-12-18 09:35:42Z phosco@gmx.de $ * */ require_once dirname(__FILE__) . '/TableBracketExpressionBuilder.php'; /** * This class implements the builder for the create definitions of CREATE TABLE. * You can overwrite all functions to achieve another handling. * * @author André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ class CreateTableDefinitionBuilder { protected function buildTableBracketExpression($parsed) { $builder = new TableBracketExpressionBuilder(); return $builder->build($parsed); } public function build($parsed) { if (!isset($parsed) || $parsed['create-def'] === false) { return ""; } return $this->buildTableBracketExpression($parsed['create-def']); } } ?> ================================================ FILE: src/library/builders/CreateTableOptionsBuilder.php ================================================ * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * @version SVN: $Id: CreateTableOptionsBuilder.php 923 2014-01-08 12:20:30Z phosco@gmx.de $ * */ require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; require_once dirname(__FILE__) . '/SelectExpressionBuilder.php'; require_once dirname(__FILE__) . '/CharacterSetBuilder.php'; require_once dirname(__FILE__) . '/CollationBuilder.php'; /** * This class implements the builder for the table-options statement part of CREATE TABLE. * You can overwrite all functions to achieve another handling. * * @author André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ class CreateTableOptionsBuilder { protected function buildExpression($parsed) { $builder = new SelectExpressionBuilder(); return $builder->build($parsed); } protected function buildCharacterSet($parsed) { $builder = new CharacterSetBuilder(); return $builder->build($parsed); } protected function buildCollation($parsed) { $builder = new CollationBuilder(); return $builder->build($parsed); } /** * Returns a well-formatted delimiter string. If you don't need nice SQL, * you could simply return $parsed['delim']. * * @param array $parsed The part of the output array, which contains the current expression. * @return a string, which is added right after the expression */ protected function getDelimiter($parsed) { return ($parsed['delim'] === false ? '' : (trim($parsed['delim']) . ' ')); } public function build($parsed) { if (!isset($parsed['options']) || $parsed['options'] === false) { return ""; } $options = $parsed['options']; $sql = ""; foreach ($options as $k => $v) { $len = strlen($sql); $sql .= $this->buildExpression($v); $sql .= $this->buildCharacterSet($v); $sql .= $this->buildCollation($v); if ($len == strlen($sql)) { throw new UnableToCreateSQLException('CREATE TABLE options', $k, $v, 'expr_type'); } $sql .= $this->getDelimiter($v); } return " " . substr($sql, 0, -1); } } ?> ================================================ FILE: src/library/builders/CreateTableSelectOptionBuilder.php ================================================ * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * @version SVN: $Id: CreateTableSelectOptionBuilder.php 932 2014-01-08 13:15:26Z phosco@gmx.de $ * */ /** * This class implements the builder for the select-options statement part of CREATE TABLE. * You can overwrite all functions to achieve another handling. * * @author André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ class CreateTableSelectOptionBuilder { public function build($parsed) { if (!isset($parsed['select-option']) || $parsed['select-option'] === false) { return ""; } $option = $parsed['select-option']; $sql = ($option['duplicates'] === false ? '' : (' ' . $option['duplicates'])); $sql .= ($option['as'] === false ? '' : ' AS'); return $sql; } } ?> ================================================ FILE: src/library/builders/DataTypeBuilder.php ================================================ * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * @version SVN: $Id: DataTypeBuilder.php 830 2013-12-18 09:35:42Z phosco@gmx.de $ * */ require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; /** * This class implements the builder for the data-type statement part of CREATE TABLE. * You can overwrite all functions to achieve another handling. * * @author André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ class DataTypeBuilder { public function build($parsed) { if ($parsed['expr_type'] !== ExpressionType::DATA_TYPE) { return ""; } return $parsed['base_expr']; } } ?> ================================================ FILE: src/library/builders/DatabaseBuilder.php ================================================ * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * @version SVN: $Id: DatabaseBuilder.php 830 2013-12-18 09:35:42Z phosco@gmx.de $ * */ require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; /** * This class implements the builder for a database within SHOW statement. * You can overwrite all functions to achieve another handling. * * @author André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ class DatabaseBuilder { public function build($parsed) { if ($parsed['expr_type'] !== ExpressionType::DATABASE) { return ""; } return $parsed['base_expr']; } } ?> ================================================ FILE: src/library/builders/DeleteBuilder.php ================================================ * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * @version SVN: $Id: DeleteBuilder.php 830 2013-12-18 09:35:42Z phosco@gmx.de $ * */ /** * This class implements the builder for the [DELETE] part. You can overwrite * all functions to achieve another handling. * * @author André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ class DeleteBuilder { public function build($parsed) { $sql = "DELETE"; foreach ($parsed['TABLES'] as $k => $v) { $sql .= $v . ","; } return substr($sql, 0, -1); } } ?> ================================================ FILE: src/library/builders/DeleteStatementBuilder.php ================================================ * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * @version SVN: $Id: DeleteStatementBuilder.php 830 2013-12-18 09:35:42Z phosco@gmx.de $ * */ require_once dirname(__FILE__) . '/WhereBuilder.php'; require_once dirname(__FILE__) . '/FromBuilder.php'; require_once dirname(__FILE__) . '/DeleteBuilder.php'; /** * This class implements the builder for the whole Delete statement. You can overwrite * all functions to achieve another handling. * * @author André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ class DeleteStatementBuilder { protected function buildWHERE($parsed) { $builder = new WhereBuilder(); return $builder->build($parsed); } protected function buildFROM($parsed) { $builder = new FromBuilder(); return $builder->build($parsed); } protected function buildDELETE($parsed) { $builder = new DeleteBuilder(); return $builder->build($parsed); } public function processDeleteStatement($parsed) { $sql = $this->buildDELETE($parsed['DELETE']) . " " . $this->processFROM($parsed['FROM']); if (isset($parsed['WHERE'])) { $sql .= " " . $this->processWHERE($parsed['WHERE']); } return $sql; } } ?> ================================================ FILE: src/library/builders/DirectionBuilder.php ================================================ * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * @version SVN: $Id: DirectionBuilder.php 830 2013-12-18 09:35:42Z phosco@gmx.de $ * */ /** * This class implements the builder for directions (e.g. of the order-by clause). * You can overwrite all functions to achieve another handling. * * @author André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ class DirectionBuilder { public function build($parsed) { if (!isset($parsed['direction']) || $parsed['direction'] === false) { return ""; } return (" " . $parsed['direction']); } } ?> ================================================ FILE: src/library/builders/EngineBuilder.php ================================================ * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * @version SVN: $Id: EngineBuilder.php 830 2013-12-18 09:35:42Z phosco@gmx.de $ * */ require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; /** * This class implements the builder for a database within SHOW statement. * You can overwrite all functions to achieve another handling. * * @author André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ class EngineBuilder { public function build($parsed) { if ($parsed['expr_type'] !== ExpressionType::ENGINE) { return ""; } return $parsed['base_expr']; } } ?> ================================================ FILE: src/library/builders/ForeignKeyBuilder.php ================================================ * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * @version SVN: $Id: ForeignKeyBuilder.php 927 2014-01-08 13:01:17Z phosco@gmx.de $ * */ require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; require_once dirname(__FILE__) . '/../exceptions/UnableToCreateSQLException.php'; require_once dirname(__FILE__) . '/ConstantBuilder.php'; require_once dirname(__FILE__) . '/ReservedBuilder.php'; require_once dirname(__FILE__) . '/ColumnListBuilder.php'; require_once dirname(__FILE__) . '/ForeignRefBuilder.php'; /** * This class implements the builder for the FOREIGN KEY statement part of CREATE TABLE. * You can overwrite all functions to achieve another handling. * * @author André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ class ForeignKeyBuilder { protected function buildConstant($parsed) { $builder = new ConstantBuilder(); return $builder->build($parsed); } protected function buildColumnList($parsed) { $builder = new ColumnListBuilder(); return $builder->build($parsed); } protected function buildReserved($parsed) { $builder = new ReservedBuilder(); return $builder->build($parsed); } protected function buildForeignRef($parsed) { $builder = new ForeignRefBuilder(); return $builder->build($parsed); } public function build($parsed) { if ($parsed['expr_type'] !== ExpressionType::FOREIGN_KEY) { return ""; } $sql = ""; foreach ($parsed['sub_tree'] as $k => $v) { $len = strlen($sql); $sql .= $this->buildConstant($v); $sql .= $this->buildReserved($v); $sql .= $this->buildColumnList($v); $sql .= $this->buildForeignRef($v); if ($len == strlen($sql)) { throw new UnableToCreateSQLException('CREATE TABLE foreign key subtree', $k, $v, 'expr_type'); } $sql .= " "; } return substr($sql, 0, -1); } } ?> ================================================ FILE: src/library/builders/ForeignRefBuilder.php ================================================ * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * @version SVN: $Id: ForeignRefBuilder.php 927 2014-01-08 13:01:17Z phosco@gmx.de $ * */ require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; require_once dirname(__FILE__) . '/../exceptions/UnableToCreateSQLException.php'; require_once dirname(__FILE__) . '/TableBuilder.php'; require_once dirname(__FILE__) . '/ReservedBuilder.php'; require_once dirname(__FILE__) . '/ColumnListBuilder.php'; /** * This class implements the builder for the FOREIGN KEY REFERENCES statement * part of CREATE TABLE. * You can overwrite all functions to achieve another handling. * * @author André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ class ForeignRefBuilder { protected function buildTable($parsed) { $builder = new TableBuilder(); return $builder->build($parsed, 0); } protected function buildColumnList($parsed) { $builder = new ColumnListBuilder(); return $builder->build($parsed); } protected function buildReserved($parsed) { $builder = new ReservedBuilder(); return $builder->build($parsed); } public function build($parsed) { if ($parsed['expr_type'] !== ExpressionType::REFERENCE) { return ""; } $sql = ""; foreach ($parsed['sub_tree'] as $k => $v) { $len = strlen($sql); $sql .= $this->buildTable($v); $sql .= $this->buildReserved($v); $sql .= $this->buildColumnList($v); if ($len == strlen($sql)) { throw new UnableToCreateSQLException('CREATE TABLE foreign ref subtree', $k, $v, 'expr_type'); } $sql .= " "; } return substr($sql, 0, -1); } } ?> ================================================ FILE: src/library/builders/FromBuilder.php ================================================ * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * @version SVN: $Id: FromBuilder.php 830 2013-12-18 09:35:42Z phosco@gmx.de $ * */ require_once dirname(__FILE__) . '/../exceptions/UnableToCreateSQLException.php'; require_once dirname(__FILE__) . '/TableBuilder.php'; require_once dirname(__FILE__) . '/TableExpressionBuilder.php'; require_once dirname(__FILE__) . '/SubQueryBuilder.php'; /** * This class implements the builder for the [FROM] part. You can overwrite * all functions to achieve another handling. * * @author André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ class FromBuilder { protected function buildTable($parsed, $key) { $builder = new TableBuilder(); return $builder->build($parsed, $key); } protected function buildTableExpression($parsed, $key) { $builder = new TableExpressionBuilder(); return $builder->build($parsed, $key); } protected function buildSubQuery($parsed, $key) { $builder = new SubQueryBuilder(); return $builder->build($parsed, $key); } public function build($parsed) { $sql = ""; foreach ($parsed as $k => $v) { $len = strlen($sql); $sql .= $this->buildTable($v, $k); $sql .= $this->buildTableExpression($v, $k); $sql .= $this->buildSubquery($v, $k); if ($len == strlen($sql)) { throw new UnableToCreateSQLException('FROM', $k, $v, 'expr_type'); } } return "FROM " . $sql; } } ?> ================================================ FILE: src/library/builders/FunctionBuilder.php ================================================ * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * @version SVN: $Id: FunctionBuilder.php 830 2013-12-18 09:35:42Z phosco@gmx.de $ * */ require_once dirname(__FILE__) . '/../exceptions/UnableToCreateSQLException.php'; require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; require_once dirname(__FILE__) . '/AliasBuilder.php'; require_once dirname(__FILE__) . '/ColumnReferenceBuilder.php'; require_once dirname(__FILE__) . '/ConstantBuilder.php'; require_once dirname(__FILE__) . '/FunctionBuilder.php'; require_once dirname(__FILE__) . '/ReservedBuilder.php'; require_once dirname(__FILE__) . '/SelectExpressionBuilder.php'; require_once dirname(__FILE__) . '/SelectBracketExpressionBuilder.php'; require_once dirname(__FILE__) . '/DirectionBuilder.php'; /** * This class implements the builder for function calls. * You can overwrite all functions to achieve another handling. * * @author André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ class FunctionBuilder { protected function buildDirection($parsed) { $builder = new DirectionBuilder(); return $builder->build($parsed); } protected function buildAlias($parsed) { $builder = new AliasBuilder(); return $builder->build($parsed); } protected function buildColRef($parsed) { $builder = new ColumnReferenceBuilder(); return $builder->build($parsed); } protected function buildConstant($parsed) { $builder = new ConstantBuilder(); return $builder->build($parsed); } protected function buildReserved($parsed) { $builder = new ReservedBuilder(); return $builder->build($parsed); } protected function isReserved($parsed) { $builder = new ReservedBuilder(); return $builder->isReserved($parsed); } protected function buildSelectExpression($parsed) { $builder = new SelectExpressionBuilder(); return $builder->build($parsed); } protected function buildSelectBracketExpression($parsed) { $builder = new SelectBracketExpressionBuilder(); return $builder->build($parsed); } public function build($parsed) { if (($parsed['expr_type'] !== ExpressionType::AGGREGATE_FUNCTION) && ($parsed['expr_type'] !== ExpressionType::SIMPLE_FUNCTION)) { return ""; } if ($parsed['sub_tree'] === false) { return $parsed['base_expr'] . "()"; } $sql = ""; foreach ($parsed['sub_tree'] as $k => $v) { $len = strlen($sql); $sql .= $this->build($v); $sql .= $this->buildConstant($v); $sql .= $this->buildColRef($v); $sql .= $this->buildReserved($v); $sql .= $this->buildSelectBracketExpression($v); $sql .= $this->buildSelectExpression($v); if ($len == strlen($sql)) { throw new UnableToCreateSQLException('function subtree', $k, $v, 'expr_type'); } $sql .= ($this->isReserved($v) ? " " : ","); } return $parsed['base_expr'] . "(" . substr($sql, 0, -1) . ")" . $this->buildAlias($parsed) . $this->buildDirection($parsed); } } ?> ================================================ FILE: src/library/builders/GroupByBuilder.php ================================================ * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * @version SVN: $Id: GroupByBuilder.php 830 2013-12-18 09:35:42Z phosco@gmx.de $ * */ require_once dirname(__FILE__) . '/../exceptions/UnableToCreateSQLException.php'; require_once dirname(__FILE__) . '/PositionBuilder.php'; require_once dirname(__FILE__) . '/ColumnReferenceBuilder.php'; require_once dirname(__FILE__) . '/FunctionBuilder.php'; /** * This class implements the builder for the GROUP-BY clause. * You can overwrite all functions to achieve another handling. * * @author André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ class GroupByBuilder { protected function buildColRef($parsed) { $builder = new ColumnReferenceBuilder(); return $builder->build($parsed); } protected function buildPosition($parsed) { $builder = new PositionBuilder(); return $builder->build($parsed); } protected function buildFunction($parsed) { $builder = new FunctionBuilder(); return $builder->build($parsed); } public function build($parsed) { $sql = ""; foreach ($parsed as $k => $v) { $len = strlen($sql); $sql .= $this->buildColRef($v); $sql .= $this->buildPosition($v); $sql .= $this->buildFunction($v); if ($len == strlen($sql)) { throw new UnableToCreateSQLException('GROUP', $k, $v, 'expr_type'); } $sql .= ", "; } $sql = substr($sql, 0, -2); return "GROUP BY " . $sql; } } ?> ================================================ FILE: src/library/builders/InListBuilder.php ================================================ * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * @version SVN: $Id: InListBuilder.php 830 2013-12-18 09:35:42Z phosco@gmx.de $ * */ require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; require_once dirname(__FILE__) . '/SubTreeBuilder.php'; /** * This class implements the builder list of values for the IN statement. * You can overwrite all functions to achieve another handling. * * @author André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ class InListBuilder { protected function buildSubTree($parsed, $delim) { $builder = new SubTreeBuilder(); return $builder->build($parsed, $delim); } public function build($parsed) { if ($parsed['expr_type'] !== ExpressionType::IN_LIST) { return ""; } $sql = $this->buildSubTree($parsed, ", "); return "(" . $sql . ")"; } } ?> ================================================ FILE: src/library/builders/IndexColumnBuilder.php ================================================ * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * @version SVN: $Id: IndexColumnBuilder.php 917 2014-01-08 11:47:42Z phosco@gmx.de $ * */ require_once dirname(__FILE__) . '/../exceptions/UnsupportedFeatureException.php'; require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; /** * This class implements the builder for index column entries of the column-list * parts of CREATE TABLE. * You can overwrite all functions to achieve another handling. * * @author André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ class IndexColumnBuilder { protected function buildLength($parsed) { return ($parsed === false ? '' : ('(' . $parsed . ')')); } protected function buildDirection($parsed) { return ($parsed === false ? '' : (' ' . $parsed)); } public function build($parsed) { if ($parsed['expr_type'] !== ExpressionType::INDEX_COLUMN) { return ""; } $sql = $parsed['name']; $sql .= $this->buildLength($parsed['length']); $sql .= $this->buildDirection($parsed['dir']); return $sql; } } ?> ================================================ FILE: src/library/builders/IndexParserBuilder.php ================================================ * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * @version SVN: $Id: IndexParserBuilder.php 918 2014-01-08 11:48:30Z phosco@gmx.de $ * */ require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; require_once dirname(__FILE__) . '/../exceptions/UnableToCreateSQLException.php'; require_once dirname(__FILE__) . '/ColumnListBuilder.php'; require_once dirname(__FILE__) . '/ConstraintBuilder.php'; require_once dirname(__FILE__) . '/ReservedBuilder.php'; require_once dirname(__FILE__) . '/IndexTypeBuilder.php'; /** * This class implements the builder for the index parser of a PRIMARY KEY * statement part of CREATE TABLE. * You can overwrite all functions to achieve another handling. * * @author André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ class IndexParserBuilder { protected function buildReserved($parsed) { $builder = new ReservedBuilder(); return $builder->build($parsed); } protected function buildConstant($parsed) { $builder = new ConstantBuilder(); return $builder->build($parsed); } public function build($parsed) { if ($parsed['expr_type'] !== ExpressionType::INDEX_PARSER) { return ""; } $sql = ""; foreach ($parsed['sub_tree'] as $k => $v) { $len = strlen($sql); $sql .= $this->buildReserved($v); $sql .= $this->buildConstant($v); if ($len == strlen($sql)) { throw new UnableToCreateSQLException('CREATE TABLE primary key index parser subtree', $k, $v, 'expr_type'); } $sql .= " "; } return substr($sql, 0, -1); } } ?> ================================================ FILE: src/library/builders/IndexSizeBuilder.php ================================================ * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * @version SVN: $Id: IndexSizeBuilder.php 918 2014-01-08 11:48:30Z phosco@gmx.de $ * */ require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; require_once dirname(__FILE__) . '/../exceptions/UnableToCreateSQLException.php'; require_once dirname(__FILE__) . '/ColumnListBuilder.php'; require_once dirname(__FILE__) . '/ConstraintBuilder.php'; require_once dirname(__FILE__) . '/ReservedBuilder.php'; require_once dirname(__FILE__) . '/IndexTypeBuilder.php'; /** * This class implements the builder for the index size of a PRIMARY KEY * statement part of CREATE TABLE. * You can overwrite all functions to achieve another handling. * * @author André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ class IndexSizeBuilder { protected function buildReserved($parsed) { $builder = new ReservedBuilder(); return $builder->build($parsed); } protected function buildConstant($parsed) { $builder = new ConstantBuilder(); return $builder->build($parsed); } public function build($parsed) { if ($parsed['expr_type'] !== ExpressionType::INDEX_SIZE) { return ""; } $sql = ""; foreach ($parsed['sub_tree'] as $k => $v) { $len = strlen($sql); $sql .= $this->buildReserved($v); $sql .= $this->buildConstant($v); if ($len == strlen($sql)) { throw new UnableToCreateSQLException('CREATE TABLE primary key index size subtree', $k, $v, 'expr_type'); } $sql .= " "; } return substr($sql, 0, -1); } } ?> ================================================ FILE: src/library/builders/IndexTypeBuilder.php ================================================ * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * @version SVN: $Id: IndexTypeBuilder.php 910 2014-01-08 10:46:12Z phosco@gmx.de $ * */ require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; require_once dirname(__FILE__) . '/../exceptions/UnableToCreateSQLException.php'; require_once dirname(__FILE__) . '/ColumnListBuilder.php'; require_once dirname(__FILE__) . '/ConstraintBuilder.php'; require_once dirname(__FILE__) . '/ReservedBuilder.php'; require_once dirname(__FILE__) . '/IndexTypeBuilder.php'; /** * This class implements the builder for the index type of a PRIMARY KEY * statement part of CREATE TABLE. * You can overwrite all functions to achieve another handling. * * @author André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ class IndexTypeBuilder { protected function buildReserved($parsed) { $builder = new ReservedBuilder(); return $builder->build($parsed); } public function build($parsed) { if ($parsed['expr_type'] !== ExpressionType::INDEX_TYPE) { return ""; } $sql = ""; foreach ($parsed['sub_tree'] as $k => $v) { $len = strlen($sql); $sql .= $this->buildReserved($v); if ($len == strlen($sql)) { throw new UnableToCreateSQLException('CREATE TABLE primary key index type subtree', $k, $v, 'expr_type'); } $sql .= " "; } return substr($sql, 0, -1); } } ?> ================================================ FILE: src/library/builders/InsertBuilder.php ================================================ * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * @version SVN: $Id: InsertBuilder.php 830 2013-12-18 09:35:42Z phosco@gmx.de $ * */ require_once dirname(__FILE__) . '/../exceptions/UnableToCreateSQLException.php'; require_once dirname(__FILE__) . '/ColumnReferenceBuilder.php'; /** * This class implements the builder for the [INSERT] statement parts. * You can overwrite all functions to achieve another handling. * * @author André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ class InsertBuilder { protected function buildColRef($parsed) { $builder = new ColumnReferenceBuilder(); return $builder->build($parsed); } public function build($parsed) { $sql = "INSERT INTO " . $parsed['table']; if ($parsed['columns'] === false) { return $sql; } $columns = ""; foreach ($parsed['columns'] as $k => $v) { $len = strlen($columns); $columns .= $this->buildColRef($v); if ($len == strlen($columns)) { throw new UnableToCreateSQLException('INSERT[columns]', $k, $v, 'expr_type'); } $columns .= ","; } if ($columns !== "") { $columns = " (" . substr($columns, 0, -1) . ")"; } $sql .= $columns; return $sql; } } ?> ================================================ FILE: src/library/builders/InsertStatementBuilder.php ================================================ * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * @version SVN: $Id: InsertStatementBuilder.php 834 2013-12-18 10:14:26Z phosco@gmx.de $ * */ require_once dirname(__FILE__) . '/InsertBuilder.php'; require_once dirname(__FILE__) . '/ValuesBuilder.php'; /** * This class implements the builder for the whole Insert statement. You can overwrite * all functions to achieve another handling. * * @author André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ class InsertStatementBuilder { protected function buildVALUES($parsed) { $builder = new ValuesBuilder(); return $builder->build($parsed); } protected function buildINSERT($parsed) { $builder = new InsertBuilder($parsed); return $builder->build($parsed); } public function build($parsed) { // TODO: are there more than one tables possible (like [INSERT][1]) return $this->buildINSERT($parsed['INSERT'][0]) . " " . $this->buildVALUES($parsed['VALUES']); // TODO: subquery? } } ?> ================================================ FILE: src/library/builders/JoinBuilder.php ================================================ * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * @version SVN: $Id: JoinBuilder.php 830 2013-12-18 09:35:42Z phosco@gmx.de $ * */ require_once dirname(__FILE__) . '/../exceptions/UnsupportedFeatureException.php'; /** * This class implements the builder for the JOIN statement parts (within FROM). * You can overwrite all functions to achieve another handling. * * @author André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ class JoinBuilder { public function build($parsed) { if ($parsed === 'CROSS') { return ", "; } if ($parsed === 'JOIN') { return " INNER JOIN "; } if ($parsed === 'LEFT') { return " LEFT JOIN "; } if ($parsed === 'RIGHT') { return " RIGHT JOIN "; } // TODO: add more throw new UnsupportedFeatureException($parsed); } } ?> ================================================ FILE: src/library/builders/LikeBuilder.php ================================================ * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * @version SVN: $Id: LikeBuilder.php 830 2013-12-18 09:35:42Z phosco@gmx.de $ * */ require_once dirname(__FILE__) . '/../exceptions/UnableToCreateSQLException.php'; require_once dirname(__FILE__) . '/TableBuilder.php'; /** * This class implements the builder for the LIKE statement part of CREATE TABLE. * You can overwrite all functions to achieve another handling. * * @author André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ class LikeBuilder { protected function buildTable($parsed, $index) { $builder = new TableBuilder(); return $builder->build($parsed, $index); } public function build($parsed) { $sql = $this->buildTable($parsed, 0); if (strlen($sql) === 0) { throw new UnableToCreateSQLException('LIKE', "", $like, 'table'); } return "LIKE " . $sql; } } ?> ================================================ FILE: src/library/builders/LikeExpressionBuilder.php ================================================ * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * @version SVN: $Id: LikeExpressionBuilder.php 906 2014-01-07 14:38:08Z phosco@gmx.de $ * */ require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; require_once dirname(__FILE__) . '/TableBuilder.php'; require_once dirname(__FILE__) . '/ReservedBuilder.php'; /** * This class implements the builder for the (LIKE) keyword within a * CREATE TABLE statement. There are difference to LIKE (without parenthesis), * the latter is a top-level element of the output array. * You can overwrite all functions to achieve another handling. * * @author André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ class LikeExpressionBuilder { protected function buildTable($parsed, $index) { $builder = new TableBuilder(); return $builder->build($parsed, $index); } protected function buildReserved($parsed) { $builder = new ReservedBuilder(); return $builder->build($parsed); } public function build($parsed) { if ($parsed['expr_type'] !== ExpressionType::LIKE) { return ""; } $sql = ""; foreach ($parsed['sub_tree'] as $k => $v) { $len = strlen($sql); $sql .= $this->buildReserved($v); $sql .= $this->buildTable($v, 0); if ($len == strlen($sql)) { throw new UnableToCreateSQLException('CREATE TABLE create-def (like) subtree', $k, $v, 'expr_type'); } $sql .= " "; } return substr($sql, 0, -1); } } ?> ================================================ FILE: src/library/builders/LimitBuilder.php ================================================ * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * @version SVN: $Id: LimitBuilder.php 830 2013-12-18 09:35:42Z phosco@gmx.de $ * */ require_once dirname(__FILE__) . '/../exceptions/UnableToCreateSQLException.php'; /** * This class implements the builder LIMIT statement. * You can overwrite all functions to achieve another handling. * * @author André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ class LimitBuilder { public function build($parsed) { $sql = ($parsed['offset'] ? $parsed['offset'] . ", " : "") . $parsed['rowcount']; if ($sql === "") { throw new UnableToCreateSQLException('LIMIT', 'rowcount', $parsed, 'rowcount'); } return "LIMIT " . $sql; } } ?> ================================================ FILE: src/library/builders/OperatorBuilder.php ================================================ * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * @version SVN: $Id: OperatorBuilder.php 830 2013-12-18 09:35:42Z phosco@gmx.de $ * */ require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; /** * This class implements the builder for operators. * You can overwrite all functions to achieve another handling. * * @author André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ class OperatorBuilder { public function build($parsed) { if ($parsed['expr_type'] !== ExpressionType::OPERATOR) { return ""; } return $parsed['base_expr']; } } ?> ================================================ FILE: src/library/builders/OrderByAliasBuilder.php ================================================ * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * @version SVN: $Id: OrderByAliasBuilder.php 830 2013-12-18 09:35:42Z phosco@gmx.de $ * */ require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; require_once dirname(__FILE__) . '/DirectionBuilder.php'; /** * This class implements the builder for an alias within the ORDER-BY clause. * You can overwrite all functions to achieve another handling. * * @author André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ class OrderByAliasBuilder { protected function buildDirection($parsed) { $builder = new DirectionBuilder(); return $builder->build($parsed); } public function build($parsed) { if ($parsed['expr_type'] !== ExpressionType::ALIAS) { return ""; } return $parsed['base_expr'] . $this->buildDirection($parsed); } } ?> ================================================ FILE: src/library/builders/OrderByBuilder.php ================================================ * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * @version SVN: $Id: OrderByBuilder.php 830 2013-12-18 09:35:42Z phosco@gmx.de $ * */ require_once dirname(__FILE__) . '/../exceptions/UnableToCreateSQLException.php'; require_once dirname(__FILE__) . '/OrderByAliasBuilder.php'; require_once dirname(__FILE__) . '/ColumnReferenceBuilder.php'; /** * This class implements the builder for the ORDER-BY clause. * You can overwrite all functions to achieve another handling. * * @author André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ class OrderByBuilder { protected function buildFunction($parsed) { $builder = new FunctionBuilder(); return $builder->build($parsed); } protected function buildColRef($parsed) { $builder = new ColumnReferenceBuilder(); return $builder->build($parsed); } protected function buildOrderByAlias($parsed) { $builder = new OrderByAliasBuilder(); return $builder->build($parsed); } public function build($parsed) { $sql = ""; foreach ($parsed as $k => $v) { $len = strlen($sql); $sql .= $this->buildOrderByAlias($v); $sql .= $this->buildColRef($v); $sql .= $this->buildFunction($v); if ($len == strlen($sql)) { throw new UnableToCreateSQLException('ORDER', $k, $v, 'expr_type'); } $sql .= ", "; } $sql = substr($sql, 0, -2); return "ORDER BY " . $sql; } } ?> ================================================ FILE: src/library/builders/PositionBuilder.php ================================================ * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * @version SVN: $Id: PositionBuilder.php 830 2013-12-18 09:35:42Z phosco@gmx.de $ * */ require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; /** * This class implements the builder for positions of the GROUP-BY clause. * You can overwrite all functions to achieve another handling. * * @author André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ class PositionBuilder { public function build($parsed) { if ($parsed['expr_type'] !== ExpressionType::POSITION) { return ""; } return $parsed['base_expr']; } } ?> ================================================ FILE: src/library/builders/PrimaryKeyBuilder.php ================================================ * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * @version SVN: $Id: PrimaryKeyBuilder.php 919 2014-01-08 11:49:02Z phosco@gmx.de $ * */ require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; require_once dirname(__FILE__) . '/../exceptions/UnableToCreateSQLException.php'; require_once dirname(__FILE__) . '/ColumnListBuilder.php'; require_once dirname(__FILE__) . '/ConstraintBuilder.php'; require_once dirname(__FILE__) . '/ReservedBuilder.php'; require_once dirname(__FILE__) . '/IndexTypeBuilder.php'; require_once dirname(__FILE__) . '/IndexSizeBuilder.php'; require_once dirname(__FILE__) . '/IndexParserBuilder.php'; /** * This class implements the builder for the PRIMARY KEY statement part of CREATE TABLE. * You can overwrite all functions to achieve another handling. * * @author André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ class PrimaryKeyBuilder { protected function buildColumnList($parsed) { $builder = new ColumnListBuilder(); return $builder->build($parsed); } protected function buildConstraint($parsed) { $builder = new ConstraintBuilder(); return $builder->build($parsed); } protected function buildReserved($parsed) { $builder = new ReservedBuilder(); return $builder->build($parsed); } protected function buildIndexType($parsed) { $builder = new IndexTypeBuilder(); return $builder->build($parsed); } protected function buildIndexSize($parsed) { $builder = new IndexSizeBuilder(); return $builder->build($parsed); } protected function buildIndexParser($parsed) { $builder = new IndexParserBuilder(); return $builder->build($parsed); } public function build($parsed) { if ($parsed['expr_type'] !== ExpressionType::PRIMARY_KEY) { return ""; } $sql = ""; foreach ($parsed['sub_tree'] as $k => $v) { $len = strlen($sql); $sql .= $this->buildConstraint($v); $sql .= $this->buildReserved($v); $sql .= $this->buildColumnList($v); $sql .= $this->buildIndexType($v); $sql .= $this->buildIndexSize($v); $sql .= $this->buildIndexParser($v); if ($len == strlen($sql)) { throw new UnableToCreateSQLException('CREATE TABLE primary key subtree', $k, $v, 'expr_type'); } $sql .= " "; } return substr($sql, 0, -1); } } ?> ================================================ FILE: src/library/builders/ProcedureBuilder.php ================================================ * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * @version SVN: $Id: ProcedureBuilder.php 830 2013-12-18 09:35:42Z phosco@gmx.de $ * */ require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; /** * This class implements the builder for a procedure within SHOW statement. * You can overwrite all functions to achieve another handling. * * @author André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ class ProcedureBuilder { public function build($parsed) { if ($parsed['expr_type'] !== ExpressionType::PROCEDURE) { return ""; } return $parsed['base_expr']; } } ?> ================================================ FILE: src/library/builders/RecordBuilder.php ================================================ * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * @version SVN: $Id: RecordBuilder.php 830 2013-12-18 09:35:42Z phosco@gmx.de $ * */ require_once dirname(__FILE__) . '/../exceptions/UnableToCreateSQLException.php'; require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; require_once dirname(__FILE__) . '/OperatorBuilder.php'; require_once dirname(__FILE__) . '/ConstantBuilder.php'; require_once dirname(__FILE__) . '/FunctionBuilder.php'; /** * This class implements the builder for the records within INSERT statement. * You can overwrite all functions to achieve another handling. * * @author André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ class RecordBuilder { protected function buildOperator($parsed) { $builder = new OperatorBuilder(); return $builder->build($parsed); } protected function buildFunction($parsed) { $builder = new FunctionBuilder(); return $builder->build($parsed); } protected function buildConstant($parsed) { $builder = new ConstantBuilder(); return $builder->build($parsed); } public function build($parsed) { if ($parsed['expr_type'] !== ExpressionType::RECORD) { return ""; } $sql = ""; foreach ($parsed['data'] as $k => $v) { $len = strlen($sql); $sql .= $this->buildConstant($v); $sql .= $this->buildFunction($v); $sql .= $this->buildOperator($v); if ($len == strlen($sql)) { throw new UnableToCreateSQLException(ExpressionType::RECORD, $k, $v, 'expr_type'); } $sql .= ","; } $sql = substr($sql, 0, -1); return "(" . $sql . ")"; } } ?> ================================================ FILE: src/library/builders/RefClauseBuilder.php ================================================ * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * @version SVN: $Id: RefClauseBuilder.php 830 2013-12-18 09:35:42Z phosco@gmx.de $ * */ require_once dirname(__FILE__) . '/../exceptions/UnableToCreateSQLException.php'; require_once dirname(__FILE__) . '/ColumnReferenceBuilder.php'; require_once dirname(__FILE__) . '/OperatorBuilder.php'; require_once dirname(__FILE__) . '/ConstantBuilder.php'; /** * This class implements the references clause within a JOIN. * You can overwrite all functions to achieve another handling. * * @author André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ class RefClauseBuilder { protected function buildColRef($parsed) { $builder = new ColumnReferenceBuilder(); return $builder->build($parsed); } protected function buildOperator($parsed) { $builder = new OperatorBuilder(); return $builder->build($parsed); } protected function buildConstant($parsed) { $builder = new ConstantBuilder(); return $builder->build($parsed); } public function build($parsed) { if ($parsed === false) { return ""; } $sql = ""; foreach ($parsed as $k => $v) { $len = strlen($sql); $sql .= $this->buildColRef($v); $sql .= $this->buildOperator($v); $sql .= $this->buildConstant($v); if ($len == strlen($sql)) { throw new UnableToCreateSQLException('expression ref_clause', $k, $v, 'expr_type'); } $sql .= " "; } return "(" . substr($sql, 0, -1) . ")"; } } ?> ================================================ FILE: src/library/builders/RefTypeBuilder.php ================================================ * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * @version SVN: $Id: RefTypeBuilder.php 830 2013-12-18 09:35:42Z phosco@gmx.de $ * */ require_once dirname(__FILE__) . '/../exceptions/UnsupportedFeatureException.php'; /** * This class implements the references type within a JOIN. * You can overwrite all functions to achieve another handling. * * @author André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ class RefTypeBuilder { public function build($parsed) { if ($parsed === false) { return ""; } if ($parsed === 'ON') { return " ON "; } if ($parsed === 'USING') { return " USING "; } // TODO: add more throw new UnsupportedFeatureException($parsed); } } ?> ================================================ FILE: src/library/builders/ReservedBuilder.php ================================================ * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * @version SVN: $Id: ReservedBuilder.php 830 2013-12-18 09:35:42Z phosco@gmx.de $ * */ require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; /** * This class implements the builder for reserved keywords. * You can overwrite all functions to achieve another handling. * * @author André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ class ReservedBuilder { public function isReserved($parsed) { return ($parsed['expr_type'] === ExpressionType::RESERVED); } public function build($parsed) { if (!$this->isReserved($parsed)) { return ""; } return $parsed['base_expr']; } } ?> ================================================ FILE: src/library/builders/SelectBracketExpressionBuilder.php ================================================ * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * @version SVN: $Id: SelectBracketExpressionBuilder.php 830 2013-12-18 09:35:42Z phosco@gmx.de $ * */ require_once dirname(__FILE__) . '/SubTreeBuilder.php'; require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; /** * This class implements the builder for bracket expressions within a SELECT statement. * You can overwrite all functions to achieve another handling. * * @author André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ class SelectBracketExpressionBuilder { protected function buildSubTree($parsed, $delim) { $builder = new SubTreeBuilder(); return $builder->build($parsed, $delim); } public function build($parsed) { if ($parsed['expr_type'] !== ExpressionType::BRACKET_EXPRESSION) { return ""; } $sql = $this->buildSubTree($parsed, " "); $sql = "(" . $sql . ")"; return $sql; } } ?> ================================================ FILE: src/library/builders/SelectBuilder.php ================================================ * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * @version SVN: $Id: SelectBuilder.php 903 2014-01-06 11:29:19Z phosco@gmx.de $ * */ require_once dirname(__FILE__) . '/../exceptions/UnableToCreateSQLException.php'; require_once dirname(__FILE__) . '/ConstantBuilder.php'; require_once dirname(__FILE__) . '/FunctionBuilder.php'; require_once dirname(__FILE__) . '/SelectExpressionBuilder.php'; require_once dirname(__FILE__) . '/SelectBracketExpressionBuilder.php'; require_once dirname(__FILE__) . '/ColumnReferenceBuilder.php'; /** * This class implements the builder for the [SELECT] field. You can overwrite * all functions to achieve another handling. * * @author André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ class SelectBuilder { protected function buildConstant($parsed) { $builder = new ConstantBuilder(); return $builder->build($parsed); } protected function buildFunction($parsed) { $builder = new FunctionBuilder(); return $builder->build($parsed); } protected function buildSelectExpression($parsed) { $builder = new SelectExpressionBuilder(); return $builder->build($parsed); } protected function buildSelectBracketExpression($parsed) { $builder = new SelectBracketExpressionBuilder(); return $builder->build($parsed); } protected function buildColRef($parsed) { $builder = new ColumnReferenceBuilder(); return $builder->build($parsed); } protected function buildReserved($parsed) { $builder = new ReservedBuilder(); return $builder->build($parsed); } /** * Returns a well-formatted delimiter string. If you don't need nice SQL, * you could simply return $parsed['delim']. * * @param array $parsed The part of the output array, which contains the current expression. * @return a string, which is added right after the expression */ protected function getDelimiter($parsed) { return ($parsed['delim'] === false ? '' : (trim($parsed['delim']) . ' ')); } public function build($parsed) { $sql = ""; foreach ($parsed as $k => $v) { $len = strlen($sql); $sql .= $this->buildColRef($v); $sql .= $this->buildSelectBracketExpression($v); $sql .= $this->buildSelectExpression($v); $sql .= $this->buildFunction($v); $sql .= $this->buildConstant($v); $sql .= $this->buildReserved($v); if ($len == strlen($sql)) { throw new UnableToCreateSQLException('SELECT', $k, $v, 'expr_type'); } $sql .= $this->getDelimiter($v); } return "SELECT " . $sql; } } ?> ================================================ FILE: src/library/builders/SelectExpressionBuilder.php ================================================ * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * @version SVN: $Id: SelectExpressionBuilder.php 830 2013-12-18 09:35:42Z phosco@gmx.de $ * */ require_once dirname(__FILE__) . '/SubTreeBuilder.php'; require_once dirname(__FILE__) . '/AliasBuilder.php'; require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; /** * This class implements the builder for simple expressions within a SELECT statement. * You can overwrite all functions to achieve another handling. * * @author André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ class SelectExpressionBuilder { protected function buildSubTree($parsed, $delim) { $builder = new SubTreeBuilder(); return $builder->build($parsed, $delim); } protected function buildAlias($parsed) { $builder = new AliasBuilder(); return $builder->build($parsed); } public function build($parsed) { if ($parsed['expr_type'] !== ExpressionType::EXPRESSION) { return ""; } $sql = $this->buildSubTree($parsed, " "); $sql .= $this->buildAlias($parsed); return $sql; } } ?> ================================================ FILE: src/library/builders/SelectStatementBuilder.php ================================================ * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * @version SVN: $Id: SelectStatementBuilder.php 830 2013-12-18 09:35:42Z phosco@gmx.de $ * */ require_once dirname(__FILE__) . '/LimitBuilder.php'; require_once dirname(__FILE__) . '/SelectBuilder.php'; require_once dirname(__FILE__) . '/FromBuilder.php'; require_once dirname(__FILE__) . '/WhereBuilder.php'; require_once dirname(__FILE__) . '/GroupByBuilder.php'; require_once dirname(__FILE__) . '/OrderByBuilder.php'; /** * This class implements the builder for the whole Select statement. You can overwrite * all functions to achieve another handling. * * @author André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ class SelectStatementBuilder { protected function buildSELECT($parsed) { $builder = new SelectBuilder(); return $builder->build($parsed); } protected function buildFROM($parsed) { $builder = new FromBuilder(); return $builder->build($parsed); } protected function buildWHERE($parsed) { $builder = new WhereBuilder(); return $builder->build($parsed); } protected function buildGROUP($parsed) { $builder = new GroupByBuilder(); return $builder->build($parsed); } protected function buildORDER($parsed) { $builder = new OrderByBuilder(); return $builder->build($parsed); } protected function buildLIMIT($parsed) { $builder = new LimitBuilder(); return $builder->build($parsed); } public function build($parsed) { $sql = $this->buildSELECT($parsed['SELECT']); if (isset($parsed['FROM'])) { $sql .= " " . $this->buildFROM($parsed['FROM']); } if (isset($parsed['WHERE'])) { $sql .= " " . $this->buildWHERE($parsed['WHERE']); } if (isset($parsed['GROUP'])) { $sql .= " " . $this->buildGROUP($parsed['GROUP']); } if (isset($parsed['ORDER'])) { $sql .= " " . $this->buildORDER($parsed['ORDER']); } if (isset($parsed['LIMIT'])) { $sql .= " " . $this->buildLIMIT($parsed['LIMIT']); } return $sql; } } ?> ================================================ FILE: src/library/builders/SetBuilder.php ================================================ * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * @version SVN: $Id: SetBuilder.php 830 2013-12-18 09:35:42Z phosco@gmx.de $ * */ require_once dirname(__FILE__) . '/../exceptions/UnableToCreateSQLException.php'; require_once dirname(__FILE__) . '/SetExpressionBuilder.php'; /** * This class implements the builder for the SET part of INSERT statement. * You can overwrite all functions to achieve another handling. * * @author André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ class SetBuilder { protected function buildSetExpression($parsed) { $builder = new SetExpressionBuilder(); return $builder->build($parsed); } public function build($parsed) { $sql = ""; foreach ($parsed as $k => $v) { $len = strlen($sql); $sql .= $this->buildSetExpression($v); if ($len == strlen($sql)) { throw new UnableToCreateSQLException('SET', $k, $v, 'expr_type'); } $sql .= ","; } return "SET " . substr($sql, 0, -1); } } ?> ================================================ FILE: src/library/builders/SetExpressionBuilder.php ================================================ * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * @version SVN: $Id: SetExpressionBuilder.php 830 2013-12-18 09:35:42Z phosco@gmx.de $ * */ require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; require_once dirname(__FILE__) . '/../exceptions/UnableToCreateSQLException.php'; require_once dirname(__FILE__) . '/ColumnReferenceBuilder.php'; require_once dirname(__FILE__) . '/ConstantBuilder.php'; require_once dirname(__FILE__) . '/OperatorBuilder.php'; require_once dirname(__FILE__) . '/FunctionBuilder.php'; /** * This class implements the builder for the SET part of INSERT statement. * You can overwrite all functions to achieve another handling. * * @author André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ class SetExpressionBuilder { protected function buildColRef($parsed) { $builder = new ColumnReferenceBuilder(); return $builder->build($parsed); } protected function buildConstant($parsed) { $builder = new ConstantBuilder(); return $builder->build($parsed); } protected function buildOperator($parsed) { $builder = new OperatorBuilder(); return $builder->build($parsed); } protected function buildFunction($parsed) { $builder = new FunctionBuilder(); return $builder->build($parsed); } public function build($parsed) { if ($parsed['expr_type'] !== ExpressionType::EXPRESSION) { return ""; } $sql = ""; foreach ($parsed['sub_tree'] as $k => $v) { $len = strlen($sql); $sql .= $this->buildColRef($v); $sql .= $this->buildConstant($v); $sql .= $this->buildOperator($v); $sql .= $this->buildFunction($v); if ($len == strlen($sql)) { throw new UnableToCreateSQLException('SET expression subtree', $k, $v, 'expr_type'); } $sql .= " "; } $sql = substr($sql, 0, -1); return $sql; } } ?> ================================================ FILE: src/library/builders/ShowBuilder.php ================================================ * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * @version SVN: $Id: ShowBuilder.php 830 2013-12-18 09:35:42Z phosco@gmx.de $ * */ require_once dirname(__FILE__) . '/../exceptions/UnableToCreateSQLException.php'; require_once dirname(__FILE__) . '/ReservedBuilder.php'; require_once dirname(__FILE__) . '/ConstantBuilder.php'; require_once dirname(__FILE__) . '/EngineBuilder.php'; require_once dirname(__FILE__) . '/FunctionBuilder.php'; require_once dirname(__FILE__) . '/ProcedureBuilder.php'; require_once dirname(__FILE__) . '/DatabaseBuilder.php'; require_once dirname(__FILE__) . '/TableBuilder.php'; /** * This class implements the builder for the SHOW statement. * You can overwrite all functions to achieve another handling. * * @author André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ class ShowBuilder { protected function buildTable($parsed, $delim) { $builder = new TableBuilder(); return $builder->build($parsed, $delim); } protected function buildFunction($parsed) { $builder = new FunctionBuilder(); return $builder->build($parsed); } protected function buildProcedure($parsed) { $builder = new ProcedureBuilder(); return $builder->build($parsed); } protected function buildDatabase($parsed) { $builder = new DatabaseBuilder(); return $builder->build($parsed); } protected function buildEngine($parsed) { $builder = new EngineBuilder(); return $builder->build($parsed); } protected function buildConstant($parsed) { $builder = new ConstantBuilder(); return $builder->build($parsed); } protected function buildReserved($parsed) { $builder = new ReservedBuilder(); return $builder->build($parsed); } public function build($parsed) { $show = $parsed['SHOW']; $sql = ""; foreach ($show as $k => $v) { $len = strlen($sql); $sql .= $this->buildReserved($v); $sql .= $this->buildConstant($v); $sql .= $this->buildEngine($v); $sql .= $this->buildDatabase($v); $sql .= $this->buildProcedure($v); $sql .= $this->buildFunction($v); $sql .= $this->buildTable($v, 0); if ($len == strlen($sql)) { throw new UnableToCreateSQLException('SHOW', $k, $v, 'expr_type'); } $sql .= " "; } $sql = substr($sql, 0, -1); return "SHOW " . $sql; } } ?> ================================================ FILE: src/library/builders/ShowStatementBuilder.php ================================================ * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * @version SVN: $Id: ShowStatementBuilder.php 830 2013-12-18 09:35:42Z phosco@gmx.de $ * */ require_once dirname(__FILE__) . '/ShowBuilder.php'; require_once dirname(__FILE__) . '/WhereBuilder.php'; /** * This class implements the builder for the SHOW statement. * You can overwrite all functions to achieve another handling. * * @author André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ class ShowStatementBuilder { protected function buildWHERE($parsed) { $builder = new WhereBuilder(); return $builder->build($parsed); } protected function buildSHOW($parsed) { $builder = new ShowBuilder(); return $builder->build($parsed); } public function build($parsed) { $sql = $this->buildSHOW($parsed); if (isset($parsed['WHERE'])) { $sql .= " " . $this->buildWHERE($parsed['WHERE']); } return $sql; } } ?> ================================================ FILE: src/library/builders/SubQueryBuilder.php ================================================ * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * @version SVN: $Id: SubQueryBuilder.php 830 2013-12-18 09:35:42Z phosco@gmx.de $ * */ require_once dirname(__FILE__) . '/RefClauseBuilder.php'; require_once dirname(__FILE__) . '/RefTypeBuilder.php'; require_once dirname(__FILE__) . '/JoinBuilder.php'; require_once dirname(__FILE__) . '/AliasBuilder.php'; require_once dirname(__FILE__) . '/AliasBuilder.php'; require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; /** * This class implements the builder for sub-queries. * You can overwrite all functions to achieve another handling. * * @author André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ class SubQueryBuilder { protected function buildRefClause($parsed) { $builder = new RefClauseBuilder(); return $builder->build($parsed); } protected function buildRefType($parsed) { $builder = new RefTypeBuilder(); return $builder->build($parsed); } protected function buildJoin($parsed) { $builder = new JoinBuilder(); return $builder->build($parsed); } protected function buildAlias($parsed) { $builder = new AliasBuilder(); return $builder->build($parsed); } protected function buildSelectStatement($parsed) { $builder = new SelectStatementBuilder(); return $builder->build($parsed); } public function build($parsed, $index = 0) { if ($parsed['expr_type'] !== ExpressionType::SUBQUERY) { return ""; } $sql = $this->buildSelectStatement($parsed['sub_tree']); $sql = "(" . $sql . ")"; $sql .= $this->buildAlias($parsed); if ($index !== 0) { $sql = $this->buildJoin($parsed['join_type']) . $sql; $sql .= $this - buildRefType($parsed['ref_type']); $sql .= $this->buildRefClause($parsed['ref_clause']); } return $sql; } } ?> ================================================ FILE: src/library/builders/SubTreeBuilder.php ================================================ * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * @version SVN: $Id: SubTreeBuilder.php 830 2013-12-18 09:35:42Z phosco@gmx.de $ * */ require_once dirname(__FILE__) . '/../exceptions/UnableToCreateSQLException.php'; require_once dirname(__FILE__) . '/ReservedBuilder.php'; require_once dirname(__FILE__) . '/SelectBracketExpressionBuilder.php'; require_once dirname(__FILE__) . '/ColumnReferenceBuilder.php'; require_once dirname(__FILE__) . '/FunctionBuilder.php'; require_once dirname(__FILE__) . '/OperatorBuilder.php'; require_once dirname(__FILE__) . '/ConstantBuilder.php'; require_once dirname(__FILE__) . '/SubQueryBuilder.php'; require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; /** * This class implements the builder for [sub_tree] fields. * You can overwrite all functions to achieve another handling. * * @author André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ class SubTreeBuilder { protected function buildColRef($parsed) { $builder = new ColumnReferenceBuilder(); return $builder->build($parsed); } protected function buildFunction($parsed) { $builder = new FunctionBuilder(); return $builder->build($parsed); } protected function buildOperator($parsed) { $builder = new OperatorBuilder(); return $builder->build($parsed); } protected function buildConstant($parsed) { $builder = new ConstantBuilder(); return $builder->build($parsed); } protected function buildReserved($parsed) { $builder = new ReservedBuilder(); return $builder->build($parsed); } protected function buildSubQuery($parsed) { $builder = new SubQueryBuilder(); return $builder->build($parsed); } protected function buildSelectBracketExpression($parsed) { $builder = new SelectBracketExpressionBuilder(); return $builder->build($parsed); } public function build($parsed, $delim = " ") { if ($parsed['sub_tree'] === '') { return ""; } $sql = ""; foreach ($parsed['sub_tree'] as $k => $v) { $len = strlen($sql); $sql .= $this->buildColRef($v); $sql .= $this->buildFunction($v); $sql .= $this->buildOperator($v); $sql .= $this->buildConstant($v); $sql .= $this->buildSubQuery($v); $sql .= $this->buildSelectBracketExpression($v); $sql .= $this->buildReserved($v); if ($len == strlen($sql)) { throw new UnableToCreateSQLException('expression subtree', $k, $v, 'expr_type'); } $sql .= $delim; } return substr($sql, 0, -strlen($delim)); } } ?> ================================================ FILE: src/library/builders/TableBracketExpressionBuilder.php ================================================ * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * @version SVN: $Id: TableBracketExpressionBuilder.php 928 2014-01-08 13:01:57Z phosco@gmx.de $ * */ require_once dirname(__FILE__) . '/../exceptions/UnableToCreateSQLException.php'; require_once dirname(__FILE__) . '/ColumnDefinitionBuilder.php'; require_once dirname(__FILE__) . '/PrimaryKeyBuilder.php'; require_once dirname(__FILE__) . '/ForeignKeyBuilder.php'; require_once dirname(__FILE__) . '/CheckBuilder.php'; require_once dirname(__FILE__) . '/LikeExpressionBuilder.php'; require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; /** * This class implements the builder for the table expressions * within the create definitions of CREATE TABLE. * You can overwrite all functions to achieve another handling. * * @author André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ class TableBracketExpressionBuilder { protected function buildColDef($parsed) { $builder = new ColumnDefinitionBuilder(); return $builder->build($parsed); } protected function buildPrimaryKey($parsed) { $builder = new PrimaryKeyBuilder(); return $builder->build($parsed); } protected function buildForeignKey($parsed) { $builder = new ForeignKeyBuilder(); return $builder->build($parsed); } protected function buildCheck($parsed) { $builder = new CheckBuilder(); return $builder->build($parsed); } protected function buildLikeExpression($parsed) { $builder = new LikeExpressionBuilder(); return $builder->build($parsed); } public function build($parsed) { if ($parsed['expr_type'] !== ExpressionType::BRACKET_EXPRESSION) { return ""; } $sql = ""; foreach ($parsed['sub_tree'] as $k => $v) { $len = strlen($sql); $sql .= $this->buildColDef($v); $sql .= $this->buildPrimaryKey($v); $sql .= $this->buildCheck($v); $sql .= $this->buildLikeExpression($v); $sql .= $this->buildForeignKey($v); if ($len == strlen($sql)) { throw new UnableToCreateSQLException('CREATE TABLE create-def expression subtree', $k, $v, 'expr_type'); } $sql .= ", "; } $sql = " (" . substr($sql, 0, -2) . ")"; return $sql; } } ?> ================================================ FILE: src/library/builders/TableBuilder.php ================================================ * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * @version SVN: $Id: TableBuilder.php 830 2013-12-18 09:35:42Z phosco@gmx.de $ * */ require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; require_once dirname(__FILE__) . '/AliasBuilder.php'; require_once dirname(__FILE__) . '/JoinBuilder.php'; require_once dirname(__FILE__) . '/RefTypeBuilder.php'; require_once dirname(__FILE__) . '/RefClauseBuilder.php'; /** * This class implements the builder for the table name and join options. * You can overwrite all functions to achieve another handling. * * @author André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ class TableBuilder { protected function buildAlias($parsed) { $builder = new AliasBuilder(); return $builder->build($parsed); } protected function buildJoin($parsed) { $builder = new JoinBuilder(); return $builder->build($parsed); } protected function buildRefType($parsed) { $builder = new RefTypeBuilder(); return $builder->build($parsed); } protected function buildRefClause($parsed) { $builder = new RefClauseBuilder(); return $builder->build($parsed); } public function build($parsed, $index) { if ($parsed['expr_type'] !== ExpressionType::TABLE) { return ""; } $sql = $parsed['table']; $sql .= $this->buildAlias($parsed); if ($index !== 0) { $sql = $this->buildJoin($parsed['join_type']) . $sql; $sql .= $this->buildRefType($parsed['ref_type']); $sql .= $this->buildRefClause($parsed['ref_clause']); } return $sql; } } ?> ================================================ FILE: src/library/builders/TableExpressionBuilder.php ================================================ * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * @version SVN: $Id: TableExpressionBuilder.php 830 2013-12-18 09:35:42Z phosco@gmx.de $ * */ require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; require_once dirname(__FILE__) . '/AliasBuilder.php'; require_once dirname(__FILE__) . '/JoinBuilder.php'; require_once dirname(__FILE__) . '/RefTypeBuilder.php'; require_once dirname(__FILE__) . '/RefClauseBuilder.php'; require_once dirname(__FILE__) . '/FromBuilder.php'; /** * This class implements the builder for the table name and join options. * You can overwrite all functions to achieve another handling. * * @author André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ class TableExpressionBuilder { protected function buildFROM($parsed) { $builder = new FromBuilder(); return $builder->build($parsed); } protected function buildAlias($parsed) { $builder = new AliasBuilder(); return $builder->build($parsed); } protected function buildJoin($parsed) { $builder = new JoinBuilder(); return $builder->build($parsed); } protected function buildRefType($parsed) { $builder = new RefTypeBuilder(); return $builder->build($parsed); } protected function buildRefClause($parsed) { $builder = new RefClauseBuilder(); return $builder->build($parsed); } public function build($parsed, $index) { if ($parsed['expr_type'] !== ExpressionType::TABLE_EXPRESSION) { return ""; } $sql = substr($this->buildFROM($parsed['sub_tree']), 5); // remove FROM keyword $sql = "(" . $sql . ")"; $sql .= $this->buildAlias($parsed); if ($index !== 0) { $sql = $this->buildJoin($parsed['join_type']) . $sql; $sql .= $this->buildRefType($parsed['ref_type']); $sql .= $this->buildRefClause($parsed['ref_clause']); } return $sql; } } ?> ================================================ FILE: src/library/builders/UpdateBuilder.php ================================================ * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * @version SVN: $Id: UpdateBuilder.php 830 2013-12-18 09:35:42Z phosco@gmx.de $ * */ /** * This class implements the builder for the UPDATE statement parts. * You can overwrite all functions to achieve another handling. * * @author André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ class UpdateBuilder { public function build($parsed) { return "UPDATE " . $parsed[0]['table']; } } ?> ================================================ FILE: src/library/builders/UpdateStatementBuilder.php ================================================ * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * @version SVN: $Id: UpdateStatementBuilder.php 830 2013-12-18 09:35:42Z phosco@gmx.de $ * */ require_once dirname(__FILE__) . '/WhereBuilder.php'; require_once dirname(__FILE__) . '/SetBuilder.php'; require_once dirname(__FILE__) . '/UpdateBuilder.php'; /** * This class implements the builder for the whole Update statement. You can overwrite * all functions to achieve another handling. * * @author André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ class UpdateStatementBuilder { protected function buildWHERE($parsed) { $builder = new WhereBuilder(); return $builder->build($parsed); } protected function buildSET($parsed) { $builder = new SetBuilder(); return $builder->build($parsed); } protected function buildUPDATE($parsed) { $builder = new UpdateBuilder(); return $builder->build($parsed); } public function build($parsed) { $sql = $this->buildUPDATE($parsed['UPDATE']) . " " . $this->buildSET($parsed['SET']); if (isset($parsed['WHERE'])) { $sql .= " " . $this->buildWHERE($parsed['WHERE']); } return $sql; } } ?> ================================================ FILE: src/library/builders/UserVariableBuilder.php ================================================ * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * @version SVN: $Id: UserVariableBuilder.php 830 2013-12-18 09:35:42Z phosco@gmx.de $ * */ require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; /** * This class implements the builder for an user variable. * You can overwrite all functions to achieve another handling. * * @author André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ class UserVariableBuilder { public function build($parsed) { if ($parsed['expr_type'] !== ExpressionType::USER_VARIABLE) { return ""; } return $parsed['base_expr']; } } ?> ================================================ FILE: src/library/builders/ValuesBuilder.php ================================================ * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * @version SVN: $Id: ValuesBuilder.php 830 2013-12-18 09:35:42Z phosco@gmx.de $ * */ require_once dirname(__FILE__) . '/../exceptions/UnableToCreateSQLException.php'; require_once dirname(__FILE__) . '/RecordBuilder.php'; /** * This class implements the builder for the VALUES part of INSERT statement. * You can overwrite all functions to achieve another handling. * * @author André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ class ValuesBuilder { protected function buildRecord($parsed) { $builder = new RecordBuilder(); return $builder->build($parsed); } public function build($parsed) { $sql = ""; foreach ($parsed as $k => $v) { $len = strlen($sql); $sql .= $this->buildRecord($v); if ($len == strlen($sql)) { throw new UnableToCreateSQLException('VALUES', $k, $v, 'expr_type'); } $sql .= ","; } $sql = substr($sql, 0, -1); return "VALUES " . $sql; } } ?> ================================================ FILE: src/library/builders/WhereBracketExpressionBuilder.php ================================================ * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * @version SVN: $Id: WhereBracketExpressionBuilder.php 830 2013-12-18 09:35:42Z phosco@gmx.de $ * */ require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; require_once dirname(__FILE__) . '/../exceptions/UnableToCreateSQLException.php'; require_once dirname(__FILE__) . '/ColumnReferenceBuilder.php'; require_once dirname(__FILE__) . '/ConstantBuilder.php'; require_once dirname(__FILE__) . '/OperatorBuilder.php'; require_once dirname(__FILE__) . '/FunctionBuilder.php'; require_once dirname(__FILE__) . '/InListBuilder.php'; require_once dirname(__FILE__) . '/WhereExpressionBuilder.php'; require_once dirname(__FILE__) . '/WhereBracketExpressionBuilder.php'; require_once dirname(__FILE__) . '/UserVariableBuilder.php'; /** * This class implements the builder for bracket expressions within the WHERE part. * You can overwrite all functions to achieve another handling. * * @author André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ class WhereBracketExpressionBuilder { protected function buildColRef($parsed) { $builder = new ColumnReferenceBuilder(); return $builder->build($parsed); } protected function buildConstant($parsed) { $builder = new ConstantBuilder(); return $builder->build($parsed); } protected function buildOperator($parsed) { $builder = new OperatorBuilder(); return $builder->build($parsed); } protected function buildFunction($parsed) { $builder = new FunctionBuilder(); return $builder->build($parsed); } protected function buildInList($parsed) { $builder = new InListBuilder(); return $builder->build($parsed); } protected function buildWhereExpression($parsed) { $builder = new WhereExpressionBuilder(); return $builder->build($parsed); } protected function buildUserVariable($parsed) { $builder = new UserVariableBuilder(); return $builder->build($parsed); } public function build($parsed) { if ($parsed['expr_type'] !== ExpressionType::BRACKET_EXPRESSION) { return ""; } $sql = ""; foreach ($parsed['sub_tree'] as $k => $v) { $len = strlen($sql); $sql .= $this->buildColRef($v); $sql .= $this->buildConstant($v); $sql .= $this->buildOperator($v); $sql .= $this->buildInList($v); $sql .= $this->buildFunction($v); $sql .= $this->buildWhereExpression($v); $sql .= $this->build($v); $sql .= $this->buildUserVariable($v); if ($len == strlen($sql)) { throw new UnableToCreateSQLException('WHERE expression subtree', $k, $v, 'expr_type'); } $sql .= " "; } $sql = "(" . substr($sql, 0, -1) . ")"; return $sql; } } ?> ================================================ FILE: src/library/builders/WhereBuilder.php ================================================ * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * @version SVN: $Id: WhereBuilder.php 830 2013-12-18 09:35:42Z phosco@gmx.de $ * */ require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; require_once dirname(__FILE__) . '/../exceptions/UnableToCreateSQLException.php'; require_once dirname(__FILE__) . '/ColumnReferenceBuilder.php'; require_once dirname(__FILE__) . '/ConstantBuilder.php'; require_once dirname(__FILE__) . '/OperatorBuilder.php'; require_once dirname(__FILE__) . '/FunctionBuilder.php'; require_once dirname(__FILE__) . '/InListBuilder.php'; require_once dirname(__FILE__) . '/WhereExpressionBuilder.php'; require_once dirname(__FILE__) . '/WhereBracketExpressionBuilder.php'; require_once dirname(__FILE__) . '/UserVariableBuilder.php'; require_once dirname(__FILE__) . '/SubQueryBuilder.php'; /** * This class implements the builder for the WHERE part. * You can overwrite all functions to achieve another handling. * * @author André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ class WhereBuilder { protected function buildColRef($parsed) { $builder = new ColumnReferenceBuilder(); return $builder->build($parsed); } protected function buildConstant($parsed) { $builder = new ConstantBuilder(); return $builder->build($parsed); } protected function buildOperator($parsed) { $builder = new OperatorBuilder(); return $builder->build($parsed); } protected function buildFunction($parsed) { $builder = new FunctionBuilder(); return $builder->build($parsed); } protected function buildSubQuery($parsed) { $builder = new SubQueryBuilder(); return $builder->build($parsed); } protected function buildInList($parsed) { $builder = new InListBuilder(); return $builder->build($parsed); } protected function buildWhereExpression($parsed) { $builder = new WhereExpressionBuilder(); return $builder->build($parsed); } protected function buildWhereBracketExpression($parsed) { $builder = new WhereBracketExpressionBuilder(); return $builder->build($parsed); } protected function buildUserVariable($parsed) { $builder = new UserVariableBuilder(); return $builder->build($parsed); } public function build($parsed) { $sql = "WHERE "; foreach ($parsed as $k => $v) { $len = strlen($sql); $sql .= $this->buildOperator($v); $sql .= $this->buildConstant($v); $sql .= $this->buildColRef($v); $sql .= $this->buildSubQuery($v); $sql .= $this->buildInList($v); $sql .= $this->buildFunction($v); $sql .= $this->buildWhereExpression($v); $sql .= $this->buildWhereBracketExpression($v); $sql .= $this->buildUserVariable($v); if (strlen($sql) == $len) { throw new UnableToCreateSQLException('WHERE', $k, $v, 'expr_type'); } $sql .= " "; } return substr($sql, 0, -1); } } ?> ================================================ FILE: src/library/builders/WhereExpressionBuilder.php ================================================ * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * @version SVN: $Id: WhereExpressionBuilder.php 830 2013-12-18 09:35:42Z phosco@gmx.de $ * */ require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; require_once dirname(__FILE__) . '/../exceptions/UnableToCreateSQLException.php'; require_once dirname(__FILE__) . '/ColumnReferenceBuilder.php'; require_once dirname(__FILE__) . '/ConstantBuilder.php'; require_once dirname(__FILE__) . '/OperatorBuilder.php'; require_once dirname(__FILE__) . '/FunctionBuilder.php'; require_once dirname(__FILE__) . '/InListBuilder.php'; require_once dirname(__FILE__) . '/WhereExpressionBuilder.php'; require_once dirname(__FILE__) . '/WhereBracketExpressionBuilder.php'; require_once dirname(__FILE__) . '/UserVariableBuilder.php'; /** * This class implements the builder for expressions within the WHERE part. * You can overwrite all functions to achieve another handling. * * @author André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ class WhereExpressionBuilder { protected function buildColRef($parsed) { $builder = new ColumnReferenceBuilder(); return $builder->build($parsed); } protected function buildConstant($parsed) { $builder = new ConstantBuilder(); return $builder->build($parsed); } protected function buildOperator($parsed) { $builder = new OperatorBuilder(); return $builder->build($parsed); } protected function buildFunction($parsed) { $builder = new FunctionBuilder(); return $builder->build($parsed); } protected function buildInList($parsed) { $builder = new InListBuilder(); return $builder->build($parsed); } protected function buildWhereExpression($parsed) { $builder = new WhereExpressionBuilder(); return $builder->build($parsed); } protected function buildWhereBracketExpression($parsed) { $builder = new WhereBracketExpressionBuilder(); return $builder->build($parsed); } protected function buildUserVariable($parsed) { $builder = new UserVariableBuilder(); return $builder->build($parsed); } public function build($parsed) { if ($parsed['expr_type'] !== ExpressionType::EXPRESSION) { return ""; } $sql = ""; foreach ($parsed['sub_tree'] as $k => $v) { $len = strlen($sql); $sql .= $this->buildColRef($v); $sql .= $this->buildConstant($v); $sql .= $this->buildOperator($v); $sql .= $this->buildInList($v); $sql .= $this->buildFunction($v); $sql .= $this->buildWhereExpression($v); $sql .= $this->buildWhereBracketExpression($v); $sql .= $this->buildUserVariable($v); if ($len == strlen($sql)) { throw new UnableToCreateSQLException('WHERE expression subtree', $k, $v, 'expr_type'); } $sql .= " "; } $sql = substr($sql, 0, -1); return $sql; } } ?> ================================================ FILE: src/library/exceptions/InvalidParameterException.php ================================================ * * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * DAMAGE. */ /** * This exception will occur in the parser, if the given SQL statement * is not a String type. * * @author arothe * */ class InvalidParameterException extends InvalidArgumentException { protected $argument; public function __construct($argument) { $this->argument = $argument; parent::__construct("no SQL string to parse: \n" . $argument, 10); } public function getArgument() { return $this->argument; } } ?> ================================================ FILE: src/library/exceptions/UnableToCalculatePositionException.php ================================================ * * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * DAMAGE. */ /** * This exception will occur, if the PositionCalculator can not find the token * defined by a base_expr field within the original SQL statement. Please create * an issue in such a case, it is an application error. * * @author arothe * */ class UnableToCalculatePositionException extends Exception { protected $needle; protected $haystack; public function __construct($needle, $haystack) { $this->needle = $needle; $this->haystack = $haystack; parent::__construct("cannot calculate position of " . $needle . " within " . $haystack, 5); } public function getNeedle() { return $this->needle; } public function getHaystack() { return $this->haystack; } } ?> ================================================ FILE: src/library/exceptions/UnableToCreateSQLException.php ================================================ * * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * DAMAGE. */ /** * This exception will occur within the PHPSQLCreator, if the creator can not find a * method, which can handle the current expr_type field. It could be an error within the parser * output or a special case has not been modelled within the creator. Please create an issue * in such a case. * * @author arothe * */ class UnableToCreateSQLException extends Exception { protected $part; protected $partkey; protected $entry; protected $entrykey; public function __construct($part, $partkey, $entry, $entrykey) { $this->part = $part; $this->partkey = $partkey; $this->entry = $entry; $this->entrykey = $entrykey; parent::__construct("unknown [" . $entrykey . "] = " .$entry[$entrykey] . " in \"" . $part . "\" [" . $partkey . "] ", 15); } public function getEntry() { return $this->entry; } public function getEntryKey() { return $this->entrykey; } public function getSQLPart() { return $this->part; } public function getSQLPartKey() { return $this->partkey; } } ?> ================================================ FILE: src/library/exceptions/UnsupportedFeatureException.php ================================================ * * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * DAMAGE. */ /** * This exception will occur in the PHPSQLCreator, if the creator finds * a field name, which is unknown. The developers have created some * additional output of the parser, but the creator class has not been * enhanced. Please open an issue in such a case. * * @author arothe * */ class UnsupportedFeatureException extends Exception { protected $key; public function __construct($key) { $this->key = $key; parent::__construct($key . " not implemented.", 20); } public function getKey() { return $this->key; } } ?> ================================================ FILE: src/library/lexer/LexerSplitter.php ================================================ * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * @version SVN: $Id: LexerSplitter.php 842 2013-12-30 08:57:53Z phosco@gmx.de $ * */ /** * This class holds a sorted array of characters, which are used as stop token. * On every part of the array the given SQL string will be split into single tokens. * The array must be sorted by element size, longest first (3 chars -> 2 chars -> 1 char). * * @author André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ class LexerSplitter { protected static $splitters = array("<=>", "\r\n", "!=", ">=", "<=", "<>", "<<", ">>", ":=", "\\", "&&", "||", ":=", "/*", "*/", "--", ">", "<", "|", "=", "^", "(", ")", "\t", "\n", "'", "\"", "`", ",", "@", " ", "+", "-", "*", "/", ";"); protected $tokenSize; protected $hashSet; /** * Constructor. * * It initializes some fields. */ public function __construct() { $this->tokenSize = strlen(self::$splitters[0]); // should be the largest one $this->hashSet = array_flip(self::$splitters); } /** * Get the maximum length of a split token. * * The largest element must be on position 0 of the internal $_splitters array, * so the function returns the length of that token. It must be > 0. * * @return int The number of characters for the largest split token. */ public function getMaxLengthOfSplitter() { return $this->tokenSize; } /** * Looks into the internal split token array and compares the given token with * the array content. It returns true, if the token will be found, false otherwise. * * @param String $token a string, which could be a split token. * * @return boolean true, if the given string will be a split token, false otherwise */ public function isSplitter($token) { return isset($this->hashSet[$token]); } } ?> ================================================ FILE: src/library/lexer/PHPSQLLexer.php ================================================ * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * @version SVN: $Id: PHPSQLLexer.php 842 2013-12-30 08:57:53Z phosco@gmx.de $ * */ require_once dirname(__FILE__) . '/LexerSplitter.php'; require_once dirname(__FILE__) . '/../exceptions/InvalidParameterException.php'; /** * This class splits the SQL string into little parts, which the parser can * use to build the result array. * * @author André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ class PHPSQLLexer { protected $splitters; /** * Constructor. * * It initializes some fields. */ public function __construct() { $this->splitters = new LexerSplitter(); } /** * Ends the given string $haystack with the string $needle? * * @param string $haystack * @param string $needle * * @return boolean true, if the parameter $haystack ends with the character sequences $needle, false otherwise */ protected function endsWith($haystack, $needle) { $length = strlen($needle); if ($length == 0) { return true; } return (substr($haystack, -$length) === $needle); } public function split($sql) { if (!is_string($sql)) { throw new InvalidParameterException($sql); } $tokens = array(); $token = ""; $splitLen = $this->splitters->getMaxLengthOfSplitter(); $found = false; $len = strlen($sql); $pos = 0; while ($pos < $len) { for ($i = $splitLen; $i > 0; $i--) { $substr = substr($sql, $pos, $i); if ($this->splitters->isSplitter($substr)) { if ($token !== "") { $tokens[] = $token; } $tokens[] = $substr; $pos += $i; $token = ""; continue 2; } } $token .= $sql[$pos]; $pos++; } if ($token !== "") { $tokens[] = $token; } $tokens = $this->concatEscapeSequences($tokens); $tokens = $this->balanceBackticks($tokens); $tokens = $this->concatColReferences($tokens); $tokens = $this->balanceParenthesis($tokens); $tokens = $this->concatComments($tokens); $tokens = $this->concatUserDefinedVariables($tokens); return $tokens; } protected function concatUserDefinedVariables($tokens) { $i = 0; $cnt = count($tokens); $userdef = false; while ($i < $cnt) { if (!isset($tokens[$i])) { $i++; continue; } $token = $tokens[$i]; if ($userdef !== false) { $tokens[$userdef] .= $token; unset($tokens[$i]); if ($token !== "@") { $userdef = false; } } if ($userdef === false && $token === "@") { $userdef = $i; } $i++; } return array_values($tokens); } protected function concatComments($tokens) { $i = 0; $cnt = count($tokens); $comment = false; while ($i < $cnt) { if (!isset($tokens[$i])) { $i++; continue; } $token = $tokens[$i]; if ($comment !== false) { if ($inline === true && ($token === "\n" || $token === "\r\n")) { $comment = false; } else { unset($tokens[$i]); $tokens[$comment] .= $token; } if ($inline === false && ($token === "*/")) { $comment = false; } } if (($comment === false) && ($token === "--")) { $comment = $i; $inline = true; } if (($comment === false) && ($token === "/*")) { $comment = $i; $inline = false; } $i++; } return array_values($tokens); } protected function isBacktick($token) { return ($token === "'" || $token === "\"" || $token === "`"); } protected function balanceBackticks($tokens) { $i = 0; $cnt = count($tokens); while ($i < $cnt) { if (!isset($tokens[$i])) { $i++; continue; } $token = $tokens[$i]; if ($this->isBacktick($token)) { $tokens = $this->balanceCharacter($tokens, $i, $token); } $i++; } return $tokens; } // backticks are not balanced within one token, so we have // to re-combine some tokens protected function balanceCharacter($tokens, $idx, $char) { $token_count = count($tokens); $i = $idx + 1; while ($i < $token_count) { if (!isset($tokens[$i])) { $i++; continue; } $token = $tokens[$i]; $tokens[$idx] .= $token; unset($tokens[$i]); if ($token === $char) { break; } $i++; } return array_values($tokens); } /** * This function concats some tokens to a column reference. * There are two different cases: * * 1. If the current token ends with a dot, we will add the next token * 2. If the next token starts with a dot, we will add it to the previous token * */ protected function concatColReferences($tokens) { $cnt = count($tokens); $i = 0; while ($i < $cnt) { if (!isset($tokens[$i])) { $i++; continue; } if ($tokens[$i][0] === ".") { // concat the previous tokens, till the token has been changed $k = $i - 1; $len = strlen($tokens[$i]); while (($k >= 0) && ($len == strlen($tokens[$i]))) { if (!isset($tokens[$k])) { // FIXME: this can be wrong if we have schema . table . column $k--; continue; } $tokens[$i] = $tokens[$k] . $tokens[$i]; unset($tokens[$k]); $k--; } } if ($this->endsWith($tokens[$i], '.') && !is_numeric($tokens[$i])) { // concat the next tokens, till the token has been changed $k = $i + 1; $len = strlen($tokens[$i]); while (($k < $cnt) && ($len == strlen($tokens[$i]))) { if (!isset($tokens[$k])) { $k++; continue; } $tokens[$i] .= $tokens[$k]; unset($tokens[$k]); $k++; } } $i++; } return array_values($tokens); } protected function concatEscapeSequences($tokens) { $tokenCount = count($tokens); $i = 0; while ($i < $tokenCount) { if ($this->endsWith($tokens[$i], "\\")) { $i++; if (isset($tokens[$i])) { $tokens[$i - 1] .= $tokens[$i]; unset($tokens[$i]); } } $i++; } return array_values($tokens); } protected function balanceParenthesis($tokens) { $token_count = count($tokens); $i = 0; while ($i < $token_count) { if ($tokens[$i] !== '(') { $i++; continue; } $count = 1; for ($n = $i + 1; $n < $token_count; $n++) { $token = $tokens[$n]; if ($token === '(') { $count++; } if ($token === ')') { $count--; } $tokens[$i] .= $token; unset($tokens[$n]); if ($count === 0) { $n++; break; } } $i = $n; } return array_values($tokens); } } ?> ================================================ FILE: src/library/positions/PositionCalculator.php ================================================ * * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * DAMAGE. */ require_once dirname(__FILE__) . '/../utils/PHPSQLParserConstants.php'; require_once dirname(__FILE__) . '/../exceptions/UnableToCalculatePositionException.php'; /** * This class calculates the positions * of base_expr within the original SQL statement. * * @author arothe * */ class PositionCalculator { private static $_allowedOnOperator = array("\t", "\n", "\r", " ", ",", "(", ")", "_", "'", "\""); private static $_allowedOnOther = array("\t", "\n", "\r", " ", ",", "(", ")", "<", ">", "*", "+", "-", "/", "|", "&", "=", "!", ";"); private function _printPos($text, $sql, $charPos, $key, $parsed, $backtracking) { if (!isset($_ENV['DEBUG'])) { return; } $spaces = ""; $caller = debug_backtrace(); $i = 1; while ($caller[$i]['function'] === 'lookForBaseExpression') { $spaces .= " "; $i++; } $holdem = substr($sql, 0, $charPos) . "^" . substr($sql, $charPos); echo $spaces . $text . " key:" . $key . " parsed:" . $parsed . " back:" . serialize($backtracking) . " " . $holdem . "\n"; } public function setPositionsWithinSQL($sql, $parsed) { $charPos = 0; $backtracking = array(); $this->lookForBaseExpression($sql, $charPos, $parsed, 0, $backtracking); return $parsed; } private function findPositionWithinString($sql, $value, $expr_type) { $offset = 0; $ok = false; while (true) { $pos = strpos($sql, $value, $offset); if ($pos === false) { break; } $before = ""; if ($pos > 0) { $before = $sql[$pos - 1]; } $after = ""; if (isset($sql[$pos + strlen($value)])) { $after = $sql[$pos + strlen($value)]; } // if we have an operator, it should be surrounded by // whitespace, comma, parenthesis, digit or letter, end_of_string // an operator should not be surrounded by another operator if ($expr_type === 'operator') { $ok = ($before === "" || in_array($before, self::$_allowedOnOperator, true)) || (strtolower($before) >= 'a' && strtolower($before) <= 'z') || ($before >= '0' && $before <= '9'); $ok = $ok && ($after === "" || in_array($after, self::$_allowedOnOperator, true) || (strtolower($after) >= 'a' && strtolower($after) <= 'z') || ($after >= '0' && $after <= '9') || ($after === '?') || ($after === '@')); if (!$ok) { $offset = $pos + 1; continue; } break; } // in all other cases we accept // whitespace, comma, operators, parenthesis and end_of_string $ok = ($before === "" || in_array($before, self::$_allowedOnOther, true)); $ok = $ok && ($after === "" || in_array($after, self::$_allowedOnOther, true)); if ($ok) { break; } $offset = $pos + 1; } return $pos; } private function lookForBaseExpression($sql, &$charPos, &$parsed, $key, &$backtracking) { if (!is_numeric($key)) { if (($key === 'UNION' || $key === 'UNION ALL') || ($key === 'expr_type' && $parsed === ExpressionType::EXPRESSION) || ($key === 'expr_type' && $parsed === ExpressionType::SUBQUERY) || ($key === 'expr_type' && $parsed === ExpressionType::BRACKET_EXPRESSION) || ($key === 'expr_type' && $parsed === ExpressionType::TABLE_EXPRESSION) || ($key === 'expr_type' && $parsed === ExpressionType::RECORD) || ($key === 'expr_type' && $parsed === ExpressionType::IN_LIST) || ($key === 'expr_type' && $parsed === ExpressionType::MATCH_ARGUMENTS) || ($key === 'expr_type' && $parsed === ExpressionType::TABLE) || ($key === 'expr_type' && $parsed === ExpressionType::TEMPORARY_TABLE) || ($key === 'expr_type' && $parsed === ExpressionType::COLUMN_TYPE) || ($key === 'expr_type' && $parsed === ExpressionType::COLDEF) || ($key === 'expr_type' && $parsed === ExpressionType::PRIMARY_KEY) || ($key === 'expr_type' && $parsed === ExpressionType::CONSTRAINT) || ($key === 'expr_type' && $parsed === ExpressionType::COLUMN_LIST) || ($key === 'expr_type' && $parsed === ExpressionType::CHECK) || ($key === 'expr_type' && $parsed === ExpressionType::COLLATE) || ($key === 'expr_type' && $parsed === ExpressionType::LIKE) || ($key === 'expr_type' && $parsed === ExpressionType::INDEX) || ($key === 'select-option' && $parsed !== false) || ($key === 'alias' && $parsed !== false)) { // we hold the current position and come back after the next base_expr // we do this, because the next base_expr contains the complete expression/subquery/record // and we have to look into it too $backtracking[] = $charPos; } elseif (($key === 'ref_clause' || $key === 'columns') && $parsed !== false) { // we hold the current position and come back after n base_expr(s) // there is an array of sub-elements before (!) the base_expr clause of the current element // so we go through the sub-elements and must come at the end $backtracking[] = $charPos; for ($i = 1; $i < count($parsed); $i++) { $backtracking[] = false; // backtracking only after n base_expr! } } elseif (($key === 'sub_tree' && $parsed !== false) || ($key === 'options' && $parsed !== false)) { // we prevent wrong backtracking on subtrees (too much array_pop()) // there is an array of sub-elements after(!) the base_expr clause of the current element // so we go through the sub-elements and must not come back at the end for ($i = 1; $i < count($parsed); $i++) { $backtracking[] = false; } } elseif (($key === 'TABLE') || ($key === 'create-def' && $parsed !== false)) { // do nothing } else { // move the current pos after the keyword // SELECT, WHERE, INSERT etc. if (PHPSQLParserConstants::isReserved($key)) { $charPos = stripos($sql, $key, $charPos); $charPos += strlen($key); } } } if (!is_array($parsed)) { return; } foreach ($parsed as $key => $value) { if ($key === 'base_expr') { //$this->_printPos("0", $sql, $charPos, $key, $value, $backtracking); $subject = substr($sql, $charPos); $pos = $this->findPositionWithinString($subject, $value, isset($parsed['expr_type']) ? $parsed['expr_type'] : 'alias'); if ($pos === false) { throw new UnableToCalculatePositionException($value, $subject); } $parsed['position'] = $charPos + $pos; $charPos += $pos + strlen($value); //$this->_printPos("1", $sql, $charPos, $key, $value, $backtracking); $oldPos = array_pop($backtracking); if (isset($oldPos) && $oldPos !== false) { $charPos = $oldPos; } //$this->_printPos("2", $sql, $charPos, $key, $value, $backtracking); } else { $this->lookForBaseExpression($sql, $charPos, $parsed[$key], $key, $backtracking); } } } } ?> ================================================ FILE: src/library/processors/AbstractProcessor.php ================================================ * * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * DAMAGE. */ require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; require_once dirname(__FILE__) . '/../lexer/PHPSQLLexer.php'; /** * * This class processes contains some general functions for a processor. * * @author arothe * */ abstract class AbstractProcessor { /** * This function implements the main functionality of a processor class. * Always use default valuses for additional parameters within overridden functions. */ public abstract function process($tokens); /** * this function splits up a SQL statement into easy to "parse" * tokens for the SQL processor */ public function splitSQLIntoTokens($sql) { $lexer = new PHPSQLLexer(); return $lexer->split($sql); } /** * Revokes the quoting characters from an expression */ protected function revokeQuotation($sql) { $result = trim($sql); if (($result[0] === '`') && ($result[strlen($result) - 1] === '`')) { $result = substr($result, 1, -1); return trim(str_replace('``', '`', $result)); } if (($result[0] === "'") && ($result[strlen($result) - 1] === "'")) { $result = substr($result, 1, -1); return trim(str_replace("''", "'", $result)); } if (($result[0] === "\"") && ($result[strlen($result) - 1] === "\"")) { $result = substr($result, 1, -1); return trim(str_replace("\"\"", "\"", $result)); } return $sql; } /** * This method removes parenthesis from start of the given string. * It removes also the associated closing parenthesis. */ protected function removeParenthesisFromStart($token) { $parenthesisRemoved = 0; $trim = trim($token); if ($trim !== "" && $trim[0] === "(") { // remove only one parenthesis pair now! $parenthesisRemoved++; $trim[0] = " "; $trim = trim($trim); } $parenthesis = $parenthesisRemoved; $i = 0; $string = 0; while ($i < strlen($trim)) { if ($trim[$i] === "\\") { $i += 2; # an escape character, the next character is irrelevant continue; } if ($trim[$i] === "'" || $trim[$i] === '"') { $string++; } if (($string % 2 === 0) && ($trim[$i] === "(")) { $parenthesis++; } if (($string % 2 === 0) && ($trim[$i] === ")")) { if ($parenthesis == $parenthesisRemoved) { $trim[$i] = " "; $parenthesisRemoved--; } $parenthesis--; } $i++; } return trim($trim); } protected function getVariableType($expression) { // $expression must contain only upper-case characters if ($expression[1] !== "@") { return ExpressionType::USER_VARIABLE; } $type = substr($expression, 2, strpos($expression, ".", 2)); switch ($type) { case 'GLOBAL': $type = ExpressionType::GLOBAL_VARIABLE; break; case 'LOCAL': $type = ExpressionType::LOCAL_VARIABLE; break; case 'SESSION': default: $type = ExpressionType::SESSION_VARIABLE; break; } return $type; } protected function isCommaToken($token) { return (trim($token) === ","); } protected function isWhitespaceToken($token) { return (trim($token) === ""); } protected function isCommentToken($token) { return isset($token[0]) && isset($token[1]) && (($token[0] === '-' && $token[1] === '-') || ($token[0] === '/' && $token[1] === '*')); } protected function isColumnReference($out) { return (isset($out['expr_type']) && $out['expr_type'] === ExpressionType::COLREF); } protected function isReserved($out) { return (isset($out['expr_type']) && $out['expr_type'] === ExpressionType::RESERVED); } protected function isConstant($out) { return (isset($out['expr_type']) && $out['expr_type'] === ExpressionType::CONSTANT); } protected function isAggregateFunction($out) { return (isset($out['expr_type']) && $out['expr_type'] === ExpressionType::AGGREGATE_FUNCTION); } protected function isFunction($out) { return (isset($out['expr_type']) && $out['expr_type'] === ExpressionType::SIMPLE_FUNCTION); } protected function isExpression($out) { return (isset($out['expr_type']) && $out['expr_type'] === ExpressionType::EXPRESSION); } protected function isBracketExpression($out) { return (isset($out['expr_type']) && $out['expr_type'] === ExpressionType::BRACKET_EXPRESSION); } protected function isSubQuery($out) { return (isset($out['expr_type']) && $out['expr_type'] === ExpressionType::SUBQUERY); } /** * translates an array of objects into an associative array */ public function toArray($tokenList) { $expr = array(); foreach ($tokenList as $token) { $expr[] = $token->toArray(); } return (empty($expr) ? false : $expr); } protected function array_insert_after($array, $key, $entry) { $idx = array_search($key, array_keys($array)); $array = array_slice($array, 0, $idx + 1, true) + $entry + array_slice($array, $idx + 1, count($array) - 1, true); return $array; } } ?> ================================================ FILE: src/library/processors/ColumnDefinitionProcessor.php ================================================ * * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * DAMAGE. */ require_once dirname(__FILE__) . '/AbstractProcessor.php'; require_once dirname(__FILE__) . '/ReferenceDefinitionProcessor.php'; require_once dirname(__FILE__) . '/ExpressionListProcessor.php'; require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; /** * * This class processes the column definition part of a CREATE TABLE statement. * * @author arothe * */ class ColumnDefinitionProcessor extends AbstractProcessor { protected function processExpressionList($parsed) { $processor = new ExpressionListProcessor(); return $processor->process($parsed); } protected function processReferenceDefinition($parsed) { $processor = new ReferenceDefinitionProcessor(); return $processor->process($parsed); } protected function removeComma($tokens) { $res = array(); foreach ($tokens as $token) { if (trim($token) !== ',') { $res[] = $token; } } return $res; } protected function buildColDef($expr, $base_expr, $options, $refs, $key) { $expr = array('expr_type' => ExpressionType::COLUMN_TYPE, 'base_expr' => $base_expr, 'sub_tree' => $expr); // add options first $expr['sub_tree'] = array_merge($expr['sub_tree'], $options['sub_tree']); unset($options['sub_tree']); $expr = array_merge($expr, $options); // followed by references if (sizeof($refs) !== 0) { $expr['sub_tree'] = array_merge($expr['sub_tree'], $refs); } $expr['till'] = $key; return $expr; } public function process($tokens) { $trim = ''; $base_expr = ''; $currCategory = ''; $expr = array(); $refs = array(); $options = array('unique' => false, 'nullable' => true, 'auto_inc' => false, 'primary' => false, 'sub_tree' => array()); $skip = 0; foreach ($tokens as $key => $token) { $trim = trim($token); $base_expr .= $token; if ($skip > 0) { $skip--; continue; } if ($skip < 0) { break; } if ($trim === '') { continue; } $upper = strtoupper($trim); switch ($upper) { case ',': // we stop on a single comma and return // the $expr entry and the index $key $expr = $this->buildColDef($expr, trim(substr($base_expr, 0, -strlen($token))), $options, $refs, $key - 1); break 2; case 'VARCHAR': $expr[] = array('expr_type' => ExpressionType::DATA_TYPE, 'base_expr' => $trim, 'length' => false); $prevCategory = 'TEXT'; $currCategory = 'SINGLE_PARAM_PARENTHESIS'; continue 2; case 'VARBINARY': $expr[] = array('expr_type' => ExpressionType::DATA_TYPE, 'base_expr' => $trim, 'length' => false); $prevCategory = $upper; $currCategory = 'SINGLE_PARAM_PARENTHESIS'; continue 2; case 'UNSIGNED': $last = array_pop($expr); $last['unsigned'] = true; $expr[] = $last; continue 2; case 'ZEROFILL': $last = array_pop($expr); $last['zerofill'] = true; $expr[] = $last; continue 2; case 'BIT': case 'TINYBIT': case 'SMALLINT': case 'MEDIUMINT': case 'INT': case 'INTEGER': case 'BIGINT': $expr[] = array('expr_type' => ExpressionType::DATA_TYPE, 'base_expr' => $trim, 'unsigned' => false, 'zerofill' => false, 'length' => false); $currCategory = 'SINGLE_PARAM_PARENTHESIS'; $prevCategory = $upper; continue 2; case 'BINARY': if ($currCategory === 'TEXT') { $last = array_pop($expr); $last['binary'] = true; $last['sub_tree'][] = array('expr_type' => ExpressionType::RESERVED, 'base_expr' => $trim); $expr[] = $last; continue 2; } $expr[] = array('expr_type' => ExpressionType::DATA_TYPE, 'base_expr' => $trim, 'length' => false); $currCategory = 'SINGLE_PARAM_PARENTHESIS'; $prevCategory = $upper; continue 2; case 'CHAR': $expr[] = array('expr_type' => ExpressionType::DATA_TYPE, 'base_expr' => $trim, 'length' => false); $currCategory = 'SINGLE_PARAM_PARENTHESIS'; $prevCategory = 'TEXT'; continue 2; case 'REAL': case 'DOUBLE': case 'FLOAT': $expr[] = array('expr_type' => ExpressionType::DATA_TYPE, 'base_expr' => $trim, 'unsigned' => false, 'zerofill' => false); $currCategory = 'TWO_PARAM_PARENTHESIS'; $prevCategory = $upper; continue 2; case 'DECIMAL': case 'NUMERIC': $expr[] = array('expr_type' => ExpressionType::DATA_TYPE, 'base_expr' => $trim, 'unsigned' => false, 'zerofill' => false); $currCategory = 'TWO_PARAM_PARENTHESIS'; $prevCategory = $upper; continue 2; case 'DATE': case 'TIME': case 'TIMESTAMP': case 'DATETIME': case 'YEAR': case 'TINYBLOB': case 'BLOB': case 'MEDIUMBLOB': case 'LONGBLOB': $expr[] = array('expr_type' => ExpressionType::DATA_TYPE, 'base_expr' => $trim); $prevCategory = $currCategory = $upper; continue 2; // the next token can be BINARY case 'TINYTEXT': case 'TEXT': case 'MEDIUMTEXT': case 'LONGTEXT': $prevCategory = $currCategory = 'TEXT'; $expr[] = array('expr_type' => ExpressionType::DATA_TYPE, 'base_expr' => $trim, 'binary' => false); continue 2; case 'ENUM': case 'SET': $currCategory = 'MULTIPLE_PARAM_PARENTHESIS'; $prevCategory = 'TEXT'; $expr[] = array('expr_type' => ExpressionType::RESERVED, 'base_expr' => $trim, 'sub_tree' => false); continue 2; case 'GEOMETRY': case 'POINT': case 'LINESTRING': case 'POLYGON': case 'MULTIPOINT': case 'MULTILINESTRING': case 'MULTIPOLYGON': case 'GEOMETRYCOLLECTION': $expr[] = array('expr_type' => ExpressionType::DATA_TYPE, 'base_expr' => $trim); $prevCategory = $currCategory = $upper; // TODO: is it right? // spatial types continue 2; case 'CHARACTER': if ($prevCategory === 'TEXT') { $parsed = array('expr_type' => ExpressionType::DATA_TYPE, 'base_expr' => $trim); $expr[] = array('expr_type' => ExpressionType::CHARSET, 'base_expr' => substr($base_expr, 0, -1), 'sub_tree' => $parsed); $base_expr = $token; $currCategory = 'CHARSET'; continue 2; } // else ? break; case 'SET': if ($currCategory === 'CHARSET') { // TODO: is it necessary to set special properties like the name or collation? $parsed = array('expr_type' => ExpressionType::RESERVED, 'base_expr' => $trim); $last = array_pop($expr); $last['sub_tree'][] = $parsed; $expr[] = $last; continue 2; } // else ? break; case 'COLLATE': if ($prevCategory === 'TEXT') { $parsed = array('expr_type' => ExpressionType::RESERVED, 'base_expr' => $trim); $expr[] = array('expr_type' => ExpressionType::COLLATE, 'base_expr' => substr($base_expr, 0, -1), 'sub_tree' => $parsed); $base_expr = $token; $currCategory = 'COLLATION'; continue 2; } // else ? break; case 'NOT': case 'NULL': $options['sub_tree'][] = array('expr_type' => ExpressionType::RESERVED, 'base_expr' => $trim); if ($options['nullable']) { $options['nullable'] = ($upper === 'NOT' ? false : true); } continue 2; case 'DEFAULT': case 'COMMENT': $currCategory = $upper; $options['sub_tree'][] = array('expr_type' => ExpressionType::RESERVED, 'base_expr' => $trim); continue 2; case 'AUTO_INCREMENT': $options['sub_tree'][] = array('expr_type' => ExpressionType::RESERVED, 'base_expr' => $trim); $options['auto_inc'] = true; continue 2; case 'COLUMN_FORMAT': case 'STORAGE': $currCategory = $upper; $options['sub_tree'][] = array('expr_type' => ExpressionType::RESERVED, 'base_expr' => $trim); continue 2; case 'UNIQUE': // it can follow a KEY word $currCategory = $upper; $options['sub_tree'][] = array('expr_type' => ExpressionType::RESERVED, 'base_expr' => $trim); $options['unique'] = true; continue 2; case 'PRIMARY': // it must follow a KEY word $options['sub_tree'][] = array('expr_type' => ExpressionType::RESERVED, 'base_expr' => $trim); continue 2; case 'KEY': $options['sub_tree'][] = array('expr_type' => ExpressionType::RESERVED, 'base_expr' => $trim); if ($currCategory !== 'UNIQUE') { $options['primary'] = true; } continue 2; case 'REFERENCES': $refs = $this->processReferenceDefinition(array_splice($tokens, $key - 1, null, true)); $skip = $refs['till'] - $key; unset($refs['till']); // TODO: check this, we need the last comma continue 2; default: switch ($currCategory) { case 'STORAGE': if ($upper === 'DISK' || $upper === 'MEMORY' || $upper === 'DEFAULT') { $options['sub_tree'][] = array('expr_type' => ExpressionType::RESERVED, 'base_expr' => $trim); $options['storage'] = $trim; continue 3; } // else ? break; case 'COLUMN_FORMAT': if ($upper === 'FIXED' || $upper === 'DYNAMIC' || $upper === 'DEFAULT') { $options['sub_tree'][] = array('expr_type' => ExpressionType::RESERVED, 'base_expr' => $trim); $options['col_format'] = $trim; continue 3; } // else ? break; case 'COMMENT': // this is the comment string $options['sub_tree'][] = array('expr_type' => ExpressionType::COMMENT, 'base_expr' => $trim); $options['comment'] = $trim; $currCategory = $prevCategory; break; case 'DEFAULT': // this is the default value $options['sub_tree'][] = array('expr_type' => ExpressionType::DEF_VALUE, 'base_expr' => $trim); $options['default'] = $trim; $currCategory = $prevCategory; break; case 'COLLATE': // this is the collation name $parsed = array('expr_type' => ExpressionType::CONSTANT, 'base_expr' => $trim); $last = array_pop($expr); $last['sub_tree'][] = $parsed; $t = $base_expr; $base_expr = $last['base_expr'] . $base_expr; $last['base_expr'] = $t; $currCategory = $prevCategory; break; case 'CHARSET': // this is the character set name $parsed = array('expr_type' => ExpressionType::CONSTANT, 'base_expr' => $trim); $last = array_pop($expr); $last['sub_tree'][] = $parsed; $t = $base_expr; $base_expr = $last['base_expr'] . $base_expr; $last['base_expr'] = $t; $currCategory = $prevCategory; break; case 'SINGLE_PARAM_PARENTHESIS': $parsed = $this->removeParenthesisFromStart($trim); $parsed = array('expr_type' => ExpressionType::CONSTANT, 'base_expr' => trim($parsed)); $last = array_pop($expr); $last['length'] = $parsed['base_expr']; $expr[] = $last; $expr[] = array('expr_type' => ExpressionType::BRACKET_EXPRESSION, 'base_expr' => $trim, 'sub_tree' => array($parsed)); $currCategory = $prevCategory; break; case 'TWO_PARAM_PARENTHESIS': // maximum of two parameters $parsed = $this->removeParenthesisFromStart($trim); $parsed = $this->splitSQLIntoTokens($parsed); $parsed = $this->removeComma($parsed); $parsed = $this->processExpressionList($parsed); // TODO: check that $last = array_pop($expr); $last['length'] = $parsed[0]['base_expr']; $last['decimals'] = isset($parsed[1]) ? $parsed[1]['base_expr'] : false; $expr[] = $last; $expr[] = array('expr_type' => ExpressionType::BRACKET_EXPRESSION, 'base_expr' => $trim, 'sub_tree' => $parsed); $currCategory = $prevCategory; break; case 'MULTIPLE_PARAM_PARENTHESIS': // some parameters $parsed = $this->removeParenthesisFromStart($trim); $parsed = $this->splitSQLIntoTokens($parsed); $parsed = $this->removeComma($parsed); $this->processExpressionList($parsed); $last = array_pop($expr); $last['sub_tree'] = array('expr_type' => ExpressionType::BRACKET_EXPRESSION, 'base_expr' => $trim, 'sub_tree' => $parsed); $expr[] = $last; $currCategory = $prevCategory; break; default: break; } } $prevCategory = $currCategory; $currCategory = ''; } if (!isset($expr['till'])) { // end of $tokens array $expr = $this->buildColDef($expr, trim($base_expr), $options, $refs, -1); } return $expr; } } ?> ================================================ FILE: src/library/processors/ColumnListProcessor.php ================================================ * * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * DAMAGE. */ require_once dirname(__FILE__) . '/AbstractProcessor.php'; require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; /** * * This class processes column-lists. * * @author arothe * */ class ColumnListProcessor extends AbstractProcessor { public function process($tokens) { $columns = explode(",", $tokens); $cols = array(); foreach ($columns as $k => $v) { $cols[] = array('expr_type' => ExpressionType::COLREF, 'base_expr' => trim($v), 'no_quotes' => $this->revokeQuotation($v)); } return $cols; } } ?> ================================================ FILE: src/library/processors/CreateDefinitionProcessor.php ================================================ * * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * DAMAGE. */ require_once dirname(__FILE__) . '/AbstractProcessor.php'; require_once dirname(__FILE__) . '/ColumnDefinitionProcessor.php'; require_once dirname(__FILE__) . '/IndexColumnListProcessor.php'; require_once dirname(__FILE__) . '/ReferenceDefinitionProcessor.php'; require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; /** * * This class processes the create definition of the TABLE statements. * * @author arothe * */ class CreateDefinitionProcessor extends AbstractProcessor { protected function correctExpressionType(&$expr) { $type = ExpressionType::EXPRESSION; if (!isset($expr[0]) || !isset($expr[0]['expr_type'])) { return $type; } # replace the constraint type with a more descriptive one switch ($expr[0]['expr_type']) { case ExpressionType::CONSTRAINT: $type = $expr[1]['expr_type']; $expr[1]['expr_type'] = ExpressionType::RESERVED; break; case ExpressionType::COLREF: $type = ExpressionType::COLDEF; break; default: $type = $expr[0]['expr_type']; $expr[0]['expr_type'] = ExpressionType::RESERVED; break; } return $type; } public function process($tokens) { $base_expr = ""; $prevCategory = ""; $currCategory = ""; $expr = array(); $result = array(); $skip = 0; foreach ($tokens as $k => $token) { $trim = trim($token); $base_expr .= $token; if ($skip !== 0) { $skip--; continue; } if ($trim === "") { continue; } $upper = strtoupper($trim); switch ($upper) { case 'CONSTRAINT': $expr[] = array('expr_type' => ExpressionType::CONSTRAINT, 'base_expr' => $trim, 'sub_tree' => false); $currCategory = $prevCategory = $upper; continue 2; case 'LIKE': $expr[] = array('expr_type' => ExpressionType::LIKE, 'base_expr' => $trim); $currCategory = $prevCategory = $upper; continue 2; case 'FOREIGN': if ($prevCategory === "" || $prevCategory === "CONSTRAINT") { $expr[] = array('expr_type' => ExpressionType::FOREIGN_KEY, 'base_expr' => $trim); $currCategory = $upper; continue 2; } # else ? break; case 'PRIMARY': if ($prevCategory === "" || $prevCategory === "CONSTRAINT") { # next one is KEY $expr[] = array('expr_type' => ExpressionType::PRIMARY_KEY, 'base_expr' => $trim); $currCategory = $upper; continue 2; } # else ? break; case 'UNIQUE': if ($prevCategory === "" || $prevCategory === "CONSTRAINT") { # next one is KEY $expr[] = array('expr_type' => ExpressionType::UNIQUE_IDX, 'base_expr' => $trim); $currCategory = $upper; continue 2; } # else ? break; case 'KEY': # the next one is an index name if ($currCategory === 'PRIMARY' || $currCategory === 'FOREIGN' || $currCategory === 'UNIQUE') { $expr[] = array('expr_type' => ExpressionType::RESERVED, 'base_expr' => $trim); continue 2; } $expr[] = array('expr_type' => ExpressionType::INDEX, 'base_expr' => $trim); $currCategory = $upper; continue 2; case 'CHECK': $expr[] = array('expr_type' => ExpressionType::CHECK, 'base_expr' => $trim); $currCategory = $upper; continue 2; case 'INDEX': if ($currCategory === 'UNIQUE' || $currCategory === 'FULLTEXT' || $currCategory === 'SPATIAL') { $expr[] = array('expr_type' => ExpressionType::RESERVED, 'base_expr' => $trim); continue 2; } $expr[] = array('expr_type' => ExpressionType::INDEX, 'base_expr' => $trim); $currCategory = $upper; continue 2; case 'FULLTEXT': $expr[] = array('expr_type' => ExpressionType::FULLTEXT_IDX, 'base_expr' => $trim); $currCategory = $prevCategory = $upper; continue 2; case 'SPATIAL': $expr[] = array('expr_type' => ExpressionType::SPATIAL_IDX, 'base_expr' => $trim); $currCategory = $prevCategory = $upper; continue 2; case 'WITH': # starts an index option if ($currCategory === 'INDEX_COL_LIST') { $option = array('expr_type' => ExpressionType::RESERVED, 'base_expr' => $trim); $expr[] = array('expr_type' => ExpressionType::INDEX_PARSER, 'base_expr' => substr($base_expr, 0, -strlen($token)), 'sub_tree' => array($option)); $base_expr = $token; $currCategory = 'INDEX_PARSER'; continue 2; } break; case 'KEY_BLOCK_SIZE': # starts an index option if ($currCategory === 'INDEX_COL_LIST') { $option = array('expr_type' => ExpressionType::RESERVED, 'base_expr' => $trim); $expr[] = array('expr_type' => ExpressionType::INDEX_SIZE, 'base_expr' => substr($base_expr, 0, -strlen($token)), 'sub_tree' => array($option)); $base_expr = $token; $currCategory = 'INDEX_SIZE'; continue 2; } break; case 'USING': # starts an index option if ($currCategory === 'INDEX_COL_LIST' || $currCategory === 'PRIMARY') { $option = array('expr_type' => ExpressionType::RESERVED, 'base_expr' => $trim); $expr[] = array('base_expr' => substr($base_expr, 0, -strlen($token)), 'trim' => $trim, 'category' => $currCategory, 'sub_tree' => array($option)); $base_expr = $token; $currCategory = 'INDEX_TYPE'; continue 2; } # else ? break; case 'REFERENCES': if ($currCategory === 'INDEX_COL_LIST' && $prevCategory === 'FOREIGN') { $processor = new ReferenceDefinitionProcessor(); $refs = $processor->process(array_slice($tokens, $k - 1, null, true)); $skip = $refs['till'] - $k; unset($refs['till']); $expr[] = $refs; $currCategory = $upper; } break; case 'BTREE': case 'HASH': if ($currCategory === 'INDEX_TYPE') { $last = array_pop($expr); $last['sub_tree'][] = array('expr_type' => ExpressionType::RESERVED, 'base_expr' => $trim); $expr[] = array('expr_type' => ExpressionType::INDEX_TYPE, 'base_expr' => $base_expr, 'sub_tree' => $last['sub_tree']); $base_expr = $last['base_expr'] . $base_expr; # FIXME: it could be wrong for index_type within index_option $currCategory = $last['category']; continue 2; } #else break; case '=': if ($currCategory === 'INDEX_SIZE') { # the optional character between KEY_BLOCK_SIZE and the numeric constant $last = array_pop($expr); $last['sub_tree'][] = array('expr_type' => ExpressionType::RESERVED, 'base_expr' => $trim); $expr[] = $last; continue 2; } break; case 'PARSER': if ($currCategory === 'INDEX_PARSER') { $last = array_pop($expr); $last['sub_tree'][] = array('expr_type' => ExpressionType::RESERVED, 'base_expr' => $trim); $expr[] = $last; continue 2; } # else? break; case ',': # this starts the next definition $type = $this->correctExpressionType($expr); $result['create-def'][] = array('expr_type' => $type, 'base_expr' => trim(substr($base_expr, 0, -strlen($token))), 'sub_tree' => $expr); $base_expr = ""; $expr = array(); break; default: switch ($currCategory) { case 'LIKE': # this is the tablename after LIKE $expr[] = array('expr_type' => ExpressionType::TABLE, 'table' => $trim, 'base_expr' => $trim, 'no_quotes' => $this->revokeQuotation($trim)); break; case 'PRIMARY': if ($upper[0] === '(' && substr($upper, -1) === ')') { # the column list $processor = new IndexColumnListProcessor(); $cols = $processor->process($this->removeParenthesisFromStart($trim)); $expr[] = array('expr_type' => ExpressionType::COLUMN_LIST, 'base_expr' => $trim, 'sub_tree' => $cols); $prevCategory = $currCategory; $currCategory = "INDEX_COL_LIST"; continue 3; } # else? break; case 'FOREIGN': if ($upper[0] === '(' && substr($upper, -1) === ')') { $processor = new IndexColumnListProcessor(); $cols = $processor->process($this->removeParenthesisFromStart($trim)); $expr[] = array('expr_type' => ExpressionType::COLUMN_LIST, 'base_expr' => $trim, 'sub_tree' => $cols); $prevCategory = $currCategory; $currCategory = "INDEX_COL_LIST"; continue 3; } # index name $expr[] = array('expr_type' => ExpressionType::CONSTANT, 'base_expr' => $trim); continue 3; case 'KEY': case 'UNIQUE': case 'INDEX': if ($upper[0] === '(' && substr($upper, -1) === ')') { $processor = new IndexColumnListProcessor(); $cols = $processor->process($this->removeParenthesisFromStart($trim)); $expr[] = array('expr_type' => ExpressionType::COLUMN_LIST, 'base_expr' => $trim, 'sub_tree' => $cols); $prevCategory = $currCategory; $currCategory = "INDEX_COL_LIST"; continue 3; } # index name $expr[] = array('expr_type' => ExpressionType::CONSTANT, 'base_expr' => $trim); continue 3; case 'CONSTRAINT': # constraint name $last = array_pop($expr); $last['base_expr'] = $base_expr; $last['sub_tree'] = array('expr_type' => ExpressionType::CONSTANT, 'base_expr' => $trim); $expr[] = $last; continue 3; case 'INDEX_PARSER': # index parser name $last = array_pop($expr); $last['sub_tree'][] = array('expr_type' => ExpressionType::CONSTANT, 'base_expr' => $trim); $expr[] = array('expr_type' => ExpressionType::INDEX_PARSER, 'base_expr' => $base_expr, 'sub_tree' => $last['sub_tree']); $base_expr = $last['base_expr'] . $base_expr; $currCategory = 'INDEX_COL_LIST'; continue 3; case 'INDEX_SIZE': # index key block size numeric constant $last = array_pop($expr); $last['sub_tree'][] = array('expr_type' => ExpressionType::CONSTANT, 'base_expr' => $trim); $expr[] = array('expr_type' => ExpressionType::INDEX_SIZE, 'base_expr' => $base_expr, 'sub_tree' => $last['sub_tree']); $base_expr = $last['base_expr'] . $base_expr; $currCategory = 'INDEX_COL_LIST'; continue 3; case 'CHECK': if ($upper[0] === '(' && substr($upper, -1) === ')') { $processor = new ExpressionListProcessor(); $unparsed = $this->splitSQLIntoTokens($this->removeParenthesisFromStart($trim)); $parsed = $processor->process($unparsed); $expr[] = array('expr_type' => ExpressionType::BRACKET_EXPRESSION, 'base_expr' => $trim, 'sub_tree' => $parsed); } # else? break; case '': # if the currCategory is empty, we have an unknown token, # which is a column reference $expr[] = array('expr_type' => ExpressionType::COLREF, 'base_expr' => $trim, 'no_quotes' => $this->revokeQuotation($trim)); $currCategory = 'COLUMN_NAME'; continue 3; case 'COLUMN_NAME': # the column-definition # it stops on a comma or on a parenthesis $processor = new ColumnDefinitionProcessor(); $parsed = $processor->process(array_slice($tokens, $k, null, true), $expr); $skip = $parsed['till'] - $k; unset($parsed['till']); $expr[] = $parsed; $currCategory = ''; break; default: # ? break; } break; } $prevCategory = $currCategory; $currCategory = ''; } $type = $this->correctExpressionType($expr); $result['create-def'][] = array('expr_type' => $type, 'base_expr' => trim($base_expr), 'sub_tree' => $expr); return $result; } } ?> ================================================ FILE: src/library/processors/CreateProcessor.php ================================================ * * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * DAMAGE. */ require_once dirname(__FILE__) . '/AbstractProcessor.php'; require_once dirname(__FILE__) . '/../utils/ExpressionType.php'; /** * * This class processes the CREATE statements. * * @author arothe * */ class CreateProcessor extends AbstractProcessor { public function process($tokens) { $result = array(); $base_expr = ""; foreach ($tokens as $token) { $trim = strtoupper(trim($token)); $base_expr .= $token; if ($trim === "") { continue; } switch ($trim) { case 'TEMPORARY': $result['expr_type'] = ExpressionType::TEMPORARY_TABLE; $result['not-exists'] = false; $expr[] = array('expr_type' => ExpressionType::RESERVED, 'base_expr' => $trim); break; case 'TABLE': $result['expr_type'] = ExpressionType::TABLE; $result['not-exists'] = false; $expr[] = array('expr_type' => ExpressionType::RESERVED, 'base_expr' => $trim); break; case 'IF': $expr[] = array('expr_type' => ExpressionType::RESERVED, 'base_expr' => $trim); break; case 'NOT': $expr[] = array('expr_type' => ExpressionType::RESERVED, 'base_expr' => $trim); break; case 'EXISTS': $result['not-exists'] = true; $expr[] = array('expr_type' => ExpressionType::RESERVED, 'base_expr' => $trim); break; default: break; } } $result['base_expr'] = trim($base_expr); $result['sub_tree'] = $expr; return $result; } } ?> ================================================ FILE: src/library/processors/DefaultProcessor.php ================================================ * * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * DAMAGE. */ require_once(dirname(__FILE__) . '/AbstractProcessor.php'); require_once(dirname(__FILE__) . '/UnionProcessor.php'); require_once(dirname(__FILE__) . '/SQLProcessor.php'); /** * * This class processes the incoming sql string. * * @author arothe * */ class DefaultProcessor extends AbstractProcessor { public function process($sql) { $inputArray = $this->splitSQLIntoTokens($sql); // this is the highest level lexical analysis. This is the part of the // code which finds UNION and UNION ALL query parts $processor = new UnionProcessor(); $queries = $processor->process($inputArray); // If there was no UNION or UNION ALL in the query, then the query is // stored at $queries[0]. if (!$processor->isUnion($queries)) { $processor = new SQLProcessor(); $queries = $processor->process($queries[0]); } return $queries; } } ?> ================================================ FILE: src/library/processors/DeleteProcessor.php ================================================ * * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * DAMAGE. */ require_once(dirname(__FILE__) . '/AbstractProcessor.php'); /** * * This class processes the DELETE statements. * * @author arothe * */ class DeleteProcessor extends AbstractProcessor { public function process($tokens) { $tables = array(); $del = $tokens['DELETE']; foreach ($tokens['DELETE'] as $expression) { if ($expression !== 'DELETE' && trim($expression, ' .*') !== "" && !$this->isCommaToken($expression)) { $tables[] = trim($expression, '.* '); } } if (empty($tables)) { foreach ($tokens['FROM'] as $table) { $tables[] = $table['table']; } } $tokens['DELETE'] = array('TABLES' => $tables); return $tokens; } } ?> ================================================ FILE: src/library/processors/DescProcessor.php ================================================ * * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * DAMAGE. */ require_once(dirname(__FILE__) . '/ExplainProcessor.php'); /** * * This class processes the DESC statement. * * @author arothe * */ class DescProcessor extends ExplainProcessor { protected function isStatement($keys, $needle = "DESC") { return parent::isStatement($keys, $needle); } } ?> ================================================ FILE: src/library/processors/DescribeProcessor.php ================================================ * * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * DAMAGE. */ require_once(dirname(__FILE__) . '/ExplainProcessor.php'); /** * * This class processes the DESCRIBE statements. * * @author arothe * */ class DescribeProcessor extends ExplainProcessor { protected function isStatement($keys, $needle = "DESCRIBE") { return parent::isStatement($keys, $needle); } } ?> ================================================ FILE: src/library/processors/DropProcessor.php ================================================ * * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * DAMAGE. */ require_once(dirname(__FILE__) . '/../utils/ExpressionToken.php'); require_once(dirname(__FILE__) . '/../utils/ExpressionType.php'); require_once(dirname(__FILE__) . '/AbstractProcessor.php'); /** * * This class processes the DROP statements. * * @author arothe * */ class DropProcessor extends AbstractProcessor { // TODO: we should enhance it to get the positions for the IF EXISTS keywords // look into the CreateProcessor to get an idea. public function process($tokenList) { $skip = 0; $warning = true; $base_expr = ""; $expr_type = false; $option = false; $resultList = array(); foreach ($tokenList as $k => $v) { $token = new ExpressionToken($k, $v); if ($token->isWhitespaceToken()) { continue; } if ($skip > 0) { $skip --; continue; } switch ($token->getUpper()) { case 'VIEW': case 'SCHEMA': case 'DATABASE': case 'TABLE': $expr_type = strtolower($token->getTrim()); break; case 'IF': $warning = false; $skip = 1; break; case 'TEMPORARY': $expr_type = ExpressionType::TEMPORARY_TABLE; $skip = 1; break; case 'RESTRICT': case 'CASCADE': $option = $token->getUpper(); break; case ',': $resultList[] = array('expr_type' => $expr_type, 'base_expr' => $base_expr); $base_expr = ""; break; default: $base_expr .= $token->getToken(); } } if ($base_expr !== "") { $resultList[] = array('expr_type' => $expr_type, 'base_expr' => $base_expr); } return array('option' => $option, 'warning' => $warning, 'object_list' => $resultList); } } ?> ================================================ FILE: src/library/processors/DuplicateProcessor.php ================================================ * * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * DAMAGE. */ require_once(dirname(__FILE__) . '/SetProcessor.php'); /** * * This class processes the DUPLICATE statements. * * @author arothe * */ class DuplicateProcessor extends SetProcessor { public function process($tokens,$isUpdate = false) { return parent::process($tokens, false); } } ?> ================================================ FILE: src/library/processors/ExplainProcessor.php ================================================ * * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * DAMAGE. */ require_once(dirname(__FILE__) . '/AbstractProcessor.php'); require_once(dirname(__FILE__) . '/../utils/ExpressionType.php'); /** * * This class processes the EXPLAIN statements. * * @author arothe * */ class ExplainProcessor extends AbstractProcessor { protected function isStatement($keys, $needle = "EXPLAIN") { $pos = array_search($needle, $keys); if (isset($keys[$pos + 1])) { return in_array($keys[$pos + 1], array('SELECT', 'DELETE', 'INSERT', 'REPLACE', 'UPDATE'), true); } return false; } // TODO: refactor that function public function process($tokens, $keys = array()) { $base_expr = ""; $expr = array(); $currCategory = ""; if ($this->isStatement($keys)) { foreach ($tokens as $token) { $trim = trim($token); $base_expr .= $token; if ($trim === '') { continue; } $upper = strtoupper($trim); switch ($upper) { case 'EXTENDED': case 'PARTITIONS': return array('expr_type' => ExpressionType::RESERVED, 'base_expr' => $token); break; case 'FORMAT': if ($currCategory === '') { $currCategory = $upper; $expr[] = array('expr_type' => ExpressionType::RESERVED, 'base_expr' => $trim); } // else? break; case '=': if ($currCategory === 'FORMAT') { $expr[] = array('expr_type' => ExpressionType::OPERATOR, 'base_expr' => $trim); } // else? break; case 'TRADITIONAL': case 'JSON': if ($currCategory === 'FORMAT') { $expr[] = array('expr_type' => ExpressionType::RESERVED, 'base_expr' => $trim); return array('expr_type' => ExpressionType::EXPRESSION, 'base_expr' => trim($base_expr), 'sub_tree' => $expr); } // else? break; default: // ignore the other stuff break; } } return empty($expr) ? null : $expr; } foreach ($tokens as $token) { $trim = trim($token); if ($trim === '') { continue; } switch ($currCategory) { case 'TABLENAME': $currCategory = 'WILD'; $expr[] = array('expr_type' => ExpressionType::COLREF, 'base_expr' => $trim); break; case '': $currCategory = 'TABLENAME'; $expr[] = array('expr_type' => ExpressionType::TABLE, 'base_expr' => $trim); break; default: break; } } return empty($expr) ? null : $expr; } } ?> ================================================ FILE: src/library/processors/ExpressionListProcessor.php ================================================ * * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * DAMAGE. */ require_once(dirname(__FILE__) . '/AbstractProcessor.php'); require_once(dirname(__FILE__) . '/DefaultProcessor.php'); require_once(dirname(__FILE__) . '/../utils/ExpressionToken.php'); require_once(dirname(__FILE__) . '/../utils/ExpressionType.php'); /** * * This class processes expression lists. * * @author arothe * */ class ExpressionListProcessor extends AbstractProcessor { public function process($tokens) { $resultList = array(); $skip_next = false; $prev = new ExpressionToken(); foreach ($tokens as $k => $v) { $curr = new ExpressionToken($k, $v); if ($curr->isWhitespaceToken()) { continue; } if ($skip_next) { // skip the next non-whitespace token $skip_next = false; continue; } /* is it a subquery? */ if ($curr->isSubQueryToken()) { $processor = new DefaultProcessor(); $curr->setSubTree($processor->process($this->removeParenthesisFromStart($curr->getTrim()))); $curr->setTokenType(ExpressionType::SUBQUERY); } elseif ($curr->isEnclosedWithinParenthesis()) { /* is it an in-list? */ $localTokenList = $this->splitSQLIntoTokens($this->removeParenthesisFromStart($curr->getTrim())); if ($prev->getUpper() === 'IN') { foreach ($localTokenList as $k => $v) { $tmpToken = new ExpressionToken($k, $v); if ($tmpToken->isCommaToken()) { unset($localTokenList[$k]); } } $localTokenList = array_values($localTokenList); $curr->setSubTree($this->process($localTokenList)); $curr->setTokenType(ExpressionType::IN_LIST); } elseif ($prev->getUpper() === 'AGAINST') { $match_mode = false; foreach ($localTokenList as $k => $v) { $tmpToken = new ExpressionToken($k, $v); switch ($tmpToken->getUpper()) { case 'WITH': $match_mode = 'WITH QUERY EXPANSION'; break; case 'IN': $match_mode = 'IN BOOLEAN MODE'; break; default: } if ($match_mode !== false) { unset($localTokenList[$k]); } } $tmpToken = $this->process($localTokenList); if ($match_mode !== false) { $match_mode = new ExpressionToken(0, $match_mode); $match_mode->setTokenType(ExpressionType::MATCH_MODE); $tmpToken[] = $match_mode->toArray(); } $curr->setSubTree($tmpToken); $curr->setTokenType(ExpressionType::MATCH_ARGUMENTS); $prev->setTokenType(ExpressionType::SIMPLE_FUNCTION); } elseif ($prev->isColumnReference() || $prev->isFunction() || $prev->isAggregateFunction()) { // if we have a colref followed by a parenthesis pair, // it isn't a colref, it is a user-function // TODO: this should be a method, because we need the same code // below for unspecified tokens (expressions). $localExpr = new ExpressionToken(); $tmpExprList = array(); foreach ($localTokenList as $k => $v) { $tmpToken = new ExpressionToken($k, $v); if (!$tmpToken->isCommaToken()) { $localExpr->addToken($v); $tmpExprList[] = $v; } else { // an expression could have multiple parts split by operands // if we have a comma, it is a split-point for expressions $tmpExprList = array_values($tmpExprList); $localExprList = $this->process($tmpExprList); if (count($localExprList) > 1) { $localExpr->setSubTree($localExprList); $localExpr->setTokenType(ExpressionType::EXPRESSION); $localExprList = $localExpr->toArray(); $localExprList['alias'] = false; $localExprList = array($localExprList); } if (!$curr->getSubTree()) { $curr->setSubTree($localExprList); } else { $tmpExprList = $curr->getSubTree(); $curr->setSubTree(array_merge($tmpExprList, $localExprList)); } $tmpExprList = array(); $localExpr = new ExpressionToken(); } } $tmpExprList = array_values($tmpExprList); $localExprList = $this->process($tmpExprList); if (count($localExprList) > 1) { $localExpr->setSubTree($localExprList); $localExpr->setTokenType(ExpressionType::EXPRESSION); $localExprList = $localExpr->toArray(); $localExprList['alias'] = false; $localExprList = array($localExprList); } if (!$curr->getSubTree()) { $curr->setSubTree($localExprList); } else { $tmpExprList = $curr->getSubTree(); $curr->setSubTree(array_merge($tmpExprList, $localExprList)); } $prev->setSubTree($curr->getSubTree()); if ($prev->isColumnReference()) { $prev->setTokenType(ExpressionType::SIMPLE_FUNCTION); $prev->setNoQuotes(null); } array_pop($resultList); $curr = $prev; } // we have parenthesis, but it seems to be an expression if ($curr->isUnspecified()) { // TODO: the localTokenList could contain commas and further expressions, // we must handle that like function parameters (see above)! // this should solve issue 51 $curr->setSubTree($this->process($localTokenList)); $curr->setTokenType(ExpressionType::BRACKET_EXPRESSION); } } elseif ($curr->isVariableToken()) { # a variable # it can be quoted $curr->setTokenType($this->getVariableType($curr->getUpper())); $curr->setSubTree(false); $curr->setNoQuotes(trim(trim($curr->getToken()), '@'), "`'\""); } else { /* it is either an operator, a colref or a constant */ switch ($curr->getUpper()) { case '*': $curr->setSubTree(false); // o subtree // single or first element of expression list -> all-column-alias if (empty($resultList)) { $curr->setTokenType(ExpressionType::COLREF); break; } // if the last token is colref, const or expression // then * is an operator // but if the previous colref ends with a dot, the * is the all-columns-alias if (!$prev->isColumnReference() && !$prev->isConstant() && !$prev->isExpression() && !$prev->isBracketExpression() && !$prev->isAggregateFunction() && !$prev->isVariable()) { $curr->setTokenType(ExpressionType::COLREF); break; } if ($prev->isColumnReference() && $prev->endsWith(".")) { $prev->addToken('*'); // tablealias dot * continue 2; // skip the current token } $curr->setTokenType(ExpressionType::OPERATOR); break; case ':=': case 'AND': case '&&': case 'BETWEEN': case 'AND': case 'BINARY': case '&': case '~': case '|': case '^': case 'DIV': case '/': case '<=>': case '=': case '>=': case '>': case 'IS': case 'NOT': case '<<': case '<=': case '<': case 'LIKE': case '%': case '!=': case '<>': case 'REGEXP': case '!': case '||': case 'OR': case '>>': case 'RLIKE': case 'SOUNDS': case 'XOR': case 'IN': $curr->setSubTree(false); $curr->setTokenType(ExpressionType::OPERATOR); break; case 'NULL': $curr->setSubTree(false); $curr->setTokenType(ExpressionType::CONSTANT); break; case '-': case '+': // differ between preceding sign and operator $curr->setSubTree(false); if ($prev->isColumnReference() || $prev->isFunction() || $prev->isAggregateFunction() || $prev->isConstant() || $prev->isSubQuery() || $prev->isExpression() || $prev->isBracketExpression() || $prev->isVariable()) { $curr->setTokenType(ExpressionType::OPERATOR); } else { $curr->setTokenType(ExpressionType::SIGN); } break; default: $curr->setSubTree(false); switch ($curr->getToken(0)) { case "'": case '"': // it is a string literal $curr->setTokenType(ExpressionType::CONSTANT); break; case '`': // it is an escaped colum name $curr->setTokenType(ExpressionType::COLREF); $curr->setNoQuotes($curr->getToken()); break; default: if (is_numeric($curr->getToken())) { if ($prev->isSign()) { $prev->addToken($curr->getToken()); // it is a negative numeric constant $prev->setTokenType(ExpressionType::CONSTANT); continue 3; // skip current token } else { $curr->setTokenType(ExpressionType::CONSTANT); } } else { $curr->setTokenType(ExpressionType::COLREF); $curr->setNoQuotes($curr->getToken()); } break; } } } /* is a reserved word? */ if (!$curr->isOperator() && !$curr->isInList() && !$curr->isFunction() && !$curr->isAggregateFunction() && PHPSQLParserConstants::isReserved($curr->getUpper())) { if (PHPSQLParserConstants::isAggregateFunction($curr->getUpper())) { $curr->setTokenType(ExpressionType::AGGREGATE_FUNCTION); $curr->setNoQuotes(null); } elseif ($curr->getUpper() === 'NULL') { // it is a reserved word, but we would like to set it as constant $curr->setTokenType(ExpressionType::CONSTANT); } else { if (PHPSQLParserConstants::isParameterizedFunction($curr->getUpper())) { // issue 60: check functions with parameters // -> colref (we check parameters later) // -> if there is no parameter, we leave the colref $curr->setTokenType(ExpressionType::COLREF); } elseif (PHPSQLParserConstants::isFunction($curr->getUpper())) { $curr->setTokenType(ExpressionType::SIMPLE_FUNCTION); $curr->setNoQuotes(null); } else { $curr->setTokenType(ExpressionType::RESERVED); $curr->setNoQuotes(null); } } } // issue 94, INTERVAL 1 MONTH if ($curr->isConstant() && PHPSQLParserConstants::isParameterizedFunction($prev->getUpper())) { $prev->setTokenType(ExpressionType::RESERVED); $prev->setNoQuotes(null); } if ($prev->isConstant() && PHPSQLParserConstants::isParameterizedFunction($curr->getUpper())) { $curr->setTokenType(ExpressionType::RESERVED); $curr->setNoQuotes(null); } if ($curr->isUnspecified()) { $curr->setTokenType(ExpressionType::EXPRESSION); $curr->setNoQuotes(null); $curr->setSubTree($this->process($this->splitSQLIntoTokens($curr->getTrim()))); } $resultList[] = $curr; $prev = $curr; } // end of for-loop return $this->toArray($resultList); } } ?> ================================================ FILE: src/library/processors/FromProcessor.php ================================================ * * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * DAMAGE. */ require_once(dirname(__FILE__) . '/AbstractProcessor.php'); require_once(dirname(__FILE__) . '/ExpressionListProcessor.php'); require_once(dirname(__FILE__) . '/DefaultProcessor.php'); require_once(dirname(__FILE__) . '/../utils/ExpressionType.php'); /** * * This class processes the FROM statements. * * @author arothe * */ class FromProcessor extends AbstractProcessor { protected function initParseInfo($parseInfo = false) { // first init if ($parseInfo === false) { $parseInfo = array('join_type' => "", 'saved_join_type' => "JOIN"); } // loop init return array('expression' => "", 'token_count' => 0, 'table' => "", 'no_quotes' => "", 'alias' => false, 'join_type' => "", 'next_join_type' => "", 'saved_join_type' => $parseInfo['saved_join_type'], 'ref_type' => false, 'ref_expr' => false, 'base_expr' => false, 'sub_tree' => false, 'subquery' => ""); } protected function processFromExpression(&$parseInfo) { $res = array(); // exchange the join types (join_type is save now, saved_join_type holds the next one) $parseInfo['join_type'] = $parseInfo['saved_join_type']; // initialized with JOIN $parseInfo['saved_join_type'] = ($parseInfo['next_join_type'] ? $parseInfo['next_join_type'] : 'JOIN'); // we have a reg_expr, so we have to parse it if ($parseInfo['ref_expr'] !== false) { $unparsed = $this->splitSQLIntoTokens($this->removeParenthesisFromStart($parseInfo['ref_expr'])); // here we can get a comma separated list foreach ($unparsed as $k => $v) { if ($this->isCommaToken($v)) { $unparsed[$k] = ""; } } $processor = new ExpressionListProcessor(); $parseInfo['ref_expr'] = $processor->process($unparsed); } // there is an expression, we have to parse it if (substr(trim($parseInfo['table']), 0, 1) == '(') { $parseInfo['expression'] = $this->removeParenthesisFromStart($parseInfo['table']); if (preg_match("/^\\s*select/i", $parseInfo['expression'])) { $processor = new DefaultProcessor(); $parseInfo['sub_tree'] = $processor->process($parseInfo['expression']); $res['expr_type'] = ExpressionType::SUBQUERY; } else { $tmp = $this->splitSQLIntoTokens($parseInfo['expression']); $parseInfo['sub_tree'] = $this->process($tmp); $res['expr_type'] = ExpressionType::TABLE_EXPRESSION; } } else { $res['expr_type'] = ExpressionType::TABLE; $res['table'] = $parseInfo['table']; $res['no_quotes'] = $this->revokeQuotation($parseInfo['table']); } $res['alias'] = $parseInfo['alias']; $res['join_type'] = $parseInfo['join_type']; $res['ref_type'] = $parseInfo['ref_type']; $res['ref_clause'] = $parseInfo['ref_expr']; $res['base_expr'] = trim($parseInfo['expression']); $res['sub_tree'] = $parseInfo['sub_tree']; return $res; } public function process($tokens) { $parseInfo = $this->initParseInfo(); $expr = array(); $skip_next = false; $i = 0; foreach ($tokens as $token) { $upper = strtoupper(trim($token)); if ($skip_next && $token !== "") { $parseInfo['token_count']++; $skip_next = false; continue; } else { if ($skip_next) { continue; } } switch ($upper) { case 'OUTER': case 'LEFT': case 'RIGHT': case 'NATURAL': case 'CROSS': case ',': case 'JOIN': case 'INNER': break; default: $parseInfo['expression'] .= $token; if ($parseInfo['ref_type'] !== false) { // all after ON / USING $parseInfo['ref_expr'] .= $token; } break; } switch ($upper) { case 'AS': $parseInfo['alias'] = array('as' => true, 'name' => "", 'base_expr' => $token); $parseInfo['token_count']++; $n = 1; $str = ""; while ($str == "") { $parseInfo['alias']['base_expr'] .= ($tokens[$i + $n] === "" ? " " : $tokens[$i + $n]); $str = trim($tokens[$i + $n]); ++$n; } $parseInfo['alias']['name'] = $str; $parseInfo['alias']['no_quotes'] = $this->revokeQuotation($str); $parseInfo['alias']['base_expr'] = trim($parseInfo['alias']['base_expr']); continue; case 'INDEX': if ($token_category == 'CREATE') { $token_category = $upper; continue 2; } break; case 'USING': case 'ON': $parseInfo['ref_type'] = $upper; $parseInfo['ref_expr'] = ""; case 'CROSS': case 'USE': case 'FORCE': case 'IGNORE': case 'INNER': case 'OUTER': $parseInfo['token_count']++; continue; break; case 'FOR': $parseInfo['token_count']++; $skip_next = true; continue; break; case 'LEFT': case 'RIGHT': case 'STRAIGHT_JOIN': $parseInfo['next_join_type'] = $upper; break; case ',': $parseInfo['next_join_type'] = 'CROSS'; case 'JOIN': if ($parseInfo['subquery']) { $parseInfo['sub_tree'] = $this->parse($this->removeParenthesisFromStart($parseInfo['subquery'])); $parseInfo['expression'] = $parseInfo['subquery']; } $expr[] = $this->processFromExpression($parseInfo); $parseInfo = $this->initParseInfo($parseInfo); break; default: if ($upper === "") { continue; // ends the switch statement! } if ($parseInfo['token_count'] === 0) { if ($parseInfo['table'] === "") { $parseInfo['table'] = $token; $parseInfo['no_quotes'] = $this->revokeQuotation($token); } } else if ($parseInfo['token_count'] === 1) { $parseInfo['alias'] = array('as' => false, 'name' => trim($token), 'no_quotes' => $this->revokeQuotation($token), 'base_expr' => trim($token)); } $parseInfo['token_count']++; break; } ++$i; } $expr[] = $this->processFromExpression($parseInfo); return $expr; } } ?> ================================================ FILE: src/library/processors/GroupByProcessor.php ================================================ * * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * DAMAGE. */ require_once(dirname(__FILE__) . '/OrderByProcessor.php'); /** * * This class processes the GROUP-BY statements. * * @author arothe * */ class GroupByProcessor extends OrderByProcessor { public function process($tokens, $select = array()) { $out = array(); $parseInfo = $this->initParseInfo(); if (!$tokens) { return false; } foreach ($tokens as $token) { $trim = strtoupper(trim($token)); switch ($trim) { case ',': $parsed = $this->processOrderExpression($parseInfo, $select); unset($parsed['direction']); $out[] = $parsed; $parseInfo = $this->initParseInfo(); break; default: $parseInfo['base_expr'] .= $token; } } $parsed = $this->processOrderExpression($parseInfo, $select); unset($parsed['direction']); $out[] = $parsed; return $out; } } ?> ================================================ FILE: src/library/processors/HavingProcessor.php ================================================ * * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * DAMAGE. */ require_once(dirname(__FILE__) . '/ExpressionListProcessor.php'); /** * * This class processes the HAVING statements. * * @author arothe * */ class HavingProcessor extends ExpressionListProcessor { } ?> ================================================ FILE: src/library/processors/IndexColumnListProcessor.php ================================================ * * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * DAMAGE. */ require_once(dirname(__FILE__) . '/AbstractProcessor.php'); require_once(dirname(__FILE__) . '/../utils/ExpressionType.php'); /** * * This class processes the index column lists. * * @author arothe * */ class IndexColumnListProcessor extends AbstractProcessor { protected function initExpression() { return array('name' => false, 'no_quotes' => false, 'length' => false, 'dir' => false); } public function process($sql) { $tokens = $this->splitSQLIntoTokens($sql); $expr = $this->initExpression(); $result = array(); $base_expr = ""; foreach ($tokens as $k => $token) { $trim = trim($token); $base_expr .= $token; if ($trim === "") { continue; } $upper = strtoupper($trim); switch ($upper) { case 'ASC': case 'DESC': # the optional order $expr['dir'] = $trim; break; case ',': # the next column $result[] = array_merge(array('expr_type' => ExpressionType::INDEX_COLUMN, 'base_expr' => $base_expr), $expr); $expr = $this->initExpression(); $base_expr = ""; break; default: if ($upper[0] === '(' && substr($upper, -1) === ')') { # the optional length $expr['length'] = $this->removeParenthesisFromStart($trim); continue 2; } # the col name $expr['name'] = $trim; $expr['no_quotes'] = $this->revokeQuotation($trim); break; } } $result[] = array_merge(array('expr_type' => ExpressionType::INDEX_COLUMN, 'base_expr' => $base_expr), $expr); return $result; } } ?> ================================================ FILE: src/library/processors/InsertProcessor.php ================================================ * * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * DAMAGE. */ require_once(dirname(__FILE__) . '/AbstractProcessor.php'); require_once(dirname(__FILE__) . '/ColumnListProcessor.php'); require_once(dirname(__FILE__) . '/../utils/ExpressionType.php'); /** * * This class processes the INSERT statements. * * @author arothe * */ class InsertProcessor extends AbstractProcessor { public function process($tokenList, $token_category = 'INSERT') { $table = ""; $cols = array(); $into = $tokenList['INTO']; foreach ($into as $token) { if ($this->isWhitespaceToken($token)) continue; if ($table === "") { $table = $token; } elseif (empty($cols)) { $cols[] = $token; } } if (empty($cols)) { $cols = false; } else { $processor = new ColumnListProcessor(); $cols = $processor->process($this->removeParenthesisFromStart($cols[0])); } unset($tokenList['INTO']); $tokenList[$token_category][0] = array('table' => $table, 'columns' => $cols, 'base_expr' => $table, 'no_quotes' => $this->revokeQuotation($table)); return $tokenList; } } ?> ================================================ FILE: src/library/processors/IntoProcessor.php ================================================ * * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * DAMAGE. */ require_once(dirname(__FILE__) . '/AbstractProcessor.php'); /** * * This class processes the INTO statements. * * @author arothe * */ class IntoProcessor extends AbstractProcessor { /** * TODO: This is a dummy function, we cannot parse INTO as part of SELECT * at the moment */ public function process($tokenList) { $unparsed = $tokenList['INTO']; foreach ($unparsed as $k => $token) { if ($this->isWhitespaceToken($token) || $this->isCommaToken($token)) { unset($unparsed[$k]); } } $tokenList['INTO'] = array_values($unparsed); return $tokenList; } } ?> ================================================ FILE: src/library/processors/LimitProcessor.php ================================================ * * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * DAMAGE. */ require_once(dirname(__FILE__) . '/AbstractProcessor.php'); /** * * This class processes the LIMIT statements. * * @author arothe * */ class LimitProcessor extends AbstractProcessor { public function process($tokens) { $rowcount = ""; $offset = ""; $comma = -1; $exchange = false; for ($i = 0; $i < count($tokens); ++$i) { $trim = trim($tokens[$i]); if ($trim === ",") { $comma = $i; break; } if ($trim === "OFFSET") { $comma = $i; $exchange = true; break; } } for ($i = 0; $i < $comma; ++$i) { if ($exchange) { $rowcount .= $tokens[$i]; } else { $offset .= $tokens[$i]; } } for ($i = $comma + 1; $i < count($tokens); ++$i) { if ($exchange) { $offset .= $tokens[$i]; } else { $rowcount .= $tokens[$i]; } } return array('offset' => trim($offset), 'rowcount' => trim($rowcount)); } } ?> ================================================ FILE: src/library/processors/OrderByProcessor.php ================================================ * * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * DAMAGE. */ require_once(dirname(__FILE__) . '/AbstractProcessor.php'); require_once(dirname(__FILE__) . '/SelectExpressionProcessor.php'); require_once(dirname(__FILE__) . '/../utils/ExpressionType.php'); /** * * This class processes the ORDER-BY statements. * * @author arothe * */ class OrderByProcessor extends AbstractProcessor { private $selectExpressionProcessor; public function __construct() { $this->selectExpressionProcessor = new SelectExpressionProcessor(); } protected function initParseInfo() { return array('base_expr' => "", 'dir' => "ASC", 'expr_type' => ExpressionType::EXPRESSION); } protected function processOrderExpression(&$parseInfo, $select) { $parseInfo['base_expr'] = trim($parseInfo['base_expr']); if ($parseInfo['base_expr'] === "") { return false; } if (is_numeric($parseInfo['base_expr'])) { $parseInfo['expr_type'] = ExpressionType::POSITION; } else { $parseInfo['no_quotes'] = $this->revokeQuotation($parseInfo['base_expr']); // search to see if the expression matches an alias foreach ($select as $clause) { if (!$clause['alias']) { continue; } if ($clause['alias']['no_quotes'] === $parseInfo['no_quotes']) { $parseInfo['expr_type'] = ExpressionType::ALIAS; break; } } } if ($parseInfo['expr_type'] === ExpressionType::EXPRESSION) { $expr = $this->selectExpressionProcessor->process($parseInfo['base_expr']); $expr['direction'] = $parseInfo['dir']; unset($expr['alias']); return $expr; } $result = array(); $result['expr_type'] = $parseInfo['expr_type']; $result['base_expr'] = $parseInfo['base_expr']; if (isset($parseInfo['no_quotes'])) { $result['no_quotes'] = $parseInfo['no_quotes']; } $result['direction'] = $parseInfo['dir']; return $result; } public function process($tokens, $select = array()) { $out = array(); $parseInfo = $this->initParseInfo(); if (!$tokens) { return false; } foreach ($tokens as $token) { $upper = strtoupper(trim($token)); switch ($upper) { case ',': $out[] = $this->processOrderExpression($parseInfo, $select); $parseInfo = $this->initParseInfo(); break; case 'DESC': $parseInfo['dir'] = "DESC"; break; case 'ASC': $parseInfo['dir'] = "ASC"; break; default: $parseInfo['base_expr'] .= $token; } } $out[] = $this->processOrderExpression($parseInfo, $select); return $out; } } ?> ================================================ FILE: src/library/processors/RecordProcessor.php ================================================ * * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * DAMAGE. */ require_once(dirname(__FILE__) . '/AbstractProcessor.php'); require_once(dirname(__FILE__) . '/ExpressionListProcessor.php'); /** * * This class processes records. * * @author arothe * */ class RecordProcessor extends AbstractProcessor { private $expressionListProcessor; public function __construct() { $this->expressionListProcessor = new ExpressionListProcessor(); } public function process($unparsed) { $unparsed = $this->removeParenthesisFromStart($unparsed); $values = $this->splitSQLIntoTokens($unparsed); foreach ($values as $k => $v) { if ($this->isCommaToken($v)) { $values[$k] = ""; } } return $this->expressionListProcessor->process($values); } } ?> ================================================ FILE: src/library/processors/ReferenceDefinitionProcessor.php ================================================ * * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * DAMAGE. */ require_once(dirname(__FILE__) . '/AbstractProcessor.php'); require_once(dirname(__FILE__) . '/IndexColumnListProcessor.php'); require_once(dirname(__FILE__) . '/../utils/ExpressionType.php'); /** * * This class processes the reference definition part of the CREATE TABLE statements. * * @author arothe */ class ReferenceDefinitionProcessor extends AbstractProcessor { protected function buildReferenceDef($expr, $base_expr, $key) { $expr['till'] = $key; $expr['base_expr'] = $base_expr; return $expr; } public function process($tokens) { $expr = array('expr_type' => ExpressionType::REFERENCE, 'base_expr' => false, 'sub_tree' => array()); $base_expr = ''; foreach ($tokens as $key => $token) { $trim = trim($token); $base_expr .= $token; if ($trim === '') { continue; } $upper = strtoupper($trim); switch ($upper) { case ',': # we stop on a single comma # or at the end of the array $tokens $expr = $this->buildReferenceDef($expr, trim(substr($base_expr, 0, -strlen($token))), $key - 1); break 2; case 'REFERENCES': $expr['sub_tree'][] = array('expr_type' => ExpressionType::RESERVED, 'base_expr' => $trim); $currCategory = $upper; break; case 'MATCH': if ($currCategory === 'REF_COL_LIST') { $expr['sub_tree'][] = array('expr_type' => ExpressionType::RESERVED, 'base_expr' => $trim); $currCategory = 'REF_MATCH'; continue 2; } # else? break; case 'FULL': case 'PARTIAL': case 'SIMPLE': if ($currCategory === 'REF_MATCH') { $expr['sub_tree'][] = array('expr_type' => ExpressionType::RESERVED, 'base_expr' => $trim); $expr['match'] = $upper; $currCategory = 'REF_COL_LIST'; continue 2; } # else? break; case 'ON': if ($currCategory === 'REF_COL_LIST') { $expr['sub_tree'][] = array('expr_type' => ExpressionType::RESERVED, 'base_expr' => $trim); $currCategory = 'REF_ACTION'; continue 2; } # else ? break; case 'UPDATE': case 'DELETE': if ($currCategory === 'REF_ACTION') { $expr['sub_tree'][] = array('expr_type' => ExpressionType::RESERVED, 'base_expr' => $trim); $currCategory = 'REF_OPTION_' . $upper; continue 2; } # else ? break; case 'RESTRICT': case 'CASCADE': if (strpos($currCategory, 'REF_OPTION_') === 0) { $expr['sub_tree'][] = array('expr_type' => ExpressionType::RESERVED, 'base_expr' => $trim); $expr['on_' . strtolower(substr($currCategory, -6))] = $upper; continue 2; } # else ? break; case 'SET': case 'NO': if (strpos($currCategory, 'REF_OPTION_') === 0) { $expr['sub_tree'][] = array('expr_type' => ExpressionType::RESERVED, 'base_expr' => $trim); $expr['on_' . strtolower(substr($currCategory, -6))] = $upper; $currCategory = 'SEC_' . $currCategory; continue 2; } # else ? break; case 'NULL': case 'ACTION': if (strpos($currCategory, 'SEC_REF_OPTION_') === 0) { $expr['sub_tree'][] = array('expr_type' => ExpressionType::RESERVED, 'base_expr' => $trim); $expr['on_' . strtolower(substr($currCategory, -6))] .= ' ' . $upper; $currCategory = 'REF_COL_LIST'; continue 2; } # else ? break; default: switch ($currCategory) { case 'REFERENCES': if ($upper[0] === '(' && substr($upper, -1) === ')') { # index_col_name list $processor = new IndexColumnListProcessor(); $cols = $processor->process($this->removeParenthesisFromStart($trim)); $expr['sub_tree'][] = array('expr_type' => ExpressionType::COLUMN_LIST, 'base_expr' => $trim, 'sub_tree' => $cols); $currCategory = 'REF_COL_LIST'; continue 3; } # foreign key reference table name $expr['sub_tree'][] = array('expr_type' => ExpressionType::TABLE, 'table' => $trim, 'base_expr' => $trim, 'no_quotes' => $this->revokeQuotation($trim)); continue 3; default: # else ? break; } break; } } if (!isset($expr['till'])) { $expr = $this->buildReferenceDef($expr, trim($base_expr), -1); } return $expr; } } ?> ================================================ FILE: src/library/processors/RenameProcessor.php ================================================ * * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * DAMAGE. */ require_once(dirname(__FILE__) . '/AbstractProcessor.php'); require_once(dirname(__FILE__) . '/../utils/ExpressionToken.php'); require_once(dirname(__FILE__) . '/../utils/ExpressionType.php'); /** * * This class processes the RENAME statements. * * @author arothe * */ class RenameProcessor extends AbstractProcessor { public function process($tokenList) { $base_expr = ""; $resultList = array(); $tablePair = array(); foreach ($tokenList as $k => $v) { $token = new ExpressionToken($k, $v); if ($token->isWhitespaceToken()) { continue; } switch ($token->getUpper()) { case 'TO': // separate source table from destination $tablePair['source'] = array('expr_type' => ExpressionType::TABLE, 'table' => trim($base_expr), 'no_quotes' => $this->revokeQuotation($base_expr), 'base_expr' => $base_expr); $base_expr = ""; break; case ',': // split rename operations $tablePair['destination'] = array('expr_type' => ExpressionType::TABLE, 'table' => trim($base_expr), 'no_quotes' => $this->revokeQuotation($base_expr), 'base_expr' => $base_expr); $resultList[] = $tablePair; $tablePair = array(); $base_expr = ""; break; default: $base_expr .= $token->getToken(); break; } } if ($base_expr !== "") { $tablePair['destination'] = array('expr_type' => ExpressionType::TABLE, 'table' => trim($base_expr), 'no_quotes' => $this->revokeQuotation($base_expr), 'base_expr' => $base_expr); $resultList[] = $tablePair; } return $resultList; } } ?> ================================================ FILE: src/library/processors/ReplaceProcessor.php ================================================ * * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * DAMAGE. */ require_once(dirname(__FILE__) . '/InsertProcessor.php'); /** * * This class processes the REPLACE statements. * * @author arothe * */ class ReplaceProcessor extends InsertProcessor { public function process($tokenList,$token_category = 'REPLACE') { return parent::process($tokenList, 'REPLACE'); } } ?> ================================================ FILE: src/library/processors/SQLChunkProcessor.php ================================================ * * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * DAMAGE. */ require_once(dirname(__FILE__) . '/AbstractProcessor.php'); require_once(dirname(__FILE__) . '/FromProcessor.php'); require_once(dirname(__FILE__) . '/RecordProcessor.php'); require_once(dirname(__FILE__) . '/UpdateProcessor.php'); require_once(dirname(__FILE__) . '/DeleteProcessor.php'); require_once(dirname(__FILE__) . '/GroupByProcessor.php'); require_once(dirname(__FILE__) . '/RenameProcessor.php'); require_once(dirname(__FILE__) . '/UsingProcessor.php'); require_once(dirname(__FILE__) . '/DescribeProcessor.php'); require_once(dirname(__FILE__) . '/DescProcessor.php'); require_once(dirname(__FILE__) . '/HavingProcessor.php'); require_once(dirname(__FILE__) . '/ReplaceProcessor.php'); require_once(dirname(__FILE__) . '/ValuesProcessor.php'); require_once(dirname(__FILE__) . '/DropProcessor.php'); require_once(dirname(__FILE__) . '/InsertProcessor.php'); require_once(dirname(__FILE__) . '/SelectExpressionProcessor.php'); require_once(dirname(__FILE__) . '/WhereProcessor.php'); require_once(dirname(__FILE__) . '/DuplicateProcessor.php'); require_once(dirname(__FILE__) . '/IntoProcessor.php'); require_once(dirname(__FILE__) . '/SelectProcessor.php'); require_once(dirname(__FILE__) . '/ExplainProcessor.php'); require_once(dirname(__FILE__) . '/LimitProcessor.php'); require_once(dirname(__FILE__) . '/SetProcessor.php'); require_once(dirname(__FILE__) . '/ExpressionListProcessor.php'); require_once(dirname(__FILE__) . '/OrderByProcessor.php'); require_once(dirname(__FILE__) . '/ShowProcessor.php'); require_once(dirname(__FILE__) . '/CreateProcessor.php'); require_once(dirname(__FILE__) . '/TableProcessor.php'); /** * * This class processes the SQL chunks. * * @author arothe * */ class SQLChunkProcessor extends AbstractProcessor { protected function moveLIKE(&$out) { if (!isset($out['TABLE']['like'])) { return; } $out = $this->array_insert_after($out, 'TABLE', array('LIKE' => $out['TABLE']['like'])); unset($out['TABLE']['like']); } public function process($out) { if (!$out) { return false; } if (!empty($out['CREATE'])) { $processor = new CreateProcessor(); $out['CREATE'] = $processor->process($out['CREATE']); } if (!empty($out['TABLE'])) { $processor = new TableProcessor(); $out['TABLE'] = $processor->process($out['TABLE']); $this->moveLIKE($out); } if (!empty($out['EXPLAIN'])) { $processor = new ExplainProcessor(); $out['EXPLAIN'] = $processor->process($out['EXPLAIN'], array_keys($out)); } if (!empty($out['DESCRIBE'])) { $processor = new DescribeProcessor(); $out['DESCRIBE'] = $processor->process($out['DESCRIBE'], array_keys($out)); } if (!empty($out['DESC'])) { $processor = new DescProcessor(); $out['DESC'] = $processor->process($out['DESC'], array_keys($out)); } if (!empty($out['SELECT'])) { $processor = new SelectProcessor(); $out['SELECT'] = $processor->process($out['SELECT']); } if (!empty($out['FROM'])) { $processor = new FromProcessor(); $out['FROM'] = $processor->process($out['FROM']); } if (!empty($out['USING'])) { $processor = new UsingProcessor(); $out['USING'] = $processor->process($out['USING']); } if (!empty($out['UPDATE'])) { $processor = new UpdateProcessor(); $out['UPDATE'] = $processor->process($out['UPDATE']); } if (!empty($out['GROUP'])) { // set empty array if we have partial SQL statement $processor = new GroupByProcessor(); $out['GROUP'] = $processor->process($out['GROUP'], isset($out['SELECT']) ? $out['SELECT'] : array()); } if (!empty($out['ORDER'])) { // set empty array if we have partial SQL statement $processor = new OrderByProcessor(); $out['ORDER'] = $processor->process($out['ORDER'], isset($out['SELECT']) ? $out['SELECT'] : array()); } if (!empty($out['LIMIT'])) { $processor = new LimitProcessor(); $out['LIMIT'] = $processor->process($out['LIMIT']); } if (!empty($out['WHERE'])) { $processor = new WhereProcessor(); $out['WHERE'] = $processor->process($out['WHERE']); } if (!empty($out['HAVING'])) { $processor = new HavingProcessor(); $out['HAVING'] = $processor->process($out['HAVING']); } if (!empty($out['SET'])) { $processor = new SetProcessor(); $out['SET'] = $processor->process($out['SET'], isset($out['UPDATE'])); } if (!empty($out['DUPLICATE'])) { $processor = new DuplicateProcessor(); $out['ON DUPLICATE KEY UPDATE'] = $processor->process($out['DUPLICATE']); unset($out['DUPLICATE']); } if (!empty($out['INSERT'])) { $processor = new InsertProcessor(); $out = $processor->process($out); } if (!empty($out['REPLACE'])) { $processor = new ReplaceProcessor(); $out = $processor->process($out); } if (!empty($out['DELETE'])) { $processor = new DeleteProcessor(); $out = $processor->process($out); } if (!empty($out['VALUES'])) { $processor = new ValuesProcessor(); $out = $processor->process($out); } if (!empty($out['INTO'])) { $processor = new IntoProcessor(); $out = $processor->process($out); } if (!empty($out['DROP'])) { $processor = new DropProcessor(); $out['DROP'] = $processor->process($out['DROP']); } if (!empty($out['RENAME'])) { $processor = new RenameProcessor(); $out['RENAME'] = $processor->process($out['RENAME']); } if (!empty($out['SHOW'])) { $processor = new ShowProcessor(); $out['SHOW'] = $processor->process($out['SHOW']); } return $out; } } ?> ================================================ FILE: src/library/processors/SQLProcessor.php ================================================ * * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * DAMAGE. */ require_once(dirname(__FILE__) . '/AbstractProcessor.php'); require_once(dirname(__FILE__) . '/SQLChunkProcessor.php'); /** * * This class processes the base SQL statements. * * @author arothe * */ class SQLProcessor extends SQLChunkProcessor { /* * This function breaks up the SQL statement into logical sections. * Some sections are then further handled by specialized processors. */ public function process($tokens) { $prev_category = ""; $token_category = ""; $skip_next = 0; $out = false; $tokenCount = count($tokens); for ($tokenNumber = 0; $tokenNumber < $tokenCount; ++$tokenNumber) { $token = $tokens[$tokenNumber]; $trim = trim($token); // this removes also \n and \t! // if it starts with an "(", it should follow a SELECT if ($trim !== "" && $trim[0] === "(" && $token_category === "") { $token_category = 'SELECT'; } /* * If it isn't obvious, when $skip_next is set, then we ignore the next real token, that is we ignore whitespace. */ if ($skip_next > 0) { if ($trim === "") { if ($token_category !== "") { # is this correct?? $out[$token_category][] = $token; } continue; } #to skip the token we replace it with whitespace $trim = ""; $token = ""; $skip_next--; if ($skip_next > 0) { continue; } } $upper = strtoupper($trim); switch ($upper) { /* Tokens that get their own sections. These keywords have subclauses. */ case 'SELECT': case 'ORDER': case 'DUPLICATE': case 'VALUES': case 'GROUP': case 'HAVING': case 'WHERE': case 'CALL': case 'PROCEDURE': case 'FUNCTION': case 'SERVER': case 'LOGFILE': case 'DEFINER': case 'RETURNS': case 'TABLESPACE': case 'TRIGGER': case 'DO': case 'FLUSH': case 'KILL': case 'RESET': case 'STOP': case 'PURGE': case 'EXECUTE': case 'PREPARE': case 'DEALLOCATE': if ($trim === 'DEALLOCATE') { $skip_next = 1; } $token_category = $upper; break; case 'SET': if ($token_category !== 'TABLE') { $token_category = $upper; } break; case 'LIMIT': case 'PLUGIN': # no separate section if ($token_category === 'SHOW') { continue; } $token_category = $upper; break; case 'FROM': # this FROM is different from FROM in other DML (not join related) if ($token_category === 'PREPARE') { continue 2; } # no separate section if ($token_category === 'SHOW') { continue; } $token_category = $upper; break; case 'EXPLAIN': case 'DESCRIBE': case 'SHOW': $token_category = $upper; break; case 'DESC': if ($token_category === '') { // short version of DESCRIBE $token_category = $upper; } // else direction of ORDER-BY break; case 'RENAME': // jump over TABLE keyword $token_category = $upper; $skip_next = 1; continue 2; case 'DATABASE': case 'SCHEMA': if ($prev_category === 'DROP') { continue; } if ($prev_category === 'SHOW') { continue; } $token_category = $upper; break; case 'EVENT': // issue 71 if ($prev_category === 'DROP' || $prev_category === 'ALTER' || $prev_category === 'CREATE') { $token_category = $upper; } break; case 'DATA': // prevent wrong handling of DATA as keyword if ($prev_category === 'LOAD') { $token_category = $upper; } break; case 'INTO': // prevent wrong handling of CACHE within LOAD INDEX INTO CACHE... if ($prev_category === 'LOAD') { $out[$prev_category][] = $upper; continue 2; } $token_category = $upper; break; case 'USER': // prevent wrong processing as keyword if ($prev_category === 'CREATE' || $prev_category === 'RENAME' || $prev_category === 'DROP') { $token_category = $upper; } break; case 'VIEW': // prevent wrong processing as keyword if ($prev_category === 'CREATE' || $prev_category === 'ALTER' || $prev_category === 'DROP') { $token_category = $upper; } break; /* * These tokens get their own section, but have no subclauses. These tokens identify the statement but have no specific subclauses of their own. */ case 'DELETE': case 'ALTER': case 'INSERT': case 'TRUNCATE': case 'OPTIMIZE': case 'GRANT': case 'REVOKE': case 'HANDLER': case 'LOAD': case 'ROLLBACK': case 'SAVEPOINT': case 'UNLOCK': case 'INSTALL': case 'UNINSTALL': case 'ANALZYE': case 'BACKUP': case 'CHECKSUM': case 'REPAIR': case 'RESTORE': case 'USE': case 'HELP': $token_category = $upper; // set the category in case these get subclauses in a future version of MySQL $out[$upper][0] = $upper; continue 2; case 'REPLACE': if ($prev_category === 'TABLE') { # part of the CREATE TABLE statement $out[$prev_category][] = $upper; continue 2; } // set the category in case these get subclauses in a future version of MySQL $token_category = $upper; $out[$upper][0] = $upper; continue 2; case 'IGNORE': if ($prev_category === 'TABLE') { # part of the CREATE TABLE statement $out[$prev_category][] = $upper; continue 2; } $out['OPTIONS'][] = $upper; continue 2; break; case 'CHECK': if ($prev_category === 'TABLE') { $out[$prev_category][] = $upper; continue 2; } $token_category = $upper; $out[$upper][0] = $upper; continue 2; case 'CREATE': if ($prev_category === 'SHOW') { continue; } $token_category = $upper; break; case 'TABLE': if ($prev_category === 'CREATE') { $out[$prev_category][] = $upper; $token_category = $upper; } break; case 'TEMPORARY': if ($prev_category === 'CREATE') { $out[$prev_category][] = $upper; $token_category = $prev_category; continue 2; } break; case 'IF': if ($prev_category === 'TABLE') { $token_category = 'CREATE'; $out[$token_category] = array_merge($out[$token_category], $out[$prev_category]); $out[$prev_category] = array(); $out[$token_category][] = $upper; $prev_category = $token_category; continue 2; } break; case 'NOT': if ($prev_category === 'CREATE') { $token_category = $prev_category; $out[$prev_category][] = $upper; continue 2; } break; case 'EXISTS': if ($prev_category === 'CREATE') { $out[$prev_category][] = $upper; $prev_category = $token_category = 'TABLE'; continue 2; } break; case 'CACHE': if ($prev_category === "" || $prev_category === 'RESET' || $prev_category === 'FLUSH' || $prev_category === 'LOAD') { $token_category = $upper; continue 2; } break; /* This is either LOCK TABLES or SELECT ... LOCK IN SHARE MODE */ case 'LOCK': if ($token_category === "") { $token_category = $upper; $out[$upper][0] = $upper; } else { $trim = 'LOCK IN SHARE MODE'; $skip_next = 3; $out['OPTIONS'][] = $trim; } continue 2; break; case 'USING': /* USING in FROM clause is different from USING w/ prepared statement*/ if ($token_category === 'EXECUTE') { $token_category = $upper; continue 2; } if ($token_category === 'FROM' && !empty($out['DELETE'])) { $token_category = $upper; continue 2; } break; /* DROP TABLE is different from ALTER TABLE DROP ... */ case 'DROP': if ($token_category !== 'ALTER') { $token_category = $upper; continue 2; } break; case 'FOR': if ($prev_category === 'SHOW') { continue; } $skip_next = 1; $out['OPTIONS'][] = 'FOR UPDATE'; continue 2; break; case 'UPDATE': if ($token_category === "") { $token_category = $upper; continue 2; } if ($token_category === 'DUPLICATE') { continue 2; } break; case 'START': $trim = "BEGIN"; $out[$upper][0] = $upper; $skip_next = 1; break; /* These tokens are ignored. */ case 'TO': if ($token_category === 'RENAME') { break; } case 'BY': case 'ALL': case 'SHARE': case 'MODE': case ';': continue 2; break; case 'KEY': if ($token_category === 'DUPLICATE') { continue 2; } break; /* These tokens set particular options for the statement. They never stand alone. */ case 'LOW_PRIORITY': case 'DELAYED': case 'FORCE': case 'QUICK': $out['OPTIONS'][] = $upper; continue 2; break; case 'WITH': if ($token_category === 'GROUP') { $skip_next = 1; $out['OPTIONS'][] = 'WITH ROLLUP'; continue 2; } break; case 'AS': break; case '': case ',': case ';': break; default: break; } // remove obsolete category after union (empty category because of // empty token before select) if ($token_category !== "" && ($prev_category === $token_category)) { $out[$token_category][] = $token; } $prev_category = $token_category; } return parent::process($out); } } ?> ================================================ FILE: src/library/processors/SelectExpressionProcessor.php ================================================ * * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * DAMAGE. */ require_once(dirname(__FILE__) . '/AbstractProcessor.php'); require_once(dirname(__FILE__) . '/ExpressionListProcessor.php'); require_once(dirname(__FILE__) . '/../utils/ExpressionType.php'); /** * * This class processes the SELECT expressions. * * @author arothe * */ class SelectExpressionProcessor extends AbstractProcessor { private $expressionListProcessor; public function __construct() { $this->expressionListProcessor = new ExpressionListProcessor(); } /** * This fuction processes each SELECT clause. * We determine what (if any) alias * is provided, and we set the type of expression. */ public function process($expression) { $tokens = $this->splitSQLIntoTokens($expression); $token_count = count($tokens); if ($token_count === 0) { return null; } /* * Determine if there is an explicit alias after the AS clause. * If AS is found, then the next non-whitespace token is captured as the alias. * The tokens after (and including) the AS are removed. */ $base_expr = ""; $stripped = array(); $capture = false; $alias = false; $processed = false; for ($i = 0; $i < $token_count; ++$i) { $token = $tokens[$i]; $upper = strtoupper($token); if ($upper === 'AS') { $alias = array('as' => true, "name" => "", "base_expr" => $token); $tokens[$i] = ""; $capture = true; continue; } if (!$this->isWhitespaceToken($upper)) { $stripped[] = $token; } // we have an explicit AS, next one can be the alias // but also a comment! if ($capture) { if (!$this->isWhitespaceToken($upper) && !$this->isCommentToken($upper)) { $alias['name'] .= $token; array_pop($stripped); } $alias['base_expr'] .= $token; $tokens[$i] = ""; continue; } $base_expr .= $token; } $stripped = $this->expressionListProcessor->process($stripped); // TODO: the last part can also be a comment, don't use array_pop // we remove the last token, if it is a colref, // it can be an alias without an AS $last = array_pop($stripped); if (!$alias && $this->isColumnReference($last)) { // TODO: it can be a comment, don't use array_pop // check the token before the colref $prev = array_pop($stripped); if ($this->isReserved($prev) || $this->isConstant($prev) || $this->isAggregateFunction($prev) || $this->isFunction($prev) || $this->isExpression($prev) || $this->isSubQuery($prev) || $this->isColumnReference($prev) || $this->isBracketExpression($prev)) { $alias = array('as' => false, 'name' => trim($last['base_expr']), 'no_quotes' => $this->revokeQuotation($last['base_expr']), 'base_expr' => trim($last['base_expr'])); // remove the last token array_pop($tokens); $base_expr = join("", $tokens); } } if (!$alias) { $base_expr = join("", $tokens); } else { /* remove escape from the alias */ $alias['no_quotes'] = $this->revokeQuotation($alias['name']); $alias['name'] = trim($alias['name']); $alias['base_expr'] = trim($alias['base_expr']); } // TODO: this is always done with $stripped, how we do it twice? $processed = $this->expressionListProcessor->process($tokens); // if there is only one part, we copy the expr_type // in all other cases we use "expression" as global type $type = ExpressionType::EXPRESSION; $no_quotes = $this->revokeQuotation(trim($base_expr)); if (count($processed) === 1) { if (!$this->isSubQuery($processed[0])) { $type = $processed[0]['expr_type']; $base_expr = $processed[0]['base_expr']; $no_quotes = isset($processed[0]['no_quotes']) ? $processed[0]['no_quotes'] : null; $processed = $processed[0]['sub_tree']; // it can be FALSE } } $result = array(); $result['expr_type'] = $type; $result['alias'] = $alias; $result['base_expr'] = trim($base_expr); if (!empty($no_quotes)) { $result['no_quotes'] = $no_quotes; } $result['sub_tree'] = $processed; return $result; } } ?> ================================================ FILE: src/library/processors/SelectProcessor.php ================================================ * * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * DAMAGE. */ require_once(dirname(__FILE__) . '/SelectExpressionProcessor.php'); /** * * This class processes the SELECT statements. * * @author arothe * */ class SelectProcessor extends SelectExpressionProcessor { public function process($tokens) { $expression = ""; $expressionList = array(); foreach ($tokens as $token) { if ($this->isCommaToken($token)) { $expression = parent::process(trim($expression)); $expression['delim'] = ','; $expressionList[] = $expression; $expression = ""; } else { switch (strtoupper($token)) { // add more SELECT options here case 'DISTINCT': case 'DISTINCTROW': case 'HIGH_PRIORITY': case 'SQL_CACHE': case 'SQL_NO_CACHE': case 'SQL_CALC_FOUND_ROWS': case 'STRAIGHT_JOIN': case 'SQL_SMALL_RESULT': case 'SQL_BIG_RESULT': case 'SQL_BUFFER_RESULT': $expression = parent::process(trim($token)); $expression['delim'] = ' '; $expressionList[] = $expression; $expression = ""; break; default: $expression .= $token; } } } if ($expression) { $expression = parent::process(trim($expression)); $expression['delim'] = false; $expressionList[] = $expression; } return $expressionList; } } ?> ================================================ FILE: src/library/processors/SetProcessor.php ================================================ * * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * DAMAGE. */ require_once(dirname(__FILE__) . '/AbstractProcessor.php'); require_once(dirname(__FILE__) . '/ExpressionListProcessor.php'); require_once(dirname(__FILE__) . '/../utils/ExpressionType.php'); /** * * This class processes the SET statements. * * @author arothe * */ class SetProcessor extends AbstractProcessor { private $expressionListProcessor; public function __construct() { $this->expressionListProcessor = new ExpressionListProcessor(); } /** * A SET list is simply a list of key = value expressions separated by comma (,). * This function produces a list of the key/value expressions. */ protected function getAssignment($base_expr) { $assignment = $this->expressionListProcessor->process($this->splitSQLIntoTokens($base_expr)); return array('expr_type' => ExpressionType::EXPRESSION, 'base_expr' => trim($base_expr), 'sub_tree' => $assignment); } public function process($tokens, $isUpdate = false) { $result = array(); $baseExpr = ""; $assignment = false; $varType = false; foreach ($tokens as $token) { $upper = strtoupper(trim($token)); switch ($upper) { case 'LOCAL': case 'SESSION': case 'GLOBAL': if (!$isUpdate) { $varType = $this->getVariableType("@@" . $upper . "."); $baseExpr = ""; continue 2; } break; case ',': $assignment = $this->getAssignment($baseExpr); if (!$isUpdate && $varType !== false) { $assignment['sub_tree'][0]['expr_type'] = $varType; } $result[] = $assignment; $baseExpr = ""; $varType = false; continue 2; default: } $baseExpr .= $token; } if (trim($baseExpr) !== "") { $assignment = $this->getAssignment($baseExpr); if (!$isUpdate && $varType !== false) { $assignment['sub_tree'][0]['expr_type'] = $varType; } $result[] = $assignment; } return $result; } } ?> ================================================ FILE: src/library/processors/ShowProcessor.php ================================================ * * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * DAMAGE. */ require_once(dirname(__FILE__) . '/../utils/PHPSQLParserConstants.php'); require_once(dirname(__FILE__) . '/../utils/ExpressionType.php'); require_once(dirname(__FILE__) . '/LimitProcessor.php'); require_once(dirname(__FILE__) . '/AbstractProcessor.php'); /** * * This class processes the SHOW statements. * * @author arothe * */ class ShowProcessor extends AbstractProcessor { private $limitProcessor; public function __construct() { $this->limitProcessor = new LimitProcessor(); } public function process($tokens) { $resultList = array(); $category = ""; $prev = ""; foreach ($tokens as $k => $token) { $upper = strtoupper(trim($token)); if ($this->isWhitespaceToken($token)) { continue; } switch ($upper) { case 'FROM': $resultList[] = array('expr_type' => ExpressionType::RESERVED, 'base_expr' => trim($token)); if ($prev === 'INDEX' || $prev === 'COLUMNS') { continue; } $category = $upper; break; case 'CREATE': case 'DATABASE': case 'FUNCTION': case 'PROCEDURE': case 'ENGINE': case 'TABLE': case 'FOR': case 'LIKE': case 'INDEX': case 'COLUMNS': case 'PLUGIN': case 'PRIVILEGES': case 'PROCESSLIST': case 'LOGS': case 'STATUS': case 'GLOBAL': case 'SESSION': case 'FULL': case 'GRANTS': case 'INNODB': case 'STORAGE': case 'ENGINES': case 'OPEN': case 'BDB': case 'TRIGGERS': case 'VARIABLES': case 'DATABASES': case 'ERRORS': case 'TABLES': case 'WARNINGS': case 'CHARACTER': case 'SET': case 'COLLATION': $resultList[] = array('expr_type' => ExpressionType::RESERVED, 'base_expr' => trim($token)); $category = $upper; break; default: switch ($prev) { case 'LIKE': $resultList[] = array('expr_type' => ExpressionType::CONSTANT, 'base_expr' => $token); break; case 'LIMIT': $limit = array_pop($resultList); $limit['sub_tree'] = $this->limitProcessor->process(array_slice($tokens, $k)); $resultList[] = $limit; break; case 'FROM': case 'DATABASE': $resultList[] = array('expr_type' => ExpressionType::DATABASE, 'name' => $token, 'no_quotes' => $this->revokeQuotation($token), 'base_expr' => $token); break; case 'FOR': $resultList[] = array('expr_type' => ExpressionType::USER, 'name' => $token, 'no_quotes' => $this->revokeQuotation($token), 'base_expr' => $token); break; case 'INDEX': case 'COLUMNS': case 'TABLE': $resultList[] = array('expr_type' => ExpressionType::TABLE, 'table' => $token, 'no_quotes' => $this->revokeQuotation($token), 'base_expr' => $token); $category = "TABLENAME"; break; case 'FUNCTION': if (PHPSQLParserConstants::isAggregateFunction($upper)) { $expr_type = ExpressionType::AGGREGATE_FUNCTION; } else { $expr_type = ExpressionType::SIMPLE_FUNCTION; } $resultList[] = array('expr_type' => $expr_type, 'name' => $token, 'no_quotes' => $this->revokeQuotation($token), 'base_expr' => $token); break; case 'PROCEDURE': $resultList[] = array('expr_type' => ExpressionType::PROCEDURE, 'name' => $token, 'no_quotes' => $this->revokeQuotation($token), 'base_expr' => $token); break; case 'ENGINE': $resultList[] = array('expr_type' => ExpressionType::ENGINE, 'name' => $token, 'no_quotes' => $this->revokeQuotation($token), 'base_expr' => $token); break; default: // ignore break; } break; } $prev = $category; } return $resultList; } } ?> ================================================ FILE: src/library/processors/TableProcessor.php ================================================ * * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * DAMAGE. */ require_once(dirname(__FILE__) . '/AbstractProcessor.php'); require_once(dirname(__FILE__) . '/CreateDefinitionProcessor.php'); require_once(dirname(__FILE__) . '/../utils/ExpressionType.php'); /** * * This class processes the TABLE statements. * * @author arothe * */ class TableProcessor extends AbstractProcessor { protected function getReservedType($token) { return array('expr_type' => ExpressionType::RESERVED, 'base_expr' => $token); } protected function getConstantType($token) { return array('expr_type' => ExpressionType::CONSTANT, 'base_expr' => $token); } protected function getOperatorType($token) { return array('expr_type' => ExpressionType::OPERATOR, 'base_expr' => $token); } protected function clear(&$expr, &$base_expr, &$category) { $expr = array(); $base_expr = ''; $category = 'CREATE_DEF'; } public function process($tokens) { $currCategory = "TABLE_NAME"; $result = array('base_expr' => false, 'name' => false, 'no_quotes' => false, 'create-def' => false, 'options' => false, 'like' => false, 'select-option' => false); $expr = array(); $base_expr = ''; $skip = 0; foreach ($tokens as $token) { $trim = trim($token); $base_expr .= $token; if ($skip > 0) { $skip--; continue; } if ($skip < 0) { break; } if ($trim === "") { continue; } $upper = strtoupper($trim); switch ($upper) { case ',': # it is possible to separate the table options with comma! if ($prevCategory === 'CREATE_DEF') { $last = array_pop($result['options']); $last['delim'] = ','; $result['options'][] = $last; $base_expr = ""; } continue 2; case 'UNION': if ($prevCategory === 'CREATE_DEF') { $expr[] = $this->getReservedType($trim); $currCategory = 'UNION'; continue 2; } break; case 'LIKE': # like without parenthesis if ($prevCategory === 'TABLE_NAME') { $currCategory = $upper; continue 2; } break; case '=': # the optional operator if ($prevCategory === 'TABLE_OPTION') { $expr[] = $this->getOperatorType($trim); continue 2; # don't change the category } break; case 'CHARACTER': if ($prevCategory === 'CREATE_DEF') { $expr[] = $this->getReservedType($trim); $currCategory = 'TABLE_OPTION'; } if ($prevCategory === 'TABLE_OPTION') { # add it to the previous DEFAULT $expr[] = $this->getReservedType($trim); continue 2; } break; case 'SET': if ($prevCategory === 'TABLE_OPTION') { # add it to a previous CHARACTER $expr[] = $this->getReservedType($trim); $currCategory = 'CHARSET'; continue 2; } break; case 'COLLATE': if ($prevCategory === 'TABLE_OPTION') { # add it to the previous DEFAULT $expr[] = $this->getReservedType($trim); $currCategory = 'COLLATE'; continue 2; } break; case 'DIRECTORY': if ($currCategory === 'INDEX_DIRECTORY' || $currCategory === 'DATA_DIRECTORY') { # after INDEX or DATA $expr[] = $this->getReservedType($trim); continue 2; } break; case 'INDEX': if ($prevCategory === 'CREATE_DEF') { $expr[] = $this->getReservedType($trim); $currCategory = 'INDEX_DIRECTORY'; continue 2; } break; case 'DATA': if ($prevCategory === 'CREATE_DEF') { $expr[] = $this->getReservedType($trim); $currCategory = 'DATA_DIRECTORY'; continue 2; } break; case 'INSERT_METHOD': case 'DELAY_KEY_WRITE': case 'ROW_FORMAT': case 'PASSWORD': case 'MAX_ROWS': case 'MIN_ROWS': case 'PACK_KEYS': case 'CHECKSUM': case 'COMMENT': case 'CONNECTION': case 'AUTO_INCREMENT': case 'AVG_ROW_LENGTH': case 'ENGINE': case 'TYPE': case 'STATS_AUTO_RECALC': case 'STATS_PERSISTENT': case 'KEY_BLOCK_SIZE': if ($prevCategory === 'CREATE_DEF') { $expr[] = $this->getReservedType($trim); $currCategory = $prevCategory = 'TABLE_OPTION'; continue 2; } break; case 'DYNAMIC': case 'FIXED': case 'COMPRESSED': case 'REDUNDANT': case 'COMPACT': case 'NO': case 'FIRST': case 'LAST': case 'DEFAULT': if ($prevCategory === 'CREATE_DEF') { # DEFAULT before CHARACTER SET and COLLATE $expr[] = $this->getReservedType($trim); $currCategory = 'TABLE_OPTION'; } if ($prevCategory === 'TABLE_OPTION') { # all assignments with the keywords $expr[] = $this->getReservedType($trim); $result['options'][] = array('expr_type' => ExpressionType::EXPRESSION, 'base_expr' => trim($base_expr), 'delim' => ' ', 'sub_tree' => $expr); $this->clear($expr, $base_expr, $currCategory); } break; case 'IGNORE': case 'REPLACE': $expr[] = $this->getReservedType($trim); $result['select-option'] = array('base_expr' => trim($base_expr), 'duplicates' => $trim, 'as' => false, 'sub_tree' => $expr); continue 2; case 'AS': $expr[] = $this->getReservedType($trim); if (!isset($result['select-option']['duplicates'])) { $result['select-option']['duplicates'] = false; } $result['select-option']['as'] = true; $result['select-option']['base_expr'] = trim($base_expr); $result['select-option']['sub_tree'] = $expr; continue 2; case 'PARTITION': # TODO: parse partition options $skip = -1; break; default: switch ($currCategory) { case 'CHARSET': # the charset name $expr[] = $this->getConstantType($trim); $result['options'][] = array('expr_type' => ExpressionType::CHARSET, 'base_expr' => trim($base_expr), 'delim' => ' ', 'sub_tree' => $expr); $this->clear($expr, $base_expr, $currCategory); break; case 'COLLATE': # the collate name $expr[] = $this->getConstantType($trim); $result['options'][] = array('expr_type' => ExpressionType::COLLATE, 'base_expr' => trim($base_expr), 'delim' => ' ', 'sub_tree' => $expr); $this->clear($expr, $base_expr, $currCategory); break; case 'DATA_DIRECTORY': # we have the directory name $expr[] = $this->getConstantType($trim); $result['options'][] = array('expr_type' => ExpressionType::DIRECTORY, 'kind' => 'DATA', 'base_expr' => trim($base_expr), 'delim' => ' ', 'sub_tree' => $expr); $this->clear($expr, $base_expr, $prevCategory); continue 3; case 'INDEX_DIRECTORY': # we have the directory name $expr[] = $this->getConstantType($trim); $result['options'][] = array('expr_type' => ExpressionType::DIRECTORY, 'kind' => 'INDEX', 'base_expr' => trim($base_expr), 'delim' => ' ', 'sub_tree' => $expr); $this->clear($expr, $base_expr, $prevCategory); continue 3; case 'TABLE_NAME': $result['base_expr'] = $result['name'] = $trim; $result['no_quotes'] = $this->revokeQuotation($trim); $this->clear($expr, $base_expr, $prevCategory); break; case 'LIKE': $result['like'] = array('expr_type' => ExpressionType::TABLE, 'table' => $trim, 'base_expr' => $trim, 'no_quotes' => $this->revokeQuotation($trim)); $this->clear($expr, $base_expr, $currCategory); break; case '': # after table name if ($prevCategory === 'TABLE_NAME' && $upper[0] === '(' && substr($upper, -1) === ')') { $unparsed = $this->splitSQLIntoTokens($this->removeParenthesisFromStart($trim)); $processor = new CreateDefinitionProcessor(); $coldef = $processor->process($unparsed); $result['create-def'] = array('expr_type' => ExpressionType::BRACKET_EXPRESSION, 'base_expr' => $base_expr, 'sub_tree' => $coldef['create-def']); $expr = array(); $base_expr = ''; $currCategory = 'CREATE_DEF'; } break; case 'UNION': # TODO: this token starts and ends with parenthesis # and contains a list of table names (comma-separated) # split the token and add the list as subtree # we must change the DefaultProcessor $unparsed = $this->splitSQLIntoTokens($this->removeParenthesisFromStart($trim)); $expr[] = array('expr_type' => ExpressionType::BRACKET_EXPRESSION, 'base_expr' => $trim, 'sub_tree' => '***TODO***'); $result['options'][] = array('expr_type' => ExpressionType::UNION, 'base_expr' => trim($base_expr), 'delim' => ' ', 'sub_tree' => $expr); $this->clear($expr, $base_expr, $currCategory); break; default: # strings and numeric constants $expr[] = $this->getConstantType($trim); $result['options'][] = array('expr_type' => ExpressionType::EXPRESSION, 'base_expr' => trim($base_expr), 'delim' => ' ', 'sub_tree' => $expr); $this->clear($expr, $base_expr, $currCategory); break; } break; } $prevCategory = $currCategory; $currCategory = ""; } if ($result['like'] === false) { unset($result['like']); } if ($result['select-option'] === false) { unset($result['select-option']); } return $result; } } ?> ================================================ FILE: src/library/processors/UnionProcessor.php ================================================ * * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * DAMAGE. */ require_once(dirname(__FILE__) . '/AbstractProcessor.php'); require_once(dirname(__FILE__) . '/SQLProcessor.php'); require_once(dirname(__FILE__) . '/DefaultProcessor.php'); require_once(dirname(__FILE__) . '/../utils/ExpressionType.php'); /** * * This class processes the UNION statements. * * @author arothe * */ class UnionProcessor extends AbstractProcessor { public function isUnion($queries) { $unionTypes = array('UNION', 'UNION ALL'); foreach ($unionTypes as $unionType) { if (!empty($queries[$unionType])) { return true; } } return false; } /** * MySQL supports a special form of UNION: * (select ...) * union * (select ...) * * This function handles this query syntax. Only one such subquery * is supported in each UNION block. (select)(select)union(select) is not legal. * The extra queries will be silently ignored. */ protected function processMySQLUnion($queries) { $unionTypes = array('UNION', 'UNION ALL'); foreach ($unionTypes as $unionType) { if (empty($queries[$unionType])) { continue; } foreach ($queries[$unionType] as $key => $tokenList) { foreach ($tokenList as $z => $token) { $token = trim($token); if ($token === "") { continue; } // starts with "(select" if (preg_match("/^\\(\\s*select\\s*/i", $token)) { $processor = new DefaultProcessor(); $queries[$unionType][$key] = $processor->process($this->removeParenthesisFromStart($token)); break; } $processor = new SQLProcessor(); $queries[$unionType][$key] = $processor->process($queries[$unionType][$key]); break; } } } // it can be parsed or not return $queries; } public function process($inputArray) { $outputArray = array(); // ometimes the parser needs to skip ahead until a particular // oken is found $skipUntilToken = false; // his is the last type of union used (UNION or UNION ALL) // ndicates a) presence of at least one union in this query // b) the type of union if this is the first or last query $unionType = false; // ometimes a "query" consists of more than one query (like a UNION query) // his array holds all the queries $queries = array(); foreach ($inputArray as $key => $token) { $trim = trim($token); // overread all tokens till that given token if ($skipUntilToken) { if ($trim === "") { continue; // read the next token } if (strtoupper($trim) === $skipUntilToken) { $skipUntilToken = false; continue; // read the next token } } if (strtoupper($trim) !== "UNION") { $outputArray[] = $token; // here we get empty tokens, if we remove these, we get problems in parse_sql() continue; } $unionType = "UNION"; // we are looking for an ALL token right after UNION for ($i = $key + 1; $i < count($inputArray); ++$i) { if (trim($inputArray[$i]) === "") { continue; } if (strtoupper($inputArray[$i]) !== "ALL") { break; } // the other for-loop should overread till "ALL" $skipUntilToken = "ALL"; $unionType = "UNION ALL"; } // store the tokens related to the unionType $queries[$unionType][] = $outputArray; $outputArray = array(); } // the query tokens after the last UNION or UNION ALL // or we don't have an UNION/UNION ALL if (!empty($outputArray)) { if ($unionType) { $queries[$unionType][] = $outputArray; } else { $queries[] = $outputArray; } } return $this->processMySQLUnion($queries); } } ?> ================================================ FILE: src/library/processors/UpdateProcessor.php ================================================ * * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * DAMAGE. */ require_once(dirname(__FILE__) . '/FromProcessor.php'); /** * * This class processes the UPDATE statements. * * @author arothe * */ class UpdateProcessor extends FromProcessor { } ?> ================================================ FILE: src/library/processors/UsingProcessor.php ================================================ * * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * DAMAGE. */ require_once(dirname(__FILE__) . '/FromProcessor.php'); /** * * This class processes the USING statements. * * @author arothe * */ class UsingProcessor extends FromProcessor { } ?> ================================================ FILE: src/library/processors/ValuesProcessor.php ================================================ * * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * DAMAGE. */ require_once(dirname(__FILE__) . '/../utils/ExpressionType.php'); require_once(dirname(__FILE__) . '/RecordProcessor.php'); require_once(dirname(__FILE__) . '/AbstractProcessor.php'); /** * * This class processes the VALUES statements. * * @author arothe * */ class ValuesProcessor extends AbstractProcessor { private $recordProcessor; public function __construct() { $this->recordProcessor = new RecordProcessor(); } public function process($tokens) { $unparsed = ""; foreach ($tokens['VALUES'] as $k => $v) { if ($this->isWhitespaceToken($v)) { continue; } $unparsed .= $v; } $values = $this->splitSQLIntoTokens($unparsed); $parsed = array(); foreach ($values as $k => $v) { if ($this->isCommaToken($v)) { unset($values[$k]); } else { $processor = new RecordProcessor(); $values[$k] = array('expr_type' => ExpressionType::RECORD, 'base_expr' => $v, 'data' => $this->recordProcessor->process($v)); } } $tokens['VALUES'] = array_values($values); return $tokens; } } ?> ================================================ FILE: src/library/processors/WhereProcessor.php ================================================ * * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * DAMAGE. */ require_once(dirname(__FILE__) . '/ExpressionListProcessor.php'); /** * * This class processes the WHERE statements. * * @author arothe * */ class WhereProcessor extends ExpressionListProcessor { } ?> ================================================ FILE: src/library/utils/ExpressionToken.php ================================================ subTree = false; $this->expression = ""; $this->key = $key; $this->token = $token; $this->tokenType = false; $this->trim = trim($token); $this->upper = strtoupper($this->trim); $this->noQuotes = null; } # TODO: we could replace it with a constructor new ExpressionToken(this, "*") public function addToken($string) { $this->token .= $string; } public function isEnclosedWithinParenthesis() { return ($this->upper[0] === '(' && substr($this->upper, -1) === ')'); } public function setSubTree($tree) { $this->subTree = $tree; } public function getSubTree() { return $this->subTree; } public function getUpper($idx = false) { return $idx !== false ? $this->upper[$idx] : $this->upper; } public function getTrim($idx = false) { return $idx !== false ? $this->trim[$idx] : $this->trim; } public function getToken($idx = false) { return $idx !== false ? $this->token[$idx] : $this->token; } public function setNoQuotes($token, $qchars = '`') { $this->noQuotes = ($token === null) ? null : $this->revokeQuotation($token, $qchars); } public function setTokenType($type) { $this->tokenType = $type; } public function endsWith($needle) { $length = strlen($needle); if ($length == 0) { return true; } $start = $length * -1; return (substr($this->token, $start) === $needle); } public function isWhitespaceToken() { return ($this->trim === ""); } public function isCommaToken() { return ($this->trim === ","); } public function isVariableToken() { return $this->upper[0] === '@'; } public function isSubQueryToken() { return preg_match("/^\\(\\s*SELECT/i", $this->trim); } public function isExpression() { return $this->tokenType === ExpressionType::EXPRESSION; } public function isBracketExpression() { return $this->tokenType === ExpressionType::BRACKET_EXPRESSION; } public function isOperator() { return $this->tokenType === ExpressionType::OPERATOR; } public function isInList() { return $this->tokenType === ExpressionType::IN_LIST; } public function isFunction() { return $this->tokenType === ExpressionType::SIMPLE_FUNCTION; } public function isUnspecified() { return ($this->tokenType === false); } public function isVariable() { return $this->tokenType === ExpressionType::GLOBAL_VARIABLE || $this->tokenType === ExpressionType::LOCAL_VARIABLE || $this->tokenType === ExpressionType::USER_VARIABLE; } public function isAggregateFunction() { return $this->tokenType === ExpressionType::AGGREGATE_FUNCTION; } public function isColumnReference() { return $this->tokenType === ExpressionType::COLREF; } public function isConstant() { return $this->tokenType === ExpressionType::CONSTANT; } public function isSign() { return $this->tokenType === ExpressionType::SIGN; } public function isSubQuery() { return $this->tokenType === ExpressionType::SUBQUERY; } private function revokeQuotation($token, $qchars = '`') { $result = trim($token); for ($i = 0; $i < strlen($qchars); $i++) { $quote = $qchars[$i]; if (($result[0] === $quote) && ($result[strlen($result) - 1] === $quote)) { $result = substr($result, 1, -1); return trim(str_replace($quote.$quote, $quote, $result)); } } return $token; } public function toArray() { $result = array(); $result['expr_type'] = $this->tokenType; $result['base_expr'] = $this->token; if (!empty($this->noQuotes)) { $result['no_quotes'] = $this->noQuotes; } $result['sub_tree'] = $this->subTree; return $result; } } ?> ================================================ FILE: src/library/utils/ExpressionType.php ================================================ * @copyright 2010-2014 Justin Swanhart and André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * @version SVN: $Id: ExpressionType.php 836 2013-12-20 05:31:55Z phosco@gmx.de $ * */ /** * This class defines all values, which are possible for the [expr_type] field * within the parser output. * * @author André Rothe * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * */ class ExpressionType { const USER_VARIABLE = "user_variable"; const SESSION_VARIABLE = "session_variable"; const GLOBAL_VARIABLE = "global_variable"; const LOCAL_VARIABLE = "local_variable"; const COLDEF = "column-def"; const COLREF = "colref"; const RESERVED = "reserved"; const CONSTANT = "const"; const AGGREGATE_FUNCTION = "aggregate_function"; const SIMPLE_FUNCTION = "function"; const EXPRESSION = "expression"; const BRACKET_EXPRESSION = "bracket_expression"; const TABLE_EXPRESSION = "table_expression"; const SUBQUERY = "subquery"; const IN_LIST = "in-list"; const OPERATOR = "operator"; const SIGN = "sign"; const RECORD = "record"; const MATCH_ARGUMENTS = "match-arguments"; const MATCH_MODE = "match-mode"; const ALIAS = "alias"; const POSITION = "pos"; const TEMPORARY_TABLE = "temporary-table"; const TABLE = "table"; const VIEW = "view"; const DATABASE = "database"; const SCHEMA = "schema"; const PROCEDURE = "procedure"; const ENGINE = "engine"; const USER = "user"; const DIRECTORY = "directory"; const UNION = "union"; const CHARSET = "character-set"; const COLLATE = "collation"; const LIKE = "like"; const CONSTRAINT = "constraint"; const PRIMARY_KEY = "primary-key"; const FOREIGN_KEY = "foreign-key"; const UNIQUE_IDX = "unique-index"; const INDEX = "index"; const FULLTEXT_IDX = "fulltext-index"; const SPATIAL_IDX = "spatial-index"; const INDEX_TYPE = "index-type"; const CHECK = "check"; const COLUMN_LIST = "column-list"; const INDEX_COLUMN = "index-column"; const INDEX_SIZE = "index-size"; const INDEX_PARSER = "index-parser"; const REFERENCE = "foreign-ref"; const DATA_TYPE = "data-type"; const COLUMN_TYPE = "column-type"; const DEF_VALUE = "default-value"; } ?> ================================================ FILE: src/library/utils/PHPSQLParserConstants.php ================================================ * * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * DAMAGE. */ class PHPSQLParserConstants { protected static $reserved = array('ABS', 'ACOS', 'ADDDATE', 'ADDTIME', 'AES_ENCRYPT', 'AES_DECRYPT', 'AGAINST', 'ASCII', 'ASIN', 'ATAN', 'AVG', 'BENCHMARK', 'BIN', 'BIT_AND', 'BIT_OR', 'BITCOUNT', 'BITLENGTH', 'CAST', 'CEILING', 'CHAR', 'CHAR_LENGTH', 'CHARACTER_LENGTH', 'CHARSET', 'COALESCE', 'COERCIBILITY', 'COLLATION', 'COMPRESS', 'CONCAT', 'CONCAT_WS', 'CONNECTION_ID', 'CONV', 'CONVERT', 'CONVERT_TZ', 'COS', 'COT', 'COUNT', 'CRC32', 'CURDATE', 'CURRENT_USER', 'CURRVAL', 'CURTIME', 'DATABASE', 'DATETIME', 'DATE_ADD', 'DATE_DIFF', 'DATE_FORMAT', 'DATE_SUB', 'DAY', 'DAYNAME', 'DAYOFMONTH', 'DAYOFWEEK', 'DAYOFYEAR', 'DECODE', 'DEFAULT', 'DEGREES', 'DES_DECRYPT', 'DES_ENCRYPT', 'ELT', 'ENCODE', 'ENCRYPT', 'EXISTS', 'EXP', 'EXPORT_SET', 'EXTRACT', 'FIELD', 'FIND_IN_SET', 'FLOOR', 'FORMAT', 'FOUND_ROWS', 'FROM_DAYS', 'FROM_UNIXTIME', 'GET_FORMAT', 'GET_LOCK', 'GROUP_CONCAT', 'GREATEST', 'HEX', 'HOUR', 'IF', 'IFNULL', 'IN', 'INET_ATON', 'INET_NTOA', 'INSERT', 'INSTR', 'INTERVAL', 'IS_FREE_LOCK', 'IS_USED_LOCK', 'LAST_DAY', 'LAST_INSERT_ID', 'LCASE', 'LEAST', 'LEFT', 'LENGTH', 'LN', 'LOAD_FILE', 'LOCALTIME', 'LOCALTIMESTAMP', 'LOCATE', 'LOG', 'LOG2', 'LOG10', 'LOWER', 'LPAD', 'LTRIM', 'MAKE_SET', 'MAKEDATE', 'MAKETIME', 'MASTER_POS_WAIT', 'MATCH', 'MAX', 'MD5', 'MICROSECOND', 'MID', 'MIN', 'MINUTE', 'MOD', 'MONTH', 'MONTHNAME', 'NEXTVAL', 'NOW', 'NULLIF', 'OCT', 'OCTET_LENGTH', 'OLD_PASSWORD', 'ORD', 'PASSWORD', 'PERIOD_ADD', 'PERIOD_DIFF', 'PI', 'POSITION', 'POW', 'POWER', 'QUARTER', 'QUOTE', 'RADIANS', 'RAND', 'RELEASE_LOCK', 'REPEAT', 'REPLACE', 'REVERSE', 'RIGHT', 'ROUND', 'ROW_COUNT', 'RPAD', 'RTRIM', 'SEC_TO_TIME', 'SECOND', 'SESSION_USER', 'SHA', 'SHA1', 'SIGN', 'SOUNDEX', 'SPACE', 'SQRT', 'STD', 'STDDEV', 'STDDEV_POP', 'STDDEV_SAMP', 'STRCMP', 'STR_TO_DATE', 'SUBDATE', 'SUBSTRING', 'SUBSTRING_INDEX', 'SUBTIME', 'SUM', 'SYSDATE', 'SYSTEM_USER', 'TAN', 'TIME', 'TIMEDIFF', 'TIMESTAMP', 'TIMESTAMPADD', 'TIMESTAMPDIFF', 'TIME_FORMAT', 'TIME_TO_SEC', 'TO_DAYS', 'TRIM', 'TRUNCATE', 'UCASE', 'UNCOMPRESS', 'UNCOMPRESSED_LENGTH', 'UNHEX', 'UNIX_TIMESTAMP', 'UPPER', 'USER', 'UTC_DATE', 'UTC_TIME', 'UTC_TIMESTAMP', 'UUID', 'VAR_POP', 'VAR_SAMP', 'VARIANCE', 'VERSION', 'WEEK', 'WEEKDAY', 'WEEKOFYEAR', 'YEAR', 'YEARWEEK', 'ADD', 'ALL', 'ALTER', 'ANALYZE', 'AND', 'AS', 'ASC', 'ASENSITIVE', 'AUTO_INCREMENT', 'BDB', 'BEFORE', 'BERKELEYDB', 'BETWEEN', 'BIGINT', 'BINARY', 'BLOB', 'BOTH', 'BY', 'CALL', 'CASCADE', 'CASE', 'CHANGE', 'CHAR', 'CHARACTER', 'CHECK', 'COLLATE', 'COLUMN', 'COLUMNS', 'CONDITION', 'CONNECTION', 'CONSTRAINT', 'CONTINUE', 'CREATE', 'CROSS', 'CURRENT_DATE', 'CURRENT_TIME', 'CURRENT_TIMESTAMP', 'CURSOR', 'DATABASE', 'DATABASES', 'DAY_HOUR', 'DAY_MICROSECOND', 'DAY_MINUTE', 'DAY_SECOND', 'DEC', 'DECIMAL', 'DECLARE', 'DEFAULT', 'DELAYED', 'DELETE', 'DESC', 'DESCRIBE', 'DETERMINISTIC', 'DISTINCT', 'DISTINCTROW', 'DIV', 'DOUBLE', 'DROP', 'ELSE', 'ELSEIF', 'END', 'ENCLOSED', 'ESCAPED', 'EXISTS', 'EXIT', 'EXPLAIN', 'FALSE', 'FETCH', 'FIELDS', 'FLOAT', 'FOR', 'FORCE', 'FOREIGN', 'FOUND', 'FRAC_SECOND', 'FROM', 'FULLTEXT', 'GRANT', 'GROUP', 'HAVING', 'HIGH_PRIORITY', 'HOUR_MICROSECOND', 'HOUR_MINUTE', 'HOUR_SECOND', 'IF', 'IGNORE', 'IN', 'INDEX', 'INFILE', 'INNER', 'INNODB', 'INOUT', 'INSENSITIVE', 'INSERT', 'INT', 'INTEGER', 'INTERVAL', 'INTO', 'IO_THREAD', 'IS', 'ITERATE', 'JOIN', 'KEY', 'KEYS', 'KILL', 'LEADING', 'LEAVE', 'LEFT', 'LIKE', 'LIMIT', 'LINES', 'LOAD', 'LOCALTIME', 'LOCALTIMESTAMP', 'LOCK', 'LONG', 'LONGBLOB', 'LONGTEXT', 'LOOP', 'LOW_PRIORITY', 'MASTER_SERVER_ID', 'MATCH', 'MEDIUMBLOB', 'MEDIUMINT', 'MEDIUMTEXT', 'MIDDLEINT', 'MINUTE_MICROSECOND', 'MINUTE_SECOND', 'MOD', 'NATURAL', 'NOT', 'NO_WRITE_TO_BINLOG', 'NULL', 'NUMERIC', 'ON', 'OPTIMIZE', 'OPTION', 'OPTIONALLY', 'OR', 'ORDER', 'OUT', 'OUTER', 'OUTFILE', 'PRECISION', 'PRIMARY', 'PRIVILEGES', 'PROCEDURE', 'PURGE', 'READ', 'REAL', 'REFERENCES', 'REGEXP', 'RENAME', 'REPEAT', 'REPLACE', 'REQUIRE', 'RESTRICT', 'RETURN', 'REVOKE', 'RIGHT', 'RLIKE', 'SECOND_MICROSECOND', 'SELECT', 'SENSITIVE', 'SEPARATOR', 'SET', 'SHOW', 'SMALLINT', 'SOME', 'SONAME', 'SPATIAL', 'SPECIFIC', 'SQL', 'SQLEXCEPTION', 'SQLSTATE', 'SQLWARNING', 'SQL_BIG_RESULT', 'SQL_CALC_FOUND_ROWS', 'SQL_SMALL_RESULT', 'SQL_TSI_DAY', 'SQL_TSI_FRAC_SECOND', 'SQL_TSI_HOUR', 'SQL_TSI_MINUTE', 'SQL_TSI_MONTH', 'SQL_TSI_QUARTER', 'SQL_TSI_SECOND', 'SQL_TSI_WEEK', 'SQL_TSI_YEAR', 'SSL', 'STARTING', 'STRAIGHT_JOIN', 'STRIPED', 'TABLE', 'TABLES', 'TEMPORARY', 'TERMINATED', 'THEN', 'TIMESTAMPADD', 'TIMESTAMPDIFF', 'TINYBLOB', 'TINYINT', 'TINYTEXT', 'TO', 'TRAILING', 'TRUE', 'UNDO', 'UNION', 'UNIQUE', 'UNLOCK', 'UNSIGNED', 'UPDATE', 'USAGE', 'USE', 'USER_RESOURCES', 'USING', 'UTC_DATE', 'UTC_TIME', 'UTC_TIMESTAMP', 'VALUES', 'VARBINARY', 'VARCHAR', 'VARCHARACTER', 'VARYING', 'WHEN', 'WHERE', 'WHILE', 'WITH', 'WRITE', 'XOR', 'YEAR_MONTH', 'ZEROFILL'); protected static $parameterizedFunctions = array('ABS', 'ACOS', 'ADDDATE', 'ADDTIME', 'AES_ENCRYPT', 'AES_DECRYPT', 'AGAINST', 'ASCII', 'ASIN', 'ATAN', 'AVG', 'BENCHMARK', 'BIN', 'BIT_AND', 'BIT_OR', 'BITCOUNT', 'BITLENGTH', 'CAST', 'CEILING', 'CHAR', 'CHAR_LENGTH', 'CHARACTER_LENGTH', 'CHARSET', 'COALESCE', 'COERCIBILITY', 'COLLATION', 'COMPRESS', 'CONCAT', 'CONCAT_WS', 'CONV', 'CONVERT', 'CONVERT_TZ', 'COS', 'COT', 'COUNT', 'CRC32', 'CURRVAL', 'DATE_ADD', 'DATE_DIFF', 'DATE_FORMAT', 'DATE_SUB', 'DAY', 'DAYNAME', 'DAYOFMONTH', 'DAYOFWEEK', 'DAYOFYEAR', 'DECODE', 'DEFAULT', 'DEGREES', 'DES_DECRYPT', 'DES_ENCRYPT', 'ELT', 'ENCODE', 'ENCRYPT', 'EXP', 'EXPORT_SET', 'EXTRACT', 'FIELD', 'FIND_IN_SET', 'FLOOR', 'FORMAT', 'FROM_DAYS', 'FROM_UNIXTIME', 'GET_FORMAT', 'GET_LOCK', 'GROUP_CONCAT', 'GREATEST', 'HEX', 'HOUR', 'IF', 'IFNULL', 'IN', 'INET_ATON', 'INET_NTOA', 'INSERT', 'INSTR', 'INTERVAL', 'IS_FREE_LOCK', 'IS_USED_LOCK', 'LAST_DAY', 'LCASE', 'LEAST', 'LEFT', 'LENGTH', 'LN', 'LOAD_FILE', 'LOCATE', 'LOG', 'LOG2', 'LOG10', 'LOWER', 'LPAD', 'LTRIM', 'MAKE_SET', 'MAKEDATE', 'MAKETIME', 'MASTER_POS_WAIT', 'MATCH', 'MAX', 'MD5', 'MICROSECOND', 'MID', 'MIN', 'MINUTE', 'MOD', 'MONTH', 'MONTHNAME', 'NEXTVAL', 'NULLIF', 'OCT', 'OCTET_LENGTH', 'OLD_PASSWORD', 'ORD', 'PASSWORD', 'PERIOD_ADD', 'PERIOD_DIFF', 'PI', 'POSITION', 'POW', 'POWER', 'QUARTER', 'QUOTE', 'RADIANS', 'RELEASE_LOCK', 'REPEAT', 'REPLACE', 'REVERSE', 'RIGHT', 'ROUND', 'RPAD', 'RTRIM', 'SEC_TO_TIME', 'SECOND', 'SHA', 'SHA1', 'SIGN', 'SOUNDEX', 'SPACE', 'SQRT', 'STD', 'STDDEV', 'STDDEV_POP', 'STDDEV_SAMP', 'STRCMP', 'STR_TO_DATE', 'SUBDATE', 'SUBSTRING', 'SUBSTRING_INDEX', 'SUBTIME', 'SUM', 'TAN', 'TIME', 'TIMEDIFF', 'TIMESTAMP', 'TIMESTAMPADD', 'TIMESTAMPDIFF', 'TIME_FORMAT', 'TIME_TO_SEC', 'TO_DAYS', 'TRIM', 'TRUNCATE', 'UCASE', 'UNCOMPRESS', 'UNCOMPRESSED_LENGTH', 'UNHEX', 'UPPER', 'VAR_POP', 'VAR_SAMP', 'VARIANCE', 'WEEK', 'WEEKDAY', 'WEEKOFYEAR', 'YEAR', 'YEARWEEK'); protected static $functions = array('ABS', 'ACOS', 'ADDDATE', 'ADDTIME', 'AES_ENCRYPT', 'AES_DECRYPT', 'AGAINST', 'ASCII', 'ASIN', 'ATAN', 'AVG', 'BENCHMARK', 'BIN', 'BIT_AND', 'BIT_OR', 'BITCOUNT', 'BITLENGTH', 'CAST', 'CEILING', 'CHAR', 'CHAR_LENGTH', 'CHARACTER_LENGTH', 'CHARSET', 'COALESCE', 'COERCIBILITY', 'COLLATION', 'COMPRESS', 'CONCAT', 'CONCAT_WS', 'CONNECTION_ID', 'CONV', 'CONVERT', 'CONVERT_TZ', 'COS', 'COT', 'COUNT', 'CRC32', 'CURDATE', 'CURRENT_USER', 'CURRVAL', 'CURTIME', 'DATABASE', 'DATE_ADD', 'DATE_DIFF', 'DATE_FORMAT', 'DATE_SUB', 'DAY', 'DAYNAME', 'DAYOFMONTH', 'DAYOFWEEK', 'DAYOFYEAR', 'DECODE', 'DEFAULT', 'DEGREES', 'DES_DECRYPT', 'DES_ENCRYPT', 'ELT', 'ENCODE', 'ENCRYPT', 'EXP', 'EXPORT_SET', 'EXTRACT', 'FIELD', 'FIND_IN_SET', 'FLOOR', 'FORMAT', 'FOUND_ROWS', 'FROM_DAYS', 'FROM_UNIXTIME', 'GET_FORMAT', 'GET_LOCK', 'GROUP_CONCAT', 'GREATEST', 'HEX', 'HOUR', 'IF', 'IFNULL', 'IN', 'INET_ATON', 'INET_NTOA', 'INSERT', 'INSTR', 'INTERVAL', 'IS_FREE_LOCK', 'IS_USED_LOCK', 'LAST_DAY', 'LAST_INSERT_ID', 'LCASE', 'LEAST', 'LEFT', 'LENGTH', 'LN', 'LOAD_FILE', 'LOCALTIME', 'LOCALTIMESTAMP', 'LOCATE', 'LOG', 'LOG2', 'LOG10', 'LOWER', 'LPAD', 'LTRIM', 'MAKE_SET', 'MAKEDATE', 'MAKETIME', 'MASTER_POS_WAIT', 'MATCH', 'MAX', 'MD5', 'MICROSECOND', 'MID', 'MIN', 'MINUTE', 'MOD', 'MONTH', 'MONTHNAME', 'NEXTVAL', 'NOW', 'NULLIF', 'OCT', 'OCTET_LENGTH', 'OLD_PASSWORD', 'ORD', 'PASSWORD', 'PERIOD_ADD', 'PERIOD_DIFF', 'PI', 'POSITION', 'POW', 'POWER', 'QUARTER', 'QUOTE', 'RADIANS', 'RAND', 'RELEASE_LOCK', 'REPEAT', 'REPLACE', 'REVERSE', 'RIGHT', 'ROUND', 'ROW_COUNT', 'RPAD', 'RTRIM', 'SEC_TO_TIME', 'SECOND', 'SESSION_USER', 'SHA', 'SHA1', 'SIGN', 'SOUNDEX', 'SPACE', 'SQRT', 'STD', 'STDDEV', 'STDDEV_POP', 'STDDEV_SAMP', 'STRCMP', 'STR_TO_DATE', 'SUBDATE', 'SUBSTRING', 'SUBSTRING_INDEX', 'SUBTIME', 'SUM', 'SYSDATE', 'SYSTEM_USER', 'TAN', 'TIME', 'TIMEDIFF', 'TIMESTAMP', 'TIMESTAMPADD', 'TIMESTAMPDIFF', 'TIME_FORMAT', 'TIME_TO_SEC', 'TO_DAYS', 'TRIM', 'TRUNCATE', 'UCASE', 'UNCOMPRESS', 'UNCOMPRESSED_LENGTH', 'UNHEX', 'UNIX_TIMESTAMP', 'UPPER', 'USER', 'UTC_DATE', 'UTC_TIME', 'UTC_TIMESTAMP', 'UUID', 'VAR_POP', 'VAR_SAMP', 'VARIANCE', 'VERSION', 'WEEK', 'WEEKDAY', 'WEEKOFYEAR', 'YEAR', 'YEARWEEK'); protected static $aggregateFunctions = array('AVG', 'SUM', 'COUNT', 'MIN', 'MAX', 'STDDEV', 'STDDEV_SAMP', 'STDDEV_POP', 'VARIANCE', 'VAR_SAMP', 'VAR_POP', 'GROUP_CONCAT', 'BIT_AND', 'BIT_OR', 'BIT_XOR'); public static function isAggregateFunction($token) { return in_array($token, PHPSQLParserConstants::$aggregateFunctions); } public static function isReserved($token) { return in_array($token, PHPSQLParserConstants::$reserved); } public static function isFunction($token) { return in_array($token, PHPSQLParserConstants::$functions); } public static function isParameterizedFunction($token) { return in_array($token, PHPSQLParserConstants::$parameterizedFunctions); } } ?> ================================================ FILE: src/library/utils/PHPSQLParserUtils.php ================================================ * * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * DAMAGE. */ /** * This class implements some helper functions. * * @author arothe * @deprecated */ class PHPSQLParserUtils { /** * Prints an array only if debug mode is on. * * @param array $s * @param boolean $return, if true, the formatted array is returned via return parameter */ protected function preprint($arr, $return = false) { $x = "
";
        $x .= print_r($arr, 1);
        $x .= "
"; if ($return) { return $x; } else { if (isset($_ENV['DEBUG'])) { print $x . "\n"; } } } /** * Ends the given string $haystack with the string $needle? * * @param string $haystack * @param string $needle */ protected function endsWith($haystack, $needle) { $length = strlen($needle); if ($length == 0) { return true; } return (substr($haystack, -$length) === $needle); } /** * Revokes the quoting characters from an expression */ protected function revokeQuotation($sql) { $result = trim($sql); if (($result[0] === '`') && ($result[strlen($result) - 1] === '`')) { $result = substr($result, 1, -1); return trim(str_replace('``', '`', $result)); } return $sql; } /** * This method removes parenthesis from start of the given string. * It removes also the associated closing parenthesis. */ protected function removeParenthesisFromStart($token) { $parenthesisRemoved = 0; $trim = trim($token); if ($trim !== "" && $trim[0] === "(") { // remove only one parenthesis pair now! $parenthesisRemoved++; $trim[0] = " "; $trim = trim($trim); } $parenthesis = $parenthesisRemoved; $i = 0; $string = 0; while ($i < strlen($trim)) { if ($trim[$i] === "\\") { $i += 2; # an escape character, the next character is irrelevant continue; } if ($trim[$i] === "'" || $trim[$i] === '"') { $string++; } if (($string % 2 === 0) && ($trim[$i] === "(")) { $parenthesis++; } if (($string % 2 === 0) && ($trim[$i] === ")")) { if ($parenthesis == $parenthesisRemoved) { $trim[$i] = " "; $parenthesisRemoved--; } $parenthesis--; } $i++; } return trim($trim); } public function getLastOf($array) { // $array is a copy of the original array, so we can change it without sideeffects if (!is_array($array)) { return false; } return array_pop($array); } /** * translates an array of objects into an associative array */ public function toArray($tokenList) { $expr = array(); foreach ($tokenList as $token) { $expr[] = $token->toArray(); } return (empty($expr) ? false : $expr); } } ?>