Skip to content

Commit

Permalink
Allow numeric strings in number comparisons
Browse files Browse the repository at this point in the history
  • Loading branch information
crocodele committed Jan 26, 2025
1 parent a3d6ef4 commit d2c3282
Show file tree
Hide file tree
Showing 10 changed files with 351 additions and 14 deletions.
2 changes: 1 addition & 1 deletion pre-commit
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
#!/bin/sh

make format-check lint-code
#make format-check lint-code
9 changes: 7 additions & 2 deletions src/jsonpath/interpreter.c
Original file line number Diff line number Diff line change
Expand Up @@ -528,8 +528,13 @@ static BOOL_OR_ERR evaluate_binary(zval* arr_head, zval* arr_cur, struct ast_nod
/* Determine if two zvals can be checked for inequality (>, <, >=, <=). Specifically forbid comparing strings with
* numeric values in order to avoid returning true for scenarios such as 42 > "value". */
static bool can_check_inequality(zval* lhs, zval* rhs) {
bool lhs_is_numeric = (Z_TYPE_P(lhs) == IS_LONG || Z_TYPE_P(lhs) == IS_DOUBLE);
bool rhs_is_numeric = (Z_TYPE_P(rhs) == IS_LONG || Z_TYPE_P(rhs) == IS_DOUBLE);
bool lhs_is_numeric =
(Z_TYPE_P(lhs) == IS_LONG || Z_TYPE_P(lhs) == IS_DOUBLE ||
(Z_TYPE_P(lhs) == IS_STRING && is_numeric_string(Z_STRVAL_P(lhs), Z_STRLEN_P(lhs), NULL, NULL, 0)));

bool rhs_is_numeric =
(Z_TYPE_P(rhs) == IS_LONG || Z_TYPE_P(rhs) == IS_DOUBLE ||
(Z_TYPE_P(rhs) == IS_STRING && is_numeric_string(Z_STRVAL_P(rhs), Z_STRLEN_P(rhs), NULL, NULL, 0)));

if (lhs_is_numeric && rhs_is_numeric) {
return true;
Expand Down
93 changes: 93 additions & 0 deletions tests/024.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
--TEST--
Test greater-than number comparison condition with integer compared to numbers and numerical strings
--SKIPIF--
<?php if (!extension_loaded("jsonpath")) print "skip"; ?>
--FILE--
<?php

$data = [
[
'product' => 'tomato',
'quantity' => '4',
],
[
'product' => 'apple',
'quantity' => '1',
],
[
'product' => 'pear',
'quantity' => 2,
],
[
'product' => 'banana',
'quantity' => '0',
],
[
'product' => 'cucumber',
'quantity' => 0,
],
[
'product' => 'coconut',
'quantity' => '0.5',
],
[
'product' => 'carrot',
'quantity' => '3',
],
[
'product' => 'cauliflower',
'quantity' => '-4',
],
[
'product' => 'watermelon',
'quantity' => '-2',
],
[
'product' => 'asparagus',
'quantity' => '-2.5',
],
];

$jsonPath = new \JsonPath\JsonPath();
$result = $jsonPath->find($data, "$[?(@.quantity > 0)]");

var_dump($result);
?>
--EXPECT--
array(5) {
[0]=>
array(2) {
["product"]=>
string(6) "tomato"
["quantity"]=>
string(1) "4"
}
[1]=>
array(2) {
["product"]=>
string(5) "apple"
["quantity"]=>
string(1) "1"
}
[2]=>
array(2) {
["product"]=>
string(4) "pear"
["quantity"]=>
int(2)
}
[3]=>
array(2) {
["product"]=>
string(7) "coconut"
["quantity"]=>
string(3) "0.5"
}
[4]=>
array(2) {
["product"]=>
string(6) "carrot"
["quantity"]=>
string(1) "3"
}
}
121 changes: 121 additions & 0 deletions tests/025.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
--TEST--
Test greater-than-or-equal-to number comparison condition with integer compared to numbers and numerical strings
--SKIPIF--
<?php if (!extension_loaded("jsonpath")) print "skip"; ?>
--FILE--
<?php

$data = [
[
'product' => 'tomato',
'quantity' => '4',
],
[
'product' => 'apple',
'quantity' => '1',
],
[
'product' => 'pear',
'quantity' => 2,
],
[
'product' => 'banana',
'quantity' => '0',
],
[
'product' => 'cucumber',
'quantity' => 0,
],
[
'product' => 'coconut',
'quantity' => '0.5',
],
[
'product' => 'carrot',
'quantity' => '3',
],
[
'product' => 'cauliflower',
'quantity' => '-4',
],
[
'product' => 'watermelon',
'quantity' => '-2',
],
[
'product' => 'asparagus',
'quantity' => '-2.5',
],
];

$jsonPath = new \JsonPath\JsonPath();
$result = $jsonPath->find($data, "$[?(@.quantity >= -3)]");

var_dump($result);
?>
--EXPECT--
array(9) {
[0]=>
array(2) {
["product"]=>
string(6) "tomato"
["quantity"]=>
string(1) "4"
}
[1]=>
array(2) {
["product"]=>
string(5) "apple"
["quantity"]=>
string(1) "1"
}
[2]=>
array(2) {
["product"]=>
string(4) "pear"
["quantity"]=>
int(2)
}
[3]=>
array(2) {
["product"]=>
string(6) "banana"
["quantity"]=>
string(1) "0"
}
[4]=>
array(2) {
["product"]=>
string(8) "cucumber"
["quantity"]=>
int(0)
}
[5]=>
array(2) {
["product"]=>
string(7) "coconut"
["quantity"]=>
string(3) "0.5"
}
[6]=>
array(2) {
["product"]=>
string(6) "carrot"
["quantity"]=>
string(1) "3"
}
[7]=>
array(2) {
["product"]=>
string(10) "watermelon"
["quantity"]=>
string(2) "-2"
}
[8]=>
array(2) {
["product"]=>
string(9) "asparagus"
["quantity"]=>
string(4) "-2.5"
}
}
93 changes: 93 additions & 0 deletions tests/026.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
--TEST--
Test greater-than number comparison condition with float compared to numbers and numerical strings
--SKIPIF--
<?php if (!extension_loaded("jsonpath")) print "skip"; ?>
--FILE--
<?php

$data = [
[
'product' => 'tomato',
'quantity' => '4',
],
[
'product' => 'apple',
'quantity' => '1',
],
[
'product' => 'pear',
'quantity' => 2,
],
[
'product' => 'banana',
'quantity' => '0',
],
[
'product' => 'cucumber',
'quantity' => 0,
],
[
'product' => 'coconut',
'quantity' => '0.5',
],
[
'product' => 'carrot',
'quantity' => '3',
],
[
'product' => 'cauliflower',
'quantity' => '-4',
],
[
'product' => 'watermelon',
'quantity' => '-2',
],
[
'product' => 'asparagus',
'quantity' => '-2.5',
],
];

$jsonPath = new \JsonPath\JsonPath();
$result = $jsonPath->find($data, "$[?(@.quantity > 0.2)]");

var_dump($result);
?>
--EXPECT--
array(5) {
[0]=>
array(2) {
["product"]=>
string(6) "tomato"
["quantity"]=>
string(1) "4"
}
[1]=>
array(2) {
["product"]=>
string(5) "apple"
["quantity"]=>
string(1) "1"
}
[2]=>
array(2) {
["product"]=>
string(4) "pear"
["quantity"]=>
int(2)
}
[3]=>
array(2) {
["product"]=>
string(7) "coconut"
["quantity"]=>
string(3) "0.5"
}
[4]=>
array(2) {
["product"]=>
string(6) "carrot"
["quantity"]=>
string(1) "3"
}
}
7 changes: 6 additions & 1 deletion tests/comparison_filter/047.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ $result = $jsonPath->find($data, "$[?(@.key>42)]");
var_dump($result);
?>
--EXPECT--
array(3) {
array(4) {
[0]=>
array(1) {
["key"]=>
Expand All @@ -69,4 +69,9 @@ array(3) {
["key"]=>
int(100)
}
[3]=>
array(1) {
["key"]=>
string(2) "43"
}
}
12 changes: 11 additions & 1 deletion tests/comparison_filter/048.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ $result = $jsonPath->find($data, "$[?(@.key>=42)]");
var_dump($result);
?>
--EXPECT--
array(4) {
array(6) {
[0]=>
array(1) {
["key"]=>
Expand All @@ -74,4 +74,14 @@ array(4) {
["key"]=>
int(100)
}
[4]=>
array(1) {
["key"]=>
string(2) "43"
}
[5]=>
array(1) {
["key"]=>
string(2) "42"
}
}
7 changes: 6 additions & 1 deletion tests/comparison_filter/051.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ $result = $jsonPath->find($data, "$[?(@.key<42)]");
var_dump($result);
?>
--EXPECT--
array(4) {
array(5) {
[0]=>
array(1) {
["key"]=>
Expand All @@ -74,4 +74,9 @@ array(4) {
["key"]=>
float(41.9999)
}
[4]=>
array(1) {
["key"]=>
string(2) "41"
}
}
Loading

0 comments on commit d2c3282

Please sign in to comment.