You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

168 lines
5.0 KiB

<?php
// (c) Copyright by authors of the Tiki Wiki CMS Groupware Project
//
// All Rights Reserved. See copyright.txt for details and a complete list of authors.
// Licensed under the GNU LESSER GENERAL PUBLIC LICENSE. See license.txt for details.
// $Id$
/**
* Class TikiDb_Pdo_Result
*
* Returns result set along with affected rows
*/
class TikiDb_Pdo_Result
{
/** @var array */
public $result;
/** @var int */
public $numrows;
/**
* TikiDb_Pdo_Result constructor.
* @param $result
* @param $rowCount
*/
public function __construct($result, $rowCount)
{
$this->result = &$result;
$this->numrows = is_numeric($rowCount) ? $rowCount : count($this->result);
}
/** @return array */
public function fetchRow()
{
return is_array($this->result) ? array_shift($this->result) : 0;
}
/** @return int */
public function numRows()
{
return (int) $this->numrows;
}
}
class TikiDb_Pdo extends TikiDb
{
/** @var $db PDO */
private $db;
/** @var $rowCount int*/
private $rowCount;
/**
* TikiDb_Pdo constructor.
* @param PDO $db
*/
public function __construct($db)
{
if (! $db) {
die("Invalid db object passed to TikiDB constructor");
}
$this->db = $db;
$this->setServerType($db->getAttribute(PDO::ATTR_DRIVER_NAME));
}
public function qstr($str)
{
if (is_null($str)) {
return 'NULL';
}
return $this->db->quote($str);
}
private function _query($query, $values = null, $numrows = -1, $offset = -1)
{
global $num_queries;
$num_queries++;
$numrows = (int)$numrows;
$offset = (int)$offset;
if ($query == null) {
$query = $this->getQuery();
}
$this->convertQueryTablePrefixes($query);
if ($offset != -1 && $numrows != -1) {
$query .= " LIMIT $numrows OFFSET $offset";
} elseif ($numrows != -1) {
$query .= " LIMIT $numrows";
}
// change regular expression boundaries from Henry Spencer's implementation to
// Internation Components for Unicode (ICU) used in mysql 8.0.4 and onwards
// thanks to https://stackoverflow.com/a/59230861/2459703 for the help
if (stripos($query, 'REGEXP') !== false) {
$tikiDbPdoResult = $this->query("SHOW VARIABLES LIKE 'version'");
$mysqlVersion = $tikiDbPdoResult->fetchRow();
if (version_compare($mysqlVersion['Value'], '8.0.4') >= 0) {
$values = str_replace(['[[:<:]]', '[[:>:]]'], '\\b', $values);
// TODO other exceptions as listed here maybe?
// https://dev.mysql.com/doc/refman/8.0/en/regexp.html#regexp-compatibility
}
}
$starttime = $this->startTimer();
$result = false;
if ($values) {
if (@ $pq = $this->db->prepare($query)) {
if (! is_array($values)) {
$values = [$values];
}
$result = $pq->execute($values);
$this->rowCount = $pq->rowCount();
}
} else {
$result = @ $this->db->query($query);
$this->rowCount = is_object($result) && get_class($result) === 'PDOStatement' ? $result->rowCount() : 0;
}
$this->stopTimer($starttime);
if ($result === false) {
if (! $values || ! $pq) { // Query preparation or query failed
$tmp = $this->db->errorInfo();
} else { // Prepared query failed to execute
$tmp = $pq->errorInfo();
$pq->closeCursor();
}
$this->setErrorMessage($tmp[2]);
return false;
} else {
$this->setErrorMessage("");
if (($values && ! $pq->columnCount()) || (! $values && ! $result->columnCount())) {
return []; // Return empty result set for statements of manipulation
} elseif (! $values) {
return $result->fetchAll(PDO::FETCH_ASSOC);
} else {
return $pq->fetchAll(PDO::FETCH_ASSOC);
}
}
}
public function fetchAll($query = null, $values = null, $numrows = -1, $offset = -1, $reporterrors = parent::ERR_DIRECT)
{
$result = $this->_query($query, $values, $numrows, $offset);
if (! is_array($result)) {
$this->handleQueryError($query, $values, $result, $reporterrors);
}
return $result;
}
public function query($query = null, $values = null, $numrows = -1, $offset = -1, $reporterrors = self::ERR_DIRECT)
{
$result = $this->_query($query, $values, $numrows, $offset);
if ($result === false) {
$this->handleQueryError($query, $values, $result, $reporterrors);
}
return new TikiDb_Pdo_Result($result, $this->rowCount);
}
public function lastInsertId()
{
return $this->db->lastInsertId();
}
}