Skip to content

Commit 4dc64f5

Browse files
authored
Merge pull request #30 from aaronm67/feature-inet_methods
Adds INET_ATON and INET_NTOA mysql methods
2 parents 0f6a4f1 + 1a1930d commit 4dc64f5

File tree

4 files changed

+121
-1
lines changed

4 files changed

+121
-1
lines changed

src/FakePdoStatementTrait.php

+4-1
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ public function universalExecute(?array $params = null)
129129
if ($this->realStatement) {
130130
if ($this->realStatement->execute($params) === false) {
131131
var_dump($this->sql);
132-
throw new \UnexpectedValueException($this->realStatement->errorInfo()[2]);
132+
throw new \UnexpectedValueException((string)$this->realStatement->errorInfo()[2]);
133133
}
134134
}
135135

@@ -632,6 +632,9 @@ private function getExecutedSql(?array $params) : string
632632
return $sql;
633633
}
634634

635+
/**
636+
* @return array{0: null|string, 1: int|null, 2: null|string, 3?: mixed, 4?: mixed}
637+
*/
635638
public function errorInfo(): array
636639
{
637640
return ['00000', 0, 'PHP MySQL Engine: errorInfo() not supported.'];

src/FakePdoTrait.php

+3
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,9 @@ public function quote($string, $parameter_type = \PDO::PARAM_STR)
213213
return "{$quotes[0]}{$quoted}{$quotes[1]}";
214214
}
215215

216+
/**
217+
* @return array{0: null|string, 1: int|null, 2: null|string, 3?: mixed, 4?: mixed}
218+
*/
216219
public function errorInfo(): array
217220
{
218221
return ['00000', 0, 'PHP MySQL Engine: errorInfo() not supported.'];

src/Processor/Expression/FunctionEvaluator.php

+69
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,10 @@ public static function evaluate(
100100
return self::sqlCurDate($expr);
101101
case 'WEEKDAY':
102102
return self::sqlWeekDay($conn, $scope, $expr, $row, $result);
103+
case 'INET_ATON':
104+
return self::sqlInetAton($conn, $scope, $expr, $row, $result);
105+
case 'INET_NTOA':
106+
return self::sqlInetNtoa($conn, $scope, $expr, $row, $result);
103107
}
104108

105109
throw new ProcessorException("Function " . $expr->functionName . " not implemented yet");
@@ -251,6 +255,9 @@ public static function getColumnSchema(
251255

252256
return Evaluator::getColumnSchema($expr->args[0], $scope, $columns);
253257

258+
case 'INET_ATON':
259+
return new Column\IntColumn(true, 15);
260+
254261
case 'DATEDIFF':
255262
case 'DAY':
256263
case 'WEEKDAY':
@@ -1280,6 +1287,68 @@ private static function sqlRound(
12801287
return \round($number, $precision);
12811288
}
12821289

1290+
/**
1291+
* @param array<string, mixed> $row
1292+
* @return float|null
1293+
*/
1294+
private static function sqlInetAton(
1295+
FakePdoInterface $conn,
1296+
Scope $scope,
1297+
FunctionExpression $expr,
1298+
array $row,
1299+
QueryResult $result
1300+
) : ?float {
1301+
$args = $expr->args;
1302+
1303+
if (\count($args) !== 1) {
1304+
throw new ProcessorException("MySQL INET_ATON() function must be called with one argument");
1305+
}
1306+
1307+
$subject = Evaluator::evaluate($conn, $scope, $args[0], $row, $result);
1308+
1309+
if (!is_string($subject)) {
1310+
// INET_ATON() returns NULL if it does not understand its argument.
1311+
return null;
1312+
}
1313+
1314+
$value = ip2long($subject);
1315+
1316+
if (!$value) {
1317+
return null;
1318+
}
1319+
1320+
// https://www.php.net/manual/en/function.ip2long.php - this comes as a signed int
1321+
//use %u to convert this to an unsigned long, then cast it as a float
1322+
return floatval(sprintf('%u', $value));
1323+
}
1324+
1325+
/**
1326+
* @param array<string, mixed> $row
1327+
* @return string
1328+
*/
1329+
private static function sqlInetNtoa(
1330+
FakePdoInterface $conn,
1331+
Scope $scope,
1332+
FunctionExpression $expr,
1333+
array $row,
1334+
QueryResult $result
1335+
) : ?string {
1336+
$args = $expr->args;
1337+
1338+
if (\count($args) !== 1) {
1339+
throw new ProcessorException("MySQL INET_NTOA() function must be called with one argument");
1340+
}
1341+
1342+
$subject = Evaluator::evaluate($conn, $scope, $args[0], $row, $result);
1343+
1344+
if (!is_numeric($subject)) {
1345+
// INET_NTOA() returns NULL if it does not understand its argument
1346+
return null;
1347+
}
1348+
1349+
return long2ip((int)$subject);
1350+
}
1351+
12831352
private static function getPhpIntervalFromExpression(
12841353
FakePdoInterface $conn,
12851354
Scope $scope,

tests/EndToEndTest.php

+45
Original file line numberDiff line numberDiff line change
@@ -542,6 +542,51 @@ public function testDecimalArithhmetic()
542542
);
543543
}
544544

545+
public function testInetAtoN()
546+
{
547+
$pdo = self::getPdo('mysql:foo');
548+
$pdo->setAttribute(\PDO::ATTR_EMULATE_PREPARES, false);
549+
550+
$query = $pdo->prepare("SELECT INET_ATON('255.255.255.255') AS a, INET_ATON('192.168.1.1') AS b, INET_ATON('127.0.0.1') AS c, INET_ATON('not an ip') AS d, INET_ATON(NULL) as e");
551+
$query->execute();
552+
$this->assertSame(
553+
[
554+
[
555+
'a' => 4294967295,
556+
'b' => 3232235777,
557+
'c' => 2130706433,
558+
'd' => NULL,
559+
'e' => NULL,
560+
],
561+
],
562+
$query->fetchAll(\PDO::FETCH_ASSOC)
563+
);
564+
}
565+
566+
567+
public function testInetNtoA()
568+
{
569+
$pdo = self::getPdo('mysql:foo');
570+
$pdo->setAttribute(\PDO::ATTR_EMULATE_PREPARES, false);
571+
572+
$query = $pdo->prepare("SELECT INET_NTOA(4294967295) AS a, INET_NTOA(3232235777) AS b, INET_NTOA(2130706433) AS c, INET_NTOA(NULL) as d, INET_NTOA('not a number') as e");
573+
$query->execute();
574+
575+
$this->assertSame(
576+
[
577+
[
578+
'a' => '255.255.255.255',
579+
'b' => '192.168.1.1',
580+
'c' => '127.0.0.1',
581+
'd' => NULL,
582+
'e' => NULL,
583+
],
584+
],
585+
$query->fetchAll(\PDO::FETCH_ASSOC)
586+
);
587+
}
588+
589+
545590
public function testRound()
546591
{
547592
$pdo = self::getPdo('mysql:foo');

0 commit comments

Comments
 (0)