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',