Commit f3a8e6c6 by Scott

Add support for IN statements

Co-authored-by: pupi1985 <pupi1985@bitbucket.org>
parent b8d37584
......@@ -21,6 +21,8 @@ namespace Q2A\Database;
use PDO;
use PDOException;
use PDOStatement;
use Q2A\Database\DbResult;
use Q2A\Database\Exceptions\SelectSpecException;
class DbConnection
{
......@@ -165,6 +167,11 @@ class DbConnection
public function query($query, $params = array())
{
$query = $this->applyTableSub($query);
// handle old-style placeholders
$query = str_replace(['#', '$'], '?', $query);
// handle IN queries
$query = $this->applyArraySub($query, $params);
$params = $this->flattenArray($params);
try {
if (QA_DEBUG_PERFORMANCE) {
......@@ -199,7 +206,7 @@ class DbConnection
// PDO quotes parameters by default, which breaks LIMIT clauses, so we bind parameters manually
foreach (array_values($params) as $i => $param) {
$dataType = filter_var($param, FILTER_VALIDATE_INT) !== false ? PDO::PARAM_INT : PDO::PARAM_STR;
$stmt->bindParam($i + 1, $param, $dataType);
$stmt->bindValue($i + 1, $param, $dataType);
}
for ($attempt = 0; $attempt < 100; $attempt++) {
......@@ -490,6 +497,47 @@ class DbConnection
}
/**
* Substitute single '?' in a SQL query with multiple '?' for array parameters.
* @param string $query
* @param array $params
* @return string
* @throws SelectSpecException
*/
public function applyArraySub($query, $params)
{
$result = '';
$hasArray = false;
$paramIndexCount = array();
foreach ($params as $param) {
if (is_array($param)) {
$paramIndexCount[] = count($param);
$hasArray = true;
} else {
$paramIndexCount[] = 1;
}
}
if ($hasArray) {
$explodedQuery = explode('?', $query);
if (count($explodedQuery) != count($paramIndexCount) + 1) {
throw new SelectSpecException('The number of parameters and placeholders do not match');
}
foreach ($explodedQuery as $index => $explodedQueryPart) {
$result .= $explodedQueryPart;
if (isset($paramIndexCount[$index])) {
$result .= $paramIndexCount[$index] == 1
? '?'
: str_repeat('?,', $paramIndexCount[$index] - 1) . '?';
}
}
return $result;
}
return $query;
}
/**
* Return the full name (with prefix) of a database table identifier.
* @param string $rawName
* @return string
......@@ -545,4 +593,23 @@ class DbConnection
{
return $this->updateCountsSuspended <= 0;
}
/**
* Flatten a two-level array into a one-level array.
* @param mixed $elements Input elements which can be one-level deep arrays
* @return array
*/
private function flattenArray($elements)
{
$result = array();
foreach ($elements as $element) {
if (is_array($element)) {
$result = array_merge($result, $element);
} else {
$result[] = $element;
}
}
return $result;
}
}
<?php
/*
Question2Answer by Gideon Greenspan and contributors
http://www.question2answer.org/
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
More about this license: http://www.question2answer.org/license.php
*/
namespace Q2A\Database\Exceptions;
use Q2A\Exceptions\FatalErrorException;
class SelectSpecException extends FatalErrorException
{
/**
* @param string $message
*/
public function __construct($message = 'There was an error with the selectspec array')
{
parent::__construct($message);
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment