Skip to content

Commit 17e598a

Browse files
committed
feat!: drop php<8.2 and align PDO/MySQLi result behavior
1 parent c4f0b33 commit 17e598a

8 files changed

Lines changed: 75 additions & 25 deletions

File tree

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ jobs:
2222
strategy:
2323
fail-fast: false
2424
matrix:
25-
php: ['7.4', '8.0', '8.1']
25+
php: ['8.2', '8.3']
2626
driver: [mysqli, pdo]
2727
search_build: [SPHINX2, SPHINX3, MANTICORE]
2828
env:

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
#### 4.0.0
2+
* Dropped support for PHP 8.1 and lower (minimum PHP is now 8.2)
3+
* Updated CI PHP matrix to 8.2 and 8.3
4+
* Restored runtime-level driver normalization for PDO/MySQLi scalar fetch values
5+
* Normalized MySQLi driver exception handling for modern PHP `mysqli_sql_exception` behavior
6+
17
#### 3.0.2
28
* Dropped support for PHP 7.3 and lower
39

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ Query Builder for SphinxQL
1010

1111
This is a SphinxQL Query Builder used to work with SphinxQL, a SQL dialect used with the Sphinx search engine and it's fork Manticore. It maps most of the functions listed in the [SphinxQL reference](http://sphinxsearch.com/docs/current.html#SphinxQL-reference) and is generally [faster](http://sphinxsearch.com/blog/2010/04/25/sphinxapi-vs-SphinxQL-benchmark/) than the available Sphinx API.
1212

13-
This Query Builder has no dependencies except PHP 7.1 or later, `\MySQLi` extension, `PDO`, and [Sphinx](http://sphinxsearch.com)/[Manticore](https://manticoresearch.com).
13+
This Query Builder has no dependencies except PHP 8.2 or later, `\MySQLi` extension, `PDO`, and [Sphinx](http://sphinxsearch.com)/[Manticore](https://manticoresearch.com).
1414

1515
### Missing methods?
1616

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
"irc": "irc://irc.irchighway.net/fooldriver"
1313
},
1414
"require": {
15-
"php": "^7.1 || ^8"
15+
"php": "^8.2"
1616
},
1717
"require-dev": {
1818
"phpunit/phpunit": "^7 || ^8 || ^9"

src/Drivers/Mysqli/Connection.php

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
use Foolz\SphinxQL\Exception\ConnectionException;
99
use Foolz\SphinxQL\Exception\DatabaseException;
1010
use Foolz\SphinxQL\Exception\SphinxQLException;
11+
use mysqli_sql_exception;
1112

1213
/**
1314
* SphinxQL connection class utilizing the MySQLi extension.
@@ -51,6 +52,12 @@ public function connect()
5152
if (!$conn->real_connect($data['host'], null, null, null, (int) $data['port'], $data['socket'])) {
5253
throw new ConnectionException('Connection Error: ['.$conn->connect_errno.']'.$conn->connect_error);
5354
}
55+
} catch (mysqli_sql_exception $exception) {
56+
throw new ConnectionException(
57+
'Connection Error: ['.$exception->getCode().']'.$exception->getMessage(),
58+
(int) $exception->getCode(),
59+
$exception
60+
);
5461
} finally {
5562
restore_error_handler();
5663
}
@@ -102,9 +109,15 @@ public function query($query)
102109
* ERROR mysqli::prepare(): (08S01/1047): unknown command (code=22) - prepare() not implemented by Sphinx/Manticore
103110
*/
104111
$resource = @$this->getConnection()->query($query);
112+
} catch (mysqli_sql_exception $exception) {
113+
throw new DatabaseException(
114+
'['.$exception->getCode().'] '.$exception->getMessage().' [ '.$query.']',
115+
(int) $exception->getCode(),
116+
$exception
117+
);
105118
} finally {
106119
restore_error_handler();
107-
}
120+
}
108121

109122
if ($this->getConnection()->error) {
110123
throw new DatabaseException('['.$this->getConnection()->errno.'] '.
@@ -127,7 +140,15 @@ public function multiQuery(array $queue)
127140

128141
$this->ensureConnection();
129142

130-
$this->getConnection()->multi_query(implode(';', $queue));
143+
try {
144+
$this->getConnection()->multi_query(implode(';', $queue));
145+
} catch (mysqli_sql_exception $exception) {
146+
throw new DatabaseException(
147+
'['.$exception->getCode().'] '.$exception->getMessage().' [ '.implode(';', $queue).']',
148+
(int) $exception->getCode(),
149+
$exception
150+
);
151+
}
131152

132153
if ($this->getConnection()->error) {
133154
throw new DatabaseException('['.$this->getConnection()->errno.'] '.
@@ -146,7 +167,13 @@ public function escape($value)
146167
{
147168
$this->ensureConnection();
148169

149-
if (($value = $this->getConnection()->real_escape_string((string) $value)) === false) {
170+
try {
171+
$value = $this->getConnection()->real_escape_string((string) $value);
172+
} catch (mysqli_sql_exception $exception) {
173+
throw new DatabaseException($exception->getMessage(), (int) $exception->getCode(), $exception);
174+
}
175+
176+
if ($value === false) {
150177
// @codeCoverageIgnoreStart
151178
throw new DatabaseException($this->getConnection()->error, $this->getConnection()->errno);
152179
// @codeCoverageIgnoreEnd

src/Drivers/Pdo/ResultSetAdapter.php

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ public function isDml()
6969
*/
7070
public function store()
7171
{
72-
return $this->statement->fetchAll(PDO::FETCH_NUM);
72+
return $this->normalizeRows($this->statement->fetchAll(PDO::FETCH_NUM));
7373
}
7474

7575
/**
@@ -118,6 +118,8 @@ public function fetch($assoc = true)
118118
if (!$row) {
119119
$this->valid = false;
120120
$row = null;
121+
} else {
122+
$row = $this->normalizeRow($row);
121123
}
122124

123125
return $row;
@@ -138,6 +140,37 @@ public function fetchAll($assoc = true)
138140
$this->valid = false;
139141
}
140142

143+
return $this->normalizeRows($row);
144+
}
145+
146+
/**
147+
* Cast scalar non-string values to string to keep PDO and MySQLi
148+
* result typing aligned across PHP versions.
149+
*
150+
* @param array $row
151+
* @return array
152+
*/
153+
protected function normalizeRow(array $row)
154+
{
155+
foreach ($row as $key => $value) {
156+
if (is_scalar($value) && !is_string($value)) {
157+
$row[$key] = (string) $value;
158+
}
159+
}
160+
141161
return $row;
142162
}
163+
164+
/**
165+
* @param array $rows
166+
* @return array
167+
*/
168+
protected function normalizeRows(array $rows)
169+
{
170+
foreach ($rows as $index => $row) {
171+
$rows[$index] = $this->normalizeRow($row);
172+
}
173+
174+
return $rows;
175+
}
143176
}

tests/SphinxQL/TestUtil.php

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44

55
use Foolz\SphinxQL\Drivers\Mysqli\Connection as MysqliConnection;
66
use Foolz\SphinxQL\Drivers\Pdo\Connection as PdoConnection;
7-
use PDO;
87

98
class TestUtil
109
{
@@ -13,18 +12,8 @@ class TestUtil
1312
*/
1413
public static function getConnectionDriver()
1514
{
16-
if ($GLOBALS['driver'] === 'Pdo') {
17-
return new class extends PdoConnection {
18-
public function connect()
19-
{
20-
$connected = parent::connect();
21-
$this->getConnection()->setAttribute(PDO::ATTR_STRINGIFY_FETCHES, true);
15+
$connection = '\\Foolz\\SphinxQL\\Drivers\\'.$GLOBALS['driver'].'\\Connection';
2216

23-
return $connected;
24-
}
25-
};
26-
}
27-
28-
return new MysqliConnection();
17+
return new $connection();
2918
}
3019
}

tests/bootstrap.php

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,5 @@
11
<?php
22

3-
// Keep MySQLi behavior stable across PHP versions in test runs.
4-
if (function_exists('mysqli_report') && defined('MYSQLI_REPORT_OFF')) {
5-
mysqli_report(MYSQLI_REPORT_OFF);
6-
}
7-
83
// PHPUnit Backwards Compatability Fix
94
if (!class_exists('\PHPUnit\Framework\TestCase')) {
105
class_alias('\PHPUnit_Framework_TestCase', '\PHPUnit\Framework\TestCase');

0 commit comments

Comments
 (0)