1+ <?php
2+
3+ declare (strict_types=1 );
4+
5+ namespace Pfilsx \PostgreSQLDoctrine \ORM \Query \AST \Functions ;
6+
7+ use Doctrine \ORM \Query \AST \Functions \FunctionNode ;
8+ use Doctrine \ORM \Query \AST \Node ;
9+ use Doctrine \ORM \Query \Lexer ;
10+ use Doctrine \ORM \Query \Parser ;
11+ use Doctrine \ORM \Query \SqlWalker ;
12+
13+ /**
14+ * Implementation of PostgreSql json object field retrieval by path
15+ * @see https://www.postgresql.org/docs/current/functions-json.html
16+ * @example JSON_GET_FIELD(entity.field, 'a', 'b')
17+ */
18+ class JsonGetField extends FunctionNode
19+ {
20+ protected Node $ field ;
21+
22+ /**
23+ * @var Node[]
24+ */
25+ protected array $ path = [];
26+
27+ public function parse (Parser $ parser ): void
28+ {
29+ $ parser ->match (Lexer::T_IDENTIFIER );
30+ $ parser ->match (Lexer::T_OPEN_PARENTHESIS );
31+
32+ $ this ->field = $ parser ->StringPrimary ();
33+ $ parser ->match (Lexer::T_COMMA );
34+ $ this ->path [] = $ parser ->StringPrimary ();
35+
36+ if (!$ parser ->getLexer ()->isNextToken (Lexer::T_CLOSE_PARENTHESIS )) {
37+ while ($ parser ->getLexer ()->isNextToken (Lexer::T_COMMA )) {
38+ $ parser ->match (Lexer::T_COMMA );
39+ $ this ->path [] = $ parser ->StringPrimary ();
40+ }
41+ }
42+
43+ $ parser ->match (Lexer::T_CLOSE_PARENTHESIS );
44+ }
45+
46+ public function getSql (SqlWalker $ sqlWalker ): string
47+ {
48+ return sprintf (
49+ '%s->%s ' ,
50+ $ this ->field ->dispatch ($ sqlWalker ),
51+ implode (
52+ '-> ' ,
53+ array_map (static fn (Node $ node ) => $ node ->dispatch ($ sqlWalker ), $ this ->path )
54+ )
55+ );
56+ }
57+ }
0 commit comments