Skip to content

Commit

Permalink
Added [NO] INDENT option for XMLSERIALIZE()
Browse files Browse the repository at this point in the history
  • Loading branch information
sad-spirit committed Aug 29, 2023
1 parent 7223561 commit ac5879a
Show file tree
Hide file tree
Showing 6 changed files with 30 additions and 7 deletions.
1 change: 1 addition & 0 deletions Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ Support new syntax of PostgreSQL 16 (as of beta 3)
* Constructor functions `json_array()` and `json_object()` represented by
`nodes\json\JsonArrayValueList`, `nodes\json\JsonArraySubselect`, `nodes\json\JsonObject` classes.
* `SYSTEM_USER` server variable backed by `nodes\expressions\SQLValueFunction`.
* `[NO] INDENT` option for `XMLSERIALIZE()` expression.


## [2.2.0] - 2023-05-14
Expand Down
8 changes: 7 additions & 1 deletion src/sad_spirit/pg_builder/Parser.php
Original file line number Diff line number Diff line change
Expand Up @@ -2805,7 +2805,13 @@ protected function SystemFunctionCallRequiredParens(): ?nodes\FunctionLike
$value = $this->Expression();
$this->stream->expect(Token::TYPE_KEYWORD, 'as');
$typeName = $this->SimpleTypeName();
$funcNode = new nodes\xml\XmlSerialize($docOrContent, $value, $typeName);
$indent = null;
if ($this->stream->matchesKeyword(['no', 'indent'])) {
if (!($indent = ('indent' === $this->stream->next()->getValue()))) {
$this->stream->expect(Token::TYPE_KEYWORD, 'indent');
}
}
$funcNode = new nodes\xml\XmlSerialize($docOrContent, $value, $typeName, $indent);
break;

case 'normalize':
Expand Down
3 changes: 2 additions & 1 deletion src/sad_spirit/pg_builder/SqlBuilderWalker.php
Original file line number Diff line number Diff line change
Expand Up @@ -1327,7 +1327,8 @@ public function walkXmlRoot(nodes\xml\XmlRoot $xml): string
public function walkXmlSerialize(nodes\xml\XmlSerialize $xml): string
{
return 'xmlserialize(' . $xml->documentOrContent . ' ' . $xml->argument->dispatch($this)
. ' as ' . $xml->type->dispatch($this) . ')';
. ' as ' . $xml->type->dispatch($this)
. (null === $xml->indent ? '' : ($xml->indent ? ' indent' : ' no indent')) . ')';
}

public function walkXmlTable(nodes\range\XmlTable $table): string
Expand Down
18 changes: 16 additions & 2 deletions src/sad_spirit/pg_builder/nodes/xml/XmlSerialize.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
* @property-read string $documentOrContent
* @property ScalarExpression $argument
* @property-read TypeName $type
* @property bool|null $indent
*/
class XmlSerialize extends GenericNode implements ScalarExpression, FunctionLike
{
Expand All @@ -55,9 +56,15 @@ class XmlSerialize extends GenericNode implements ScalarExpression, FunctionLike
protected $p_argument;
/** @var TypeName */
protected $p_type;
/** @var bool|null */
protected $p_indent;

public function __construct(string $documentOrContent, ScalarExpression $argument, TypeName $typeName)
{
public function __construct(
string $documentOrContent,
ScalarExpression $argument,
TypeName $typeName,
?bool $indent = null
) {
if (!isset(self::ALLOWED_TYPES[$documentOrContent])) {
throw new InvalidArgumentException(
"Either 'document' or 'content' option required, '{$documentOrContent}' given"
Expand All @@ -72,13 +79,20 @@ public function __construct(string $documentOrContent, ScalarExpression $argumen

$this->p_type = $typeName;
$this->p_type->setParentNode($this);

$this->p_indent = $indent;
}

public function setArgument(ScalarExpression $argument): void
{
$this->setRequiredProperty($this->p_argument, $argument);
}

public function setIndent(?bool $indent): void
{
$this->p_indent = $indent;
}

public function dispatch(TreeWalker $walker)
{
return $walker->walkXmlSerialize($this);
Expand Down
5 changes: 3 additions & 2 deletions tests/ParseFunctionCallTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -379,9 +379,10 @@ public function testXmlSerialize(): void
new XmlSerialize(
'document',
new ColumnReference('foo'),
new TypeName(new QualifiedName('pg_catalog', 'text'))
new TypeName(new QualifiedName('pg_catalog', 'text')),
true
),
$this->parser->parseExpression('xmlserialize(document foo as pg_catalog.text)')
$this->parser->parseExpression('xmlserialize(document foo as pg_catalog.text indent)')
);
}

Expand Down
2 changes: 1 addition & 1 deletion tests/SqlBuilderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ public function testBuildSelectStatement(): void
xmlparse(document xml.doc preserve whitespace),
xmlpi(name php, 'echo ''Hello world!'';'),
xmlroot(doc, version '1.2', standalone yes),
xmlserialize(document foo as pg_catalog.text)
xmlserialize(document foo as pg_catalog.text indent)
),
fnstuff as materialized (
select s.num,
Expand Down

0 comments on commit ac5879a

Please sign in to comment.