Query/classes/query_parser.php

140 lines
3.2 KiB
PHP
Raw Normal View History

2012-08-02 11:59:11 -04:00
<?php
/**
* Query
*
* Free Query Builder / Database Abstraction Layer
*
* @package Query
* @author Timothy J. Warren
2014-01-02 12:36:50 -05:00
* @copyright Copyright (c) 2012 - 2014
2012-08-02 11:59:11 -04:00
* @link https://github.com/aviat4ion/Query
* @license http://philsturgeon.co.uk/code/dbad-license
*/
// --------------------------------------------------------------------------
2014-04-02 17:08:50 -04:00
namespace Query;
2012-08-02 11:59:11 -04:00
/**
* Utility Class to parse sql clauses for properly escaping identifiers
*
* @package Query
2014-03-31 16:01:58 -04:00
* @subpackage Query_Builder
2012-08-02 11:59:11 -04:00
*/
class Query_Parser {
2014-04-02 17:08:50 -04:00
/**
* DB Driver
*
* @var \Query\Driver\Driver_Interface
*/
private $db;
2012-08-02 11:59:11 -04:00
/**
* Regex patterns for various syntax components
*
* @var array
*/
private $match_patterns = array(
2012-08-09 12:15:36 -04:00
'function' => '([a-zA-Z0-9_]+\((.*?)\))',
'identifier' => '([a-zA-Z0-9_-]+\.?)+',
'operator' => '=|AND|&&?|~|\|\|?|\^|/|>=?|<=?|-|%|OR|\+|NOT|\!=?|<>|XOR'
2012-08-02 11:59:11 -04:00
);
/**
* Regex matches
*
* @var array
*/
public $matches = array(
'functions' => array(),
'identifiers' => array(),
'operators' => array(),
2012-08-09 12:15:36 -04:00
'combined' => array(),
2012-08-02 11:59:11 -04:00
);
/**
* Constructor/entry point into parser
*
* @param string $sql
2012-08-02 11:59:11 -04:00
*/
public function __construct($sql = '')
{
2014-04-02 17:08:50 -04:00
if (is_object($sql))
{
$this->db = $sql;
$sql = '';
}
2012-08-09 12:15:36 -04:00
// Get sql clause components
preg_match_all('`'.$this->match_patterns['function'].'`', $sql, $this->matches['functions'], PREG_SET_ORDER);
preg_match_all('`'.$this->match_patterns['identifier'].'`', $sql, $this->matches['identifiers'], PREG_SET_ORDER);
preg_match_all('`'.$this->match_patterns['operator'].'`', $sql, $this->matches['operators'], PREG_SET_ORDER);
// Get everything at once for ordering
$full_pattern = '`'.$this->match_patterns['function'].'+|'.$this->match_patterns['identifier'].'|('.$this->match_patterns['operator'].')+`i';
preg_match_all($full_pattern, $sql, $this->matches['combined'], PREG_SET_ORDER);
// Go through the matches, and get the most relevant matches
$this->matches = array_map(array($this, 'filter_array'), $this->matches);
}
// --------------------------------------------------------------------------
/**
* Public parser method for seting the parse string
*
* @param string $sql
2012-08-09 12:15:36 -04:00
*/
2014-04-02 17:08:50 -04:00
protected function parse_join($sql)
2012-08-09 12:15:36 -04:00
{
$this->__construct($sql);
return $this->matches;
}
// --------------------------------------------------------------------------
2014-04-02 17:08:50 -04:00
/**
* Compiles a join condition after parsing
*
* @param string $condition
* @return string
*/
public function compile_join($condition)
{
$parts = $this->parse_join($condition);
$count = count($parts['identifiers']);
// Go through and quote the identifiers
for($i=0; $i <= $count; $i++)
{
if (in_array($parts['combined'][$i], $parts['identifiers']) && ! is_numeric($parts['combined'][$i]))
{
$parts['combined'][$i] = $this->db->quote_ident($parts['combined'][$i]);
}
}
return implode('', $parts['combined']);
}
2012-08-09 12:15:36 -04:00
/**
* Returns a more useful match array
*
* @param array $array
2012-08-09 12:15:36 -04:00
* @return array
*/
2014-04-02 17:08:50 -04:00
protected function filter_array($array)
2012-08-09 12:15:36 -04:00
{
$new_array = array();
foreach($array as $row)
{
2014-02-11 14:29:41 -05:00
$new_array[] = (is_array($row)) ? $row[0] : $row;
2012-08-09 12:15:36 -04:00
}
return $new_array;
2012-08-02 11:59:11 -04:00
}
}
2014-02-11 14:29:41 -05:00
// End of query_parser.php