diff --git a/src/Context.php b/src/Context.php
index 3a67e142..d332450c 100644
--- a/src/Context.php
+++ b/src/Context.php
@@ -139,6 +139,8 @@ abstract class Context
')' => 16,
'.' => 16,
',' => 16,
+ '->' => 16,
+ '->>' => 16,
';' => 16,
];
diff --git a/src/Utils/Formatter.php b/src/Utils/Formatter.php
index 7095e694..de33f874 100644
--- a/src/Utils/Formatter.php
+++ b/src/Utils/Formatter.php
@@ -533,19 +533,21 @@ public function formatList($list)
$lineEnded = false;
} else {
- // If the line ended there is no point in adding whitespaces.
+ // If the line ended, there is no point in adding whitespaces.
// Also, some tokens do not have spaces before or after them.
if (
- // A space after delimiters that are longer than 2 characters.
$prev->keyword === 'DELIMITER'
|| ! (
- ($prev->type === Token::TYPE_OPERATOR && ($prev->value === '.' || $prev->value === '('))
- // No space after . (
- || ($curr->type === Token::TYPE_OPERATOR
- && ($curr->value === '.' || $curr->value === ','
- || $curr->value === '(' || $curr->value === ')'))
- // No space before . , ( )
- || $curr->type === Token::TYPE_DELIMITER && mb_strlen((string) $curr->value, 'UTF-8') < 2
+ ($prev->type === Token::TYPE_OPERATOR
+ && ($prev->value === '.' || $prev->value === '('
+ || $prev->value === '->' || $prev->value === '->>'))
+ // No space after punctuation and JSON operators.
+ || ($curr->type === Token::TYPE_OPERATOR
+ && ($curr->value === '.' || $curr->value === ','
+ || $curr->value === '(' || $curr->value === ')'
+ || $curr->value === '->' || $curr->value === '->>'))
+ // No space before punctuation and JSON operators.
+ || $curr->type === Token::TYPE_DELIMITER && mb_strlen((string) $curr->value, 'UTF-8') < 2
)
) {
$ret .= ' ';
diff --git a/tests/Utils/FormatterTest.php b/tests/Utils/FormatterTest.php
index 73a6708d..98c2ab4c 100644
--- a/tests/Utils/FormatterTest.php
+++ b/tests/Utils/FormatterTest.php
@@ -321,6 +321,36 @@ public static function formatQueriesProviders(): array
'WHERE
' .
' 1',
],
+ 'json operator' => [
+ 'query' => 'SELECT details->\'$."first_name"\' FROM users',
+ 'text' => 'SELECT' . "\n" .
+ ' details->\'$."first_name"\'' . "\n" .
+ 'FROM' . "\n" .
+ ' users',
+ 'cli' => "\x1b[35mSELECT\n" .
+ " \x1b[39mdetails->\x1b[91m'$.\"first_name\"'\n" .
+ "\x1b[35mFROM\n" .
+ " \x1b[39musers\x1b[0m",
+ 'html' => 'SELECT
' .
+ ' details->\'$."first_name"\'
' .
+ 'FROM
' .
+ ' users',
+ ],
+ 'json operator (unquoted)' => [
+ 'query' => 'SELECT metadata->>"$.url" FROM `alerts`;',
+ 'text' => 'SELECT' . "\n" .
+ ' metadata->>"$.url"' . "\n" .
+ 'FROM' . "\n" .
+ ' `alerts`;',
+ 'cli' => "\x1b[35mSELECT\n" .
+ " \x1b[39mmetadata->>\x1b[91m\"$.url\"\n" .
+ "\x1b[35mFROM\n" .
+ " \x1b[36m`alerts`\x1b[39m;\x1b[0m",
+ 'html' => 'SELECT
' .
+ ' metadata->>"$.url"
' .
+ 'FROM
' .
+ ' `alerts`;',
+ ],
'typical' => [
'query' => 'SELECT id, if(id=1,"Si","No") from `tbl` where id = 0 or ' .
'id = 1 group by id order by id desc limit 1 offset 0',