2017-10-13

This commit is contained in:
Visman 2017-10-13 13:53:43 +07:00
parent 9becae3750
commit e3abb67d67
3 changed files with 60 additions and 67 deletions

View file

@ -69,7 +69,7 @@ class DB extends PDO
self::ATTR_DEFAULT_FETCH_MODE => self::FETCH_ASSOC,
self::ATTR_EMULATE_PREPARES => false,
self::ATTR_ERRMODE => self::ERRMODE_EXCEPTION,
self::ATTR_STATEMENT_CLASS => array(DBStatement::class, [$this]),
self::ATTR_STATEMENT_CLASS => [DBStatement::class, [$this]],
];
parent::__construct($dsn, $username, $password, $options);
@ -114,43 +114,28 @@ class DB extends PDO
/**
* Метод приводит запрос с типизированными плейсхолдерами к понятному для PDO виду
*
* @param string $query
* @param string &$query
* @param array $params
*
* @throws PDOException
*
* @return array
*/
protected function parse($query, array $params)
protected function parse(&$query, array $params)
{
$idxIn = 0;
$idxOut = 1;
$map = [];
$query = preg_replace_callback(
'%(?=[?:])(?<![\w?])(\?(?![:?])(\w+)?)?(?:(::?)(\w+))?%i',
'%(?=[?:])(?<![\w?:])(?:::(\w+)|\?(?![?:])(?:(\w+)(?::(\w+))?)?|:(\w+))%',
function($matches) use ($params, &$idxIn, &$idxOut, &$map) {
if (isset($matches[3]) && $matches[3] === '::') {
return $this->dbPrefix . $matches[4];
}
$type = $matches[2] ?: 's';
if (isset($matches[4])) {
$key1 = ':' . $matches[4];
$key2 = $matches[4];
} else {
$key1 = $idxIn;
$key2 = $idxIn;
++$idxIn;
if (! empty($matches[1])) {
return $this->dbPrefix . $matches[1];
}
if (isset($params[$key1]) || array_key_exists($key1, $params)) {
$value = $params[$key1];
} elseif (isset($params[$key2]) || array_key_exists($key2, $params)) {
$value = $params[$key2];
} else {
throw new PDOException("'$key1': No parameter for (?$type) placeholder");
}
$type = empty($matches[2]) ? 's' : $matches[2];
$key = isset($matches[4]) ? $matches[4] : (isset($matches[3]) ? $matches[3] : $idxIn++);
$value = $this->getValue($key, $params);
switch ($type) {
case 'p':
@ -160,50 +145,62 @@ class DB extends PDO
case 'a':
break;
case 'i':
$value = [$value];
break;
case 'b':
$value = [$value];
break;
case 's':
$value = [1];
break;
default:
$value = [$value];
$value = [1];
$type = 's';
break;
}
if (! is_array($value)) {
throw new PDOException("Expected array: key='{$key}', type='{$type}'");
}
if (! isset($map[$key])) {
$map[$key] = [$type];
}
$res = [];
foreach ($value as $val) {
$name = ':' . $idxOut;
++$idxOut;
$name = ':' . $idxOut++;
$res[] = $name;
if (empty($map[$key2])) {
$map[$key2] = [$type, $name];
} else {
$map[$key2][] = $name;
}
$map[$key][] = $name;
}
return implode(',', $res);
},
$query
);
//var_dump($query);
//var_dump($map);
return [$query, $map];
return $map;
}
/**
* Метод связывает параметры запроса с соответвтующими значениями
* Метод возвращает значение из массива параметров по ключу или исключение
*
* @param mixed $key
* @param array $params
*
* @throws PDOException
*
* @param PDOStatement $stmt
* @param array $bind
* @return mixed
*/
protected function bind(PDOStatement $stmt, array $bind)
public function getValue($key, array $params)
{
foreach ($bind as $key => $val) {
$stmt->bindValue($key, $val[0], $val[1]);
if (
is_string($key)
&& (isset($params[':' . $key]) || array_key_exists(':' . $key, $params))
) {
return $params[':' . $key];
} elseif (
(is_string($key) || is_int($key))
&& (isset($params[$key]) || array_key_exists($key, $params))
) {
return $params[$key];
}
throw new PDOException("The '{$key}' key is not found in the parameters");
}
/**
@ -249,7 +246,7 @@ class DB extends PDO
*/
public function exec($query, array $params = [])
{
list($query, $map) = $this->parse($query, $params);
$map = $this->parse($query, $params);
if (empty($params)) {
$start = microtime(true);
@ -293,7 +290,8 @@ class DB extends PDO
$options = [];
}
list($query, $map) = $this->parse($query, $params);
$map = $this->parse($query, $params);
$start = microtime(true);
$stmt = parent::prepare($query, $options);
$this->delta = microtime(true) - $start;
@ -321,7 +319,7 @@ class DB extends PDO
$params = [];
}
list($query, $map) = $this->parse($query, $params);
$map = $this->parse($query, $params);
if (empty($params)) {
$start = microtime(true);

View file

@ -64,21 +64,16 @@ class DBStatement extends PDOStatement
public function bindValueList(array $params)
{
foreach ($this->map as $key => $data) {
if (isset($params[$key])) {
$bValue = $params[$key];
} elseif (isset($params[':' . $key])) {
$bValue = $params[':' . $key];
} else {
throw new PDOException("The value for :{$key} placeholder isn't found");
}
$type = array_shift($data);
$bType = $this->types[$type];
$bValue = $this->db->getValue($key, $params);
if ($type{0} === 'a') {
if (! is_array($bValue)) {
throw new PDOException("Expected array: key='{$key}'");
}
foreach ($data as $bParam) {
$bVal = array_shift($bValue); //????
parent::bindValue($bParam, $bVal, $bType); //????
parent::bindValue($bParam, array_shift($bValue), $bType); //????
}
} else {
foreach ($data as $bParam) {

View file

@ -524,16 +524,16 @@ class Topic extends Page
}
if ($flag) {
if (empty($topic['mt_last_read']) && empty($topic['mt_last_visit'])) {
$this->c->DB->exec('INSERT INTO ::mark_of_topic (uid, tid, mt_last_visit, mt_last_read)
SELECT ?i:uid, ?i:tid, ?i:visit, ?i:read
FROM ::groups
WHERE NOT EXISTS (SELECT 1
FROM ::mark_of_topic
WHERE uid=?i:uid AND tid=?i:tid)
$this->c->DB->exec('INSERT INTO ::mark_of_topic (uid, tid, mt_last_visit, mt_last_read)
SELECT ?i:uid, ?i:tid, ?i:visit, ?i:read
FROM ::groups
WHERE NOT EXISTS (SELECT 1
FROM ::mark_of_topic
WHERE uid=?i:uid AND tid=?i:tid)
LIMIT 1', $vars);
} else {
$this->c->DB->exec('UPDATE ::mark_of_topic
SET mt_last_visit=?i:visit, mt_last_read=?i:read
$this->c->DB->exec('UPDATE ::mark_of_topic
SET mt_last_visit=?i:visit, mt_last_read=?i:read
WHERE uid=?i:uid AND tid=?i:tid', $vars);
}
}