File tree Expand file tree Collapse file tree 4 files changed +147
-0
lines changed Expand file tree Collapse file tree 4 files changed +147
-0
lines changed Original file line number Diff line number Diff line change 1+ <?php
2+
3+ namespace WikibaseSolutions \CypherDSL \Clauses ;
4+
5+ use WikibaseSolutions \CypherDSL \Query ;
6+
7+ /**
8+ * This class represents a CALL clause.
9+ *
10+ * @see https://neo4j.com/docs/cypher-manual/current/clauses/call-subquery/
11+ */
12+ class CallClause extends Clause
13+ {
14+ /**
15+ * @var Query The query to call.
16+ */
17+ private Query $ subQuery ;
18+
19+ /**
20+ * @param Query $subQuery The query to call.
21+ */
22+ public function __construct (Query $ subQuery )
23+ {
24+ $ this ->subQuery = $ subQuery ;
25+ }
26+
27+ /**
28+ * Returns the query that is being called.
29+ *
30+ * @return Query
31+ */
32+ public function getSubQuery (): Query
33+ {
34+ return $ this ->subQuery ;
35+ }
36+
37+ public function toQuery (): string
38+ {
39+ $ subQuery = trim ($ this ->subQuery ->toQuery ());
40+
41+ if ($ subQuery === '' ) {
42+ return '' ;
43+ }
44+
45+ return sprintf ('CALL { %s } ' , $ subQuery );
46+ }
47+
48+ /**
49+ * @inheritDoc
50+ */
51+ protected function getSubject (): string
52+ {
53+ return '{ ' . $ this ->subQuery ->toQuery () . ' } ' ;
54+ }
55+
56+ /**
57+ * @inheritDoc
58+ */
59+ protected function getClause (): string
60+ {
61+ return 'CALL ' ;
62+ }
63+ }
Original file line number Diff line number Diff line change 2222namespace WikibaseSolutions \CypherDSL ;
2323
2424use function is_callable ;
25+ use WikibaseSolutions \CypherDSL \Clauses \CallClause ;
2526use WikibaseSolutions \CypherDSL \Clauses \CallProcedureClause ;
2627use WikibaseSolutions \CypherDSL \Clauses \Clause ;
2728use WikibaseSolutions \CypherDSL \Clauses \CreateClause ;
@@ -666,6 +667,29 @@ public function union($queryOrCallable, bool $all = false): self
666667 return $ this ;
667668 }
668669
670+ /**
671+ * Creates a CALL sub query clause.
672+ *
673+ * @param callable(Query)|Query $decoratorOrClause The callable decorating the pattern, or the actual CALL clause.
674+ *
675+ * @return Query
676+ *
677+ * @see https://neo4j.com/docs/cypher-manual/current/clauses/call-subquery/
678+ */
679+ public function call ($ decoratorOrClause ): self
680+ {
681+ if (is_callable ($ decoratorOrClause )) {
682+ $ subQuery = self ::new ();
683+ $ decoratorOrClause ($ subQuery );
684+ } else {
685+ $ subQuery = $ decoratorOrClause ;
686+ }
687+
688+ $ this ->clauses [] = new CallClause ($ subQuery );
689+
690+ return $ this ;
691+ }
692+
669693 /**
670694 * Add a clause to the query.
671695 *
Original file line number Diff line number Diff line change 1+ <?php
2+
3+ namespace WikibaseSolutions \CypherDSL \Tests \Unit \Clauses ;
4+
5+ use PHPUnit \Framework \TestCase ;
6+ use WikibaseSolutions \CypherDSL \Clauses \CallClause ;
7+ use WikibaseSolutions \CypherDSL \Query ;
8+
9+ class CallClauseTest extends TestCase
10+ {
11+ public function testCallClauseEmpty (): void
12+ {
13+ $ query = Query::new ();
14+
15+ $ clause = new CallClause ($ query );
16+
17+ $ this ->assertEquals ('' , $ clause ->toQuery ());
18+ $ this ->assertEquals (Query::new (), $ clause ->getSubQuery ());
19+ }
20+
21+ public function testCallClauseFilled (): void
22+ {
23+ $ query = Query::new ()->match (Query::node ('X ' )->named ('x ' ))->returning (Query::rawExpression ('* ' ));
24+
25+ $ clause = new CallClause ($ query );
26+
27+ $ this ->assertEquals ('CALL { MATCH (x:X) RETURN * } ' , $ clause ->toQuery ());
28+ $ this ->assertEquals ($ query , $ clause ->getSubQuery ());
29+ }
30+ }
Original file line number Diff line number Diff line change @@ -1107,6 +1107,36 @@ public function testAutomaticIdentifierGeneration(): void
11071107 $ this ->assertInstanceOf (Variable::class, $ node ->getName ());
11081108 }
11091109
1110+ public function testCallCallable (): void
1111+ {
1112+ $ node = Query::node ('X ' )->named ('y ' );
1113+ $ query = Query::new ()->match ($ node )
1114+ ->call (function (Query $ subQuery ) use ($ node ) {
1115+ $ subQuery ->with ($ node ->getVariable ())
1116+ ->where ($ node ->property ('z ' )->equals (Query::literal ('foo ' ), false ))
1117+ ->returning ($ node ->property ('z ' )->alias ('foo ' ));
1118+ })
1119+ ->returning (Query::variable ('foo ' ));
1120+
1121+ $ this ->assertEquals ("MATCH (y:X) CALL { WITH y WHERE y.z = 'foo' RETURN y.z AS foo } RETURN foo " , $ query ->toQuery ());
1122+ }
1123+
1124+ public function testCallClause (): void
1125+ {
1126+ $ node = Query::node ('X ' )->named ('y ' );
1127+
1128+ $ sub = Query::new ()->with ($ node ->getVariable ())
1129+ ->where ($ node ->property ('z ' )->equals (Query::literal ('foo ' ), false ))
1130+ ->returning ($ node ->property ('z ' )->alias ('foo ' ));
1131+
1132+ $ query = Query::new ()
1133+ ->match ($ node )
1134+ ->call ($ sub )
1135+ ->returning (Query::variable ('foo ' ));
1136+
1137+ $ this ->assertEquals ("MATCH (y:X) CALL { WITH y WHERE y.z = 'foo' RETURN y.z AS foo } RETURN foo " , $ query ->toQuery ());
1138+ }
1139+
11101140 public function provideLiteralData (): array
11111141 {
11121142 return [
You can’t perform that action at this time.
0 commit comments