Skip to content

Commit 3a7c59a

Browse files
Sea-nwilliamdes
andcommitted
Fix formatter spacing for JSON path operators (->, ->>)
- Treat `->` and `->>` as SQL operators in the lexer. - Prevent formatter from inserting spaces around JSON path operators. - Add formatter test for JSON path access. For example: ```sql SELECT details->'$."first_name"' FROM users; ``` Signed-off-by: Sean Wei <me@sean.taipei> Co-Authored-By: William Desportes <williamdes@wdes.fr>
1 parent 018f347 commit 3a7c59a

File tree

3 files changed

+43
-9
lines changed

3 files changed

+43
-9
lines changed

src/Context.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,8 @@ abstract class Context
139139
')' => 16,
140140
'.' => 16,
141141
',' => 16,
142+
'->' => 16,
143+
'->>' => 16,
142144
';' => 16,
143145
];
144146

src/Utils/Formatter.php

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -533,19 +533,21 @@ public function formatList($list)
533533

534534
$lineEnded = false;
535535
} else {
536-
// If the line ended there is no point in adding whitespaces.
536+
// If the line ended, there is no point in adding whitespaces.
537537
// Also, some tokens do not have spaces before or after them.
538538
if (
539-
// A space after delimiters that are longer than 2 characters.
540539
$prev->keyword === 'DELIMITER'
541540
|| ! (
542-
($prev->type === Token::TYPE_OPERATOR && ($prev->value === '.' || $prev->value === '('))
543-
// No space after . (
544-
|| ($curr->type === Token::TYPE_OPERATOR
545-
&& ($curr->value === '.' || $curr->value === ','
546-
|| $curr->value === '(' || $curr->value === ')'))
547-
// No space before . , ( )
548-
|| $curr->type === Token::TYPE_DELIMITER && mb_strlen((string) $curr->value, 'UTF-8') < 2
541+
($prev->type === Token::TYPE_OPERATOR
542+
&& ($prev->value === '.' || $prev->value === '('
543+
|| $prev->value === '->' || $prev->value === '->>'))
544+
// No space after punctuation and JSON operators.
545+
|| ($curr->type === Token::TYPE_OPERATOR
546+
&& ($curr->value === '.' || $curr->value === ','
547+
|| $curr->value === '(' || $curr->value === ')'
548+
|| $curr->value === '->' || $curr->value === '->>'))
549+
// No space before punctuation and JSON operators.
550+
|| $curr->type === Token::TYPE_DELIMITER && mb_strlen((string) $curr->value, 'UTF-8') < 2
549551
)
550552
) {
551553
$ret .= ' ';

tests/Utils/FormatterTest.php

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -321,6 +321,36 @@ public static function formatQueriesProviders(): array
321321
'<span class="sql-reserved">WHERE</span><br/>' .
322322
'&nbsp;&nbsp;&nbsp;&nbsp;<span class="sql-number">1</span>',
323323
],
324+
'json operator' => [
325+
'query' => 'SELECT details->\'$."first_name"\' FROM users',
326+
'text' => 'SELECT' . "\n" .
327+
' details->\'$."first_name"\'' . "\n" .
328+
'FROM' . "\n" .
329+
' users',
330+
'cli' => "\x1b[35mSELECT\n" .
331+
" \x1b[39mdetails->\x1b[91m'$.\"first_name\"'\n" .
332+
"\x1b[35mFROM\n" .
333+
" \x1b[39musers\x1b[0m",
334+
'html' => '<span class="sql-reserved">SELECT</span><br/>' .
335+
'&nbsp;&nbsp;&nbsp;&nbsp;details-&gt;<span class="sql-string">\'$."first_name"\'</span><br/>' .
336+
'<span class="sql-reserved">FROM</span><br/>' .
337+
'&nbsp;&nbsp;&nbsp;&nbsp;users',
338+
],
339+
'json operator (unquoted)' => [
340+
'query' => 'SELECT metadata->>"$.url" FROM `alerts`;',
341+
'text' => 'SELECT' . "\n" .
342+
' metadata->>"$.url"' . "\n" .
343+
'FROM' . "\n" .
344+
' `alerts`;',
345+
'cli' => "\x1b[35mSELECT\n" .
346+
" \x1b[39mmetadata->>\x1b[91m\"$.url\"\n" .
347+
"\x1b[35mFROM\n" .
348+
" \x1b[36m`alerts`\x1b[39m;\x1b[0m",
349+
'html' => '<span class="sql-reserved">SELECT</span><br/>' .
350+
'&nbsp;&nbsp;&nbsp;&nbsp;metadata-&gt;&gt;<span class="sql-string">"$.url"</span><br/>' .
351+
'<span class="sql-reserved">FROM</span><br/>' .
352+
'&nbsp;&nbsp;&nbsp;&nbsp;<span class="sql-variable">`alerts`</span>;',
353+
],
324354
'typical' => [
325355
'query' => 'SELECT id, if(id=1,"Si","No") from `tbl` where id = 0 or ' .
326356
'id = 1 group by id order by id desc limit 1 offset 0',

0 commit comments

Comments
 (0)