1414use PHPUnit \Framework \TestCase ;
1515use ShipMonk \Doctrine \Walker \Handlers \CommentWholeSqlHintHandler ;
1616use ShipMonk \Doctrine \Walker \Handlers \LowercaseSelectHintHandler ;
17- use function sprintf ;
17+ use Symfony \ Component \ Cache \ Adapter \ ArrayAdapter ;
1818
1919class HintDrivenSqlWalkerTest extends TestCase
2020{
2121
2222 /**
23+ * @param callable(EntityManager):Query $queryCallback
2324 * @dataProvider walksProvider
2425 */
2526 public function testWalker (
26- string $ dql ,
27+ callable $ queryCallback ,
2728 string $ handlerClass ,
2829 mixed $ hintValue ,
2930 string $ expectedSql ,
3031 ): void
3132 {
3233 $ entityManagerMock = $ this ->createEntityManagerMock ();
3334
34- $ query = new Query ($ entityManagerMock );
35- $ query ->setDQL ($ dql );
36-
35+ $ query = $ queryCallback ($ entityManagerMock );
3736 $ query ->setHint (Query::HINT_CUSTOM_OUTPUT_WALKER , HintDrivenSqlWalker::class);
3837 $ query ->setHint ($ handlerClass , $ hintValue );
3938 $ producedSql = $ query ->getSQL ();
4039
4140 self ::assertSame ($ expectedSql , $ producedSql );
4241 }
4342
43+ public function testPagination (): void
44+ {
45+ $ pageSize = 10 ;
46+ $ entityManagerMock = $ this ->createEntityManagerMock ();
47+
48+ self ::assertNotNull (
49+ $ entityManagerMock ->getConfiguration ()->getQueryCache (),
50+ 'QueryCache needed. The purpose of this test is to ensure that we do not break the pagination by using a cache ' ,
51+ );
52+
53+ $ expectedSqls = [
54+ 'select d0_.id AS id_0 FROM dummy_entity d0_ LIMIT 10 ' ,
55+ 'select d0_.id AS id_0 FROM dummy_entity d0_ LIMIT 10 OFFSET 10 ' ,
56+ 'select d0_.id AS id_0 FROM dummy_entity d0_ LIMIT 10 OFFSET 20 ' ,
57+ ];
58+
59+ foreach ([0 , 1 , 2 ] as $ page ) {
60+ $ query = $ entityManagerMock ->createQueryBuilder ()
61+ ->select ('w ' )
62+ ->from (DummyEntity::class, 'w ' )
63+ ->getQuery ()
64+ ->setHint (Query::HINT_CUSTOM_OUTPUT_WALKER , HintDrivenSqlWalker::class)
65+ ->setHint (LowercaseSelectHintHandler::class, null )
66+ ->setFirstResult ($ page * $ pageSize )
67+ ->setMaxResults ($ pageSize );
68+ $ producedSql = $ query ->getSQL ();
69+
70+ self ::assertSame ($ expectedSqls [$ page ], $ producedSql , 'Page ' . $ page . ' failed: ' );
71+ }
72+ }
73+
4474 /**
45- * @return Generator<string, array{string , class-string<HintHandler>, mixed, string}>
75+ * @return Generator<string, array{callable(EntityManager):Query , class-string<HintHandler>, mixed, string}>
4676 */
4777 public static function walksProvider (): iterable
4878 {
49- $ selectDql = sprintf ('SELECT w FROM %s w ' , DummyEntity::class);
79+ $ selectQueryCallback = static function (EntityManager $ entityManager ): Query {
80+ return $ entityManager ->createQueryBuilder ()
81+ ->select ('w ' )
82+ ->from (DummyEntity::class, 'w ' )
83+ ->getQuery ();
84+ };
85+
86+ $ selectWithLimitQueryCallback = static function (EntityManager $ entityManager ): Query {
87+ return $ entityManager ->createQueryBuilder ()
88+ ->select ('w ' )
89+ ->from (DummyEntity::class, 'w ' )
90+ ->setMaxResults (1 )
91+ ->getQuery ();
92+ };
93+
94+ $ updateQueryCallback = static function (EntityManager $ entityManager ): Query {
95+ return $ entityManager ->createQueryBuilder ()
96+ ->update (DummyEntity::class, 'w ' )
97+ ->set ('w.id ' , 1 )
98+ ->getQuery ();
99+ };
100+
101+ $ deleteQueryCallback = static function (EntityManager $ entityManager ): Query {
102+ return $ entityManager ->createQueryBuilder ()
103+ ->delete (DummyEntity::class, 'w ' )
104+ ->getQuery ();
105+ };
50106
51107 yield 'Lowercase select ' => [
52- $ selectDql ,
108+ $ selectQueryCallback ,
53109 LowercaseSelectHintHandler::class,
54110 null ,
55111 'select d0_.id AS id_0 FROM dummy_entity d0_ ' ,
56112 ];
57113
114+ yield 'Lowercase select with LIMIT ' => [
115+ $ selectWithLimitQueryCallback ,
116+ LowercaseSelectHintHandler::class,
117+ null ,
118+ 'select d0_.id AS id_0 FROM dummy_entity d0_ LIMIT 1 ' ,
119+ ];
120+
58121 yield 'Comment whole sql - select ' => [
59- $ selectDql ,
122+ $ selectQueryCallback ,
60123 CommentWholeSqlHintHandler::class,
61124 'custom comment ' ,
62125 'SELECT d0_.id AS id_0 FROM dummy_entity d0_ -- custom comment ' ,
63126 ];
64127
128+ yield 'Comment whole sql - select with LIMIT ' => [
129+ $ selectWithLimitQueryCallback ,
130+ CommentWholeSqlHintHandler::class,
131+ 'custom comment ' ,
132+ 'SELECT d0_.id AS id_0 FROM dummy_entity d0_ -- custom comment LIMIT 1 ' , // see readme limitations
133+ ];
134+
65135 yield 'Comment whole sql - update ' => [
66- sprintf ( ' UPDATE %s w SET w.id = 1 ' , DummyEntity::class) ,
136+ $ updateQueryCallback ,
67137 CommentWholeSqlHintHandler::class,
68138 'custom comment ' ,
69139 'UPDATE dummy_entity SET id = 1 -- custom comment ' ,
70140 ];
71141
72142 yield 'Comment whole sql - delete ' => [
73- sprintf ( ' DELETE FROM %s w ' , DummyEntity::class) ,
143+ $ deleteQueryCallback ,
74144 CommentWholeSqlHintHandler::class,
75145 'custom comment ' ,
76146 'DELETE FROM dummy_entity -- custom comment ' ,
@@ -82,6 +152,7 @@ private function createEntityManagerMock(): EntityManager
82152 $ config = new Configuration ();
83153 $ config ->setProxyNamespace ('Tmp\Doctrine\Tests\Proxies ' );
84154 $ config ->setProxyDir ('/tmp/doctrine ' );
155+ $ config ->setQueryCache (new ArrayAdapter ());
85156 $ config ->setAutoGenerateProxyClasses (false );
86157 $ config ->setSecondLevelCacheEnabled (false );
87158 $ config ->setMetadataDriverImpl (new AttributeDriver ([__DIR__ ]));
0 commit comments