Skip to content

Commit

Permalink
Merge branch '5.10.x' into 5.11.x
Browse files Browse the repository at this point in the history
Signed-off-by: Maurício Meneghini Fauth <[email protected]>
  • Loading branch information
MauricioFauth committed Sep 19, 2024
2 parents 91d980a + bc9ce73 commit a5a74e7
Show file tree
Hide file tree
Showing 19 changed files with 1,318 additions and 64 deletions.
4 changes: 3 additions & 1 deletion psalm-baseline.xml
Original file line number Diff line number Diff line change
Expand Up @@ -671,7 +671,7 @@
<code>$this-&gt;last</code>
<code>$this-&gt;last</code>
</LoopInvalidation>
<MixedArrayAccess occurrences="41">
<MixedArrayAccess occurrences="43">
<code>$this-&gt;str[$this-&gt;last + 1]</code>
<code>$this-&gt;str[$this-&gt;last++]</code>
<code>$this-&gt;str[$this-&gt;last]</code>
Expand Down Expand Up @@ -713,6 +713,8 @@
<code>$this-&gt;str[$this-&gt;last]</code>
<code>$this-&gt;str[$this-&gt;last]</code>
<code>$this-&gt;str[$this-&gt;last]</code>
<code>$this-&gt;str[$this-&gt;last]</code>
<code>$this-&gt;str[$this-&gt;last]</code>
</MixedArrayAccess>
<MixedAssignment occurrences="2">
<code>$lastToken</code>
Expand Down
5 changes: 4 additions & 1 deletion src/Components/AlterOperation.php
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,10 @@ class AlterOperation extends Component
'BY' => 2,
'FOREIGN' => 2,
'FULLTEXT' => 2,
'KEY' => 2,
'KEY' => [
2,
'var',
],
'KEYS' => 2,
'PARTITION' => 2,
'PARTITION BY' => 2,
Expand Down
22 changes: 17 additions & 5 deletions src/Lexer.php
Original file line number Diff line number Diff line change
Expand Up @@ -812,7 +812,7 @@ public function parseNumber()
// 1 --------------------[ + or - ]-------------------> 1
// 1 -------------------[ 0x or 0X ]------------------> 2
// 1 --------------------[ 0 to 9 ]-------------------> 3
// 1 -----------------------[ . ]---------------------> 4
// 1 -----------------------[ . ]---------------------> 10
// 1 -----------------------[ b ]---------------------> 7
//
// 2 --------------------[ 0 to F ]-------------------> 2
Expand All @@ -831,11 +831,16 @@ public function parseNumber()
// 8 --------------------[ 0 or 1 ]-------------------> 8
// 8 -----------------------[ ' ]---------------------> 9
//
// 10 -------------------[ 0 to 9 ]-------------------> 4
//
// State 1 may be reached by negative numbers.
// State 2 is reached only by hex numbers.
// State 4 is reached only by float numbers.
// State 5 is reached only by numbers in approximate form.
// State 7 is reached only by numbers in bit representation.
// State 10 is a forced proxy to state 4 ensuring a starting dot (= "0.something") precedes a digit, and not "e"
// or "E" causing wrongly interpreted scientific notation (".e[0 to 9]" is invalid). Such invalid notation could
// break the lexer when table names under a given database context starts with ".e[0-9]".
//
// Valid final states are: 2, 3, 4 and 6. Any parsing that finished in a
// state other than these is invalid.
Expand All @@ -858,7 +863,7 @@ public function parseNumber()
} elseif ($this->str[$this->last] >= '0' && $this->str[$this->last] <= '9') {
$state = 3;
} elseif ($this->str[$this->last] === '.') {
$state = 4;
$state = 10;
} elseif ($this->str[$this->last] === 'b') {
$state = 7;
} elseif ($this->str[$this->last] !== '+') {
Expand All @@ -885,7 +890,7 @@ public function parseNumber()
($this->str[$this->last] >= 'a' && $this->str[$this->last] <= 'z')
|| ($this->str[$this->last] >= 'A' && $this->str[$this->last] <= 'Z')
) {
// A number can't be directly followed by a letter
// A number can't be directly followed by a letter
$state = -$state;
} elseif ($this->str[$this->last] < '0' || $this->str[$this->last] > '9') {
// Just digits and `.`, `e` and `E` are valid characters.
Expand All @@ -899,7 +904,7 @@ public function parseNumber()
($this->str[$this->last] >= 'a' && $this->str[$this->last] <= 'z')
|| ($this->str[$this->last] >= 'A' && $this->str[$this->last] <= 'Z')
) {
// A number can't be directly followed by a letter
// A number can't be directly followed by a letter
$state = -$state;
} elseif ($this->str[$this->last] < '0' || $this->str[$this->last] > '9') {
// Just digits, `e` and `E` are valid characters.
Expand All @@ -916,7 +921,7 @@ public function parseNumber()
($this->str[$this->last] >= 'a' && $this->str[$this->last] <= 'z')
|| ($this->str[$this->last] >= 'A' && $this->str[$this->last] <= 'Z')
) {
// A number can't be directly followed by a letter
// A number can't be directly followed by a letter
$state = -$state;
} else {
break;
Expand All @@ -941,6 +946,13 @@ public function parseNumber()
}
} elseif ($state === 9) {
break;
} elseif ($state === 10) {
$flags |= Token::FLAG_NUMBER_FLOAT;
if ($this->str[$this->last] < '0' || $this->str[$this->last] > '9') {
break;
}

$state = 4;
}

$token .= $this->str[$this->last];
Expand Down
3 changes: 2 additions & 1 deletion src/Statements/SelectStatement.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace PhpMyAdmin\SqlParser\Statements;

use PhpMyAdmin\SqlParser\Components\ArrayObj;
use PhpMyAdmin\SqlParser\Components\CaseExpression;
use PhpMyAdmin\SqlParser\Components\Condition;
use PhpMyAdmin\SqlParser\Components\Expression;
use PhpMyAdmin\SqlParser\Components\FunctionCall;
Expand Down Expand Up @@ -234,7 +235,7 @@ class SelectStatement extends Statement
/**
* Expressions that are being selected by this statement.
*
* @var Expression[]
* @var (CaseExpression|Expression)[]
*/
public $expr = [];

Expand Down
31 changes: 18 additions & 13 deletions src/TokensList.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

use ArrayAccess;

use function array_splice;
use function count;
use function in_array;
use function is_array;
Expand Down Expand Up @@ -213,25 +214,29 @@ public function getNextOfTypeAndFlag(int $type, int $flag): ?Token
}

/**
* Sets an value inside the container.
* Sets a Token inside the list of tokens.
* When defined, offset must be positive otherwise the offset is ignored.
* If the offset is not defined (like in array_push) or if it is greater than the number of Tokens already stored,
* the Token is appended to the list of tokens.
*
* @param int|null $offset the offset to be set
* @param int|null $offset the offset to be set. Must be positive otherwise, nothing will be stored.
* @param Token $value the token to be saved
*
* @return void
*/
#[\ReturnTypeWillChange]
public function offsetSet($offset, $value)
{
if ($offset === null) {
if ($offset === null || $offset >= $this->count) {
$this->tokens[$this->count++] = $value;
} else {
} elseif ($offset >= 0) {
$this->tokens[$offset] = $value;
}
}

/**
* Gets a value from the container.
* Gets a Token from the list of tokens.
* If the offset is negative or above the number of tokens set in the list, will return null.
*
* @param int $offset the offset to be returned
*
Expand All @@ -240,11 +245,12 @@ public function offsetSet($offset, $value)
#[\ReturnTypeWillChange]
public function offsetGet($offset)
{
return $offset < $this->count ? $this->tokens[$offset] : null;
return $this->offsetExists($offset) ? $this->tokens[$offset] : null;
}

/**
* Checks if an offset was previously set.
* If the offset is negative or above the number of tokens set in the list, will return false.
*
* @param int $offset the offset to be checked
*
Expand All @@ -253,11 +259,11 @@ public function offsetGet($offset)
#[\ReturnTypeWillChange]
public function offsetExists($offset)
{
return $offset < $this->count;
return $offset >= 0 && $offset < $this->count;
}

/**
* Unsets the value of an offset.
* Unsets the value of an offset, if the offset exists.
*
* @param int $offset the offset to be unset
*
Expand All @@ -266,12 +272,11 @@ public function offsetExists($offset)
#[\ReturnTypeWillChange]
public function offsetUnset($offset)
{
unset($this->tokens[$offset]);
--$this->count;
for ($i = $offset; $i < $this->count; ++$i) {
$this->tokens[$i] = $this->tokens[$i + 1];
if (! $this->offsetExists($offset)) {
return;
}

unset($this->tokens[$this->count]);
array_splice($this->tokens, $offset, 1);
--$this->count;
}
}
30 changes: 27 additions & 3 deletions tests/Lexer/TokensListTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -137,17 +137,41 @@ public function testArrayAccess(): void
// offsetSet($offset, $value)
$list[2] = $this->tokens[2];

// offsetSet($offset, $value) with overflowed offset
$list[$list->count] = $this->tokens[1];
$this->assertSame($list[$list->count - 1], $this->tokens[1]);
$this->assertSame($list->count, count($this->tokens) + 1);

// offsetGet($offset) with negative offset
$this->assertNull($list[-1]);

// offsetGet($offset) with overflow offset
$this->assertNull($list[$list->count]);

// offsetGet($offset)
for ($i = 0, $count = count($this->tokens); $i < $count; ++$i) {
$this->assertEquals($this->tokens[$i], $list[$i]);
$this->assertSame($this->tokens[$i], $list[$i]);
}

// offsetExists($offset)
$this->assertArrayHasKey(2, $list);
$this->assertArrayNotHasKey(13, $list);
$this->assertArrayNotHasKey(14, $list);
$this->assertArrayNotHasKey(-8, $list);

// offsetUnset($offset)
$currentCountTokens = $list->count;
unset($list[2]);
$this->assertEquals($this->tokens[3], $list[2]);
$newCountTokens = $list->count;
$this->assertSame($this->tokens[3], $list[2]);
$this->assertSame($currentCountTokens - 1, $newCountTokens);

// offsetUnset($offset) with invalid offset (negative or overflowed)
$currentListTokens = $list->tokens;
unset($list[-1]);
$this->assertSame($currentListTokens, $list->tokens);
$this->assertSame($newCountTokens, $list->count); // No unset actually performed.
unset($list[999]);
$this->assertSame($currentListTokens, $list->tokens);
$this->assertSame($newCountTokens, $list->count); // No unset actually performed.
}
}
2 changes: 2 additions & 0 deletions tests/Parser/AlterStatementTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ public static function alterProvider(): array
['parser/parseAlterErr4'],
['parser/parseAlterTableRenameIndex1'],
['parser/parseAlterTableRenameIndex2'],
['parser/parseAlterTableRenameKey1'],
['parser/parseAlterTableRenameKey2'],
['parser/parseAlterTablePartitionByRange1'],
['parser/parseAlterTablePartitionByRange2'],
['parser/parseAlterTableCoalescePartition'],
Expand Down
1 change: 1 addition & 0 deletions tests/Parser/LoadStatementTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ public static function loadProvider(): array
['parser/parseLoad5'],
['parser/parseLoad6'],
['parser/parseLoad7'],
['parser/parseLoad8'],
['parser/parseLoadErr1'],
['parser/parseLoadErr2'],
['parser/parseLoadErr3'],
Expand Down
18 changes: 7 additions & 11 deletions tests/data/bugs/gh317.out
Original file line number Diff line number Diff line change
Expand Up @@ -209,19 +209,15 @@
"@type": "PhpMyAdmin\\SqlParser\\Components\\OptionsArray",
"options": {
"1": "ADD",
"2": "KEY"
"2": {
"name": "KEY",
"equals": false,
"expr": "`IDX_REPAIR`",
"value": "IDX_REPAIR"
}
}
},
"field": {
"@type": "PhpMyAdmin\\SqlParser\\Components\\Expression",
"database": null,
"table": null,
"column": "IDX_REPAIR",
"expr": "`IDX_REPAIR`",
"alias": null,
"function": null,
"subquery": null
},
"field": null,
"partitions": null,
"unknown": [
{
Expand Down
2 changes: 1 addition & 1 deletion tests/data/lexer/lexNumber.in
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
SELECT 12, 34, 5.67, 0x89, -10, --11, +12, .15, 0xFFa, 0xfFA, +0xfFA, -0xFFa, -0xfFA, 1e-10, 1e10, .5e10, b'10';
-- invalid numbers
SELECT 12ex10, b'15', 0XFfA, -0XFfA, +0XFfA;
SELECT 12ex10, b'15', 0XFfA, -0XFfA, +0XFfA, .e4;
57 changes: 51 additions & 6 deletions tests/data/lexer/lexNumber.out
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
{
"query": "SELECT 12, 34, 5.67, 0x89, -10, --11, +12, .15, 0xFFa, 0xfFA, +0xfFA, -0xFFa, -0xfFA, 1e-10, 1e10, .5e10, b'10';\n-- invalid numbers\nSELECT 12ex10, b'15', 0XFfA, -0XFfA, +0XFfA;",
"query": "SELECT 12, 34, 5.67, 0x89, -10, --11, +12, .15, 0xFFa, 0xfFA, +0xfFA, -0xFFa, -0xfFA, 1e-10, 1e10, .5e10, b'10';\n-- invalid numbers\nSELECT 12ex10, b'15', 0XFfA, -0XFfA, +0XFfA, .e4;\n",
"lexer": {
"@type": "PhpMyAdmin\\SqlParser\\Lexer",
"str": "SELECT 12, 34, 5.67, 0x89, -10, --11, +12, .15, 0xFFa, 0xfFA, +0xfFA, -0xFFa, -0xfFA, 1e-10, 1e10, .5e10, b'10';\n-- invalid numbers\nSELECT 12ex10, b'15', 0XFfA, -0XFfA, +0XFfA;",
"len": 176,
"last": 176,
"str": "SELECT 12, 34, 5.67, 0x89, -10, --11, +12, .15, 0xFFa, 0xfFA, +0xfFA, -0xFFa, -0xfFA, 1e-10, 1e10, .5e10, b'10';\n-- invalid numbers\nSELECT 12ex10, b'15', 0XFfA, -0XFfA, +0XFfA, .e4;\n",
"len": 182,
"last": 182,
"list": {
"@type": "PhpMyAdmin\\SqlParser\\TokensList",
"tokens": [
Expand Down Expand Up @@ -665,14 +665,59 @@
"flags": 0,
"position": 170
},
{
"@type": "PhpMyAdmin\\SqlParser\\Token",
"token": ",",
"value": ",",
"keyword": null,
"type": 2,
"flags": 16,
"position": 175
},
{
"@type": "PhpMyAdmin\\SqlParser\\Token",
"token": " ",
"value": " ",
"keyword": null,
"type": 3,
"flags": 0,
"position": 176
},
{
"@type": "PhpMyAdmin\\SqlParser\\Token",
"token": ".",
"value": ".",
"keyword": null,
"type": 2,
"flags": 16,
"position": 177
},
{
"@type": "PhpMyAdmin\\SqlParser\\Token",
"token": "e4",
"value": "e4",
"keyword": null,
"type": 0,
"flags": 0,
"position": 178
},
{
"@type": "PhpMyAdmin\\SqlParser\\Token",
"token": ";",
"value": ";",
"keyword": null,
"type": 9,
"flags": 0,
"position": 175
"position": 180
},
{
"@type": "PhpMyAdmin\\SqlParser\\Token",
"token": "\n",
"value": " ",
"keyword": null,
"type": 3,
"flags": 0,
"position": 181
},
{
"@type": "PhpMyAdmin\\SqlParser\\Token",
Expand All @@ -684,7 +729,7 @@
"position": null
}
],
"count": 75,
"count": 80,
"idx": 0
},
"delimiter": ";",
Expand Down
Loading

0 comments on commit a5a74e7

Please sign in to comment.