PageRenderTime 50ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/tests/Propel/Tests/Generator/Builder/Om/QueryBuilderTest.php

http://github.com/propelorm/Propel2
PHP | 1433 lines | 1004 code | 196 blank | 233 comment | 0 complexity | 230ed525efb1e9fcba37ebcae0ccab41 MD5 | raw file
  1. <?php
  2. /**
  3. * MIT License. This file is part of the Propel package.
  4. * For the full copyright and license information, please view the LICENSE
  5. * file that was distributed with this source code.
  6. */
  7. namespace Propel\Tests\Generator\Builder\Om;
  8. use Propel\Runtime\ActiveQuery\Criteria;
  9. use Propel\Runtime\ActiveQuery\Criterion\ExistsCriterion;
  10. use Propel\Runtime\ActiveQuery\ModelCriteria;
  11. use Propel\Runtime\ActiveQuery\ModelJoin;
  12. use Propel\Runtime\Exception\PropelException;
  13. use Propel\Runtime\Map\TableMap;
  14. use Propel\Runtime\Propel;
  15. use Propel\Tests\Bookstore\AcctAuditLogQuery;
  16. use Propel\Tests\Bookstore\AuthorQuery;
  17. use Propel\Tests\Bookstore\Book;
  18. use Propel\Tests\Bookstore\BookClubListQuery;
  19. use Propel\Tests\Bookstore\BookListRelQuery;
  20. use Propel\Tests\Bookstore\BookOpinionQuery;
  21. use Propel\Tests\Bookstore\BookQuery;
  22. use Propel\Tests\Bookstore\BookstoreEmployeeAccountQuery;
  23. use Propel\Tests\Bookstore\BookSummaryQuery;
  24. use Propel\Tests\Bookstore\EssayQuery;
  25. use Propel\Tests\Bookstore\Map\AcctAuditLogTableMap;
  26. use Propel\Tests\Bookstore\Map\AuthorTableMap;
  27. use Propel\Tests\Bookstore\Map\BookListRelTableMap;
  28. use Propel\Tests\Bookstore\Map\BookstoreEmployeeAccountTableMap;
  29. use Propel\Tests\Bookstore\Map\BookTableMap;
  30. use Propel\Tests\Bookstore\Map\PublisherTableMap;
  31. use Propel\Tests\Bookstore\Map\RecordLabelTableMap;
  32. use Propel\Tests\Bookstore\Map\ReleasePoolTableMap;
  33. use Propel\Tests\Bookstore\Map\ReviewTableMap;
  34. use Propel\Tests\Bookstore\ReaderFavoriteQuery;
  35. use Propel\Tests\Bookstore\RecordLabelQuery;
  36. use Propel\Tests\Bookstore\ReleasePoolQuery;
  37. use Propel\Tests\Bookstore\ReviewQuery;
  38. use Propel\Tests\Helpers\Bookstore\BookstoreDataPopulator;
  39. use Propel\Tests\Helpers\Bookstore\BookstoreTestBase;
  40. use ReflectionMethod;
  41. /**
  42. * Test class for QueryBuilder.
  43. *
  44. * @author François Zaninotto
  45. *
  46. * @group database
  47. */
  48. class QueryBuilderTest extends BookstoreTestBase
  49. {
  50. /**
  51. * @return void
  52. */
  53. protected function setUp(): void
  54. {
  55. parent::setUp();
  56. include_once(__DIR__ . '/QueryBuilderTestClasses.php');
  57. include_once(__DIR__ . '/TestableQueryBuilder.php');
  58. }
  59. /**
  60. * @return void
  61. */
  62. public function testExtends()
  63. {
  64. $q = new BookQuery();
  65. $this->assertTrue($q instanceof ModelCriteria, 'Model query extends ModelCriteria');
  66. }
  67. /**
  68. * @return void
  69. */
  70. public function testConstructor()
  71. {
  72. $query = new BookQuery();
  73. $this->assertEquals('bookstore', $query->getDbName(), 'Constructor sets dabatase name');
  74. $this->assertEquals('Propel\Tests\Bookstore\Book', $query->getModelName(), 'Constructor sets model name');
  75. }
  76. /**
  77. * @return void
  78. */
  79. public function testCreate()
  80. {
  81. $query = BookQuery::create();
  82. $this->assertTrue($query instanceof BookQuery, 'create() returns an object of its class');
  83. $this->assertEquals('bookstore', $query->getDbName(), 'create() sets dabatase name');
  84. $this->assertEquals('Propel\Tests\Bookstore\Book', $query->getModelName(), 'create() sets model name');
  85. $query = BookQuery::create('foo');
  86. $this->assertTrue($query instanceof BookQuery, 'create() returns an object of its class');
  87. $this->assertEquals($query->getDbName(), 'bookstore', 'create() sets dabatase name');
  88. $this->assertEquals('Propel\Tests\Bookstore\Book', $query->getModelName(), 'create() sets model name');
  89. $this->assertEquals('foo', $query->getModelAlias(), 'create() can set the model alias');
  90. }
  91. /**
  92. * @return void
  93. */
  94. public function testCreateCustom()
  95. {
  96. // see the myBookQuery class definition at the end of this file
  97. $query = MyCustomBookQuery::create();
  98. $this->assertTrue($query instanceof MyCustomBookQuery, 'create() returns an object of its class');
  99. $this->assertTrue($query instanceof BookQuery, 'create() returns an object of its class');
  100. $this->assertEquals('bookstore', $query->getDbName(), 'create() sets dabatase name');
  101. $this->assertEquals('Propel\Tests\Bookstore\Book', $query->getModelName(), 'create() sets model name');
  102. $query = MyCustomBookQuery::create('foo');
  103. $this->assertTrue($query instanceof MyCustomBookQuery, 'create() returns an object of its class');
  104. $this->assertEquals('bookstore', $query->getDbName(), 'create() sets dabatase name');
  105. $this->assertEquals('Propel\Tests\Bookstore\Book', $query->getModelName(), 'create() sets model name');
  106. $this->assertEquals('foo', $query->getModelAlias(), 'create() can set the model alias');
  107. }
  108. /**
  109. * @return void
  110. */
  111. public function testBasePreSelect()
  112. {
  113. $method = new ReflectionMethod('\Propel\Tests\Bookstore\Behavior\Table2Query', 'basePreSelect');
  114. $this->assertEquals('Propel\Runtime\ActiveQuery\ModelCriteria', $method->getDeclaringClass()->getName(), 'BaseQuery does not override basePreSelect() by default');
  115. $method = new ReflectionMethod('\Propel\Tests\Bookstore\Behavior\Table3Query', 'basePreSelect');
  116. $this->assertEquals('Propel\Tests\Bookstore\Behavior\Base\Table3Query', $method->getDeclaringClass()->getName(), 'BaseQuery overrides basePreSelect() when a behavior is registered');
  117. }
  118. /**
  119. * @return void
  120. */
  121. public function testBasePreDelete()
  122. {
  123. $method = new ReflectionMethod('\Propel\Tests\Bookstore\Behavior\Table2Query', 'basePreDelete');
  124. $this->assertEquals('Propel\Runtime\ActiveQuery\ModelCriteria', $method->getDeclaringClass()->getName(), 'BaseQuery does not override basePreDelete() by default');
  125. $method = new ReflectionMethod('\Propel\Tests\Bookstore\Behavior\Table3Query', 'basePreDelete');
  126. $this->assertEquals('Propel\Tests\Bookstore\Behavior\Base\Table3Query', $method->getDeclaringClass()->getName(), 'BaseQuery overrides basePreDelete() when a behavior is registered');
  127. }
  128. /**
  129. * @return void
  130. */
  131. public function testBasePostDelete()
  132. {
  133. $method = new ReflectionMethod('\Propel\Tests\Bookstore\Behavior\Table2Query', 'basePostDelete');
  134. $this->assertEquals('Propel\Runtime\ActiveQuery\ModelCriteria', $method->getDeclaringClass()->getName(), 'BaseQuery does not override basePostDelete() by default');
  135. $method = new ReflectionMethod('\Propel\Tests\Bookstore\Behavior\Table3Query', 'basePostDelete');
  136. $this->assertEquals('Propel\Tests\Bookstore\Behavior\Base\Table3Query', $method->getDeclaringClass()->getName(), 'BaseQuery overrides basePostDelete() when a behavior is registered');
  137. }
  138. /**
  139. * @return void
  140. */
  141. public function testBasePreUpdate()
  142. {
  143. $method = new ReflectionMethod('\Propel\Tests\Bookstore\Behavior\Table2Query', 'basePreUpdate');
  144. $this->assertEquals('Propel\Runtime\ActiveQuery\ModelCriteria', $method->getDeclaringClass()->getName(), 'BaseQuery does not override basePreUpdate() by default');
  145. $method = new ReflectionMethod('\Propel\Tests\Bookstore\Behavior\Table3Query', 'basePreUpdate');
  146. $this->assertEquals('Propel\Tests\Bookstore\Behavior\Base\Table3Query', $method->getDeclaringClass()->getName(), 'BaseQuery overrides basePreUpdate() when a behavior is registered');
  147. }
  148. /**
  149. * @return void
  150. */
  151. public function testBasePostUpdate()
  152. {
  153. $method = new ReflectionMethod('\Propel\Tests\Bookstore\Behavior\Table2Query', 'basePostUpdate');
  154. $this->assertEquals('Propel\Runtime\ActiveQuery\ModelCriteria', $method->getDeclaringClass()->getName(), 'BaseQuery does not override basePostUpdate() by default');
  155. $method = new ReflectionMethod('\Propel\Tests\Bookstore\Behavior\Table3Query', 'basePostUpdate');
  156. $this->assertEquals('Propel\Tests\Bookstore\Behavior\Base\Table3Query', $method->getDeclaringClass()->getName(), 'BaseQuery overrides basePostUpdate() when a behavior is registered');
  157. }
  158. /**
  159. * @return void
  160. */
  161. public function testQuery()
  162. {
  163. BookstoreDataPopulator::depopulate();
  164. BookstoreDataPopulator::populate();
  165. $q = new BookQuery();
  166. $book = $q
  167. ->setModelAlias('b')
  168. ->where('b.Title like ?', 'Don%')
  169. ->orderBy('b.ISBN', 'desc')
  170. ->findOne();
  171. $this->assertTrue($book instanceof Book);
  172. $this->assertEquals('Don Juan', $book->getTitle());
  173. }
  174. /**
  175. * @return void
  176. */
  177. public function testFindPk()
  178. {
  179. $method = new ReflectionMethod('\Propel\Tests\Bookstore\BookQuery', 'findPk');
  180. $this->assertEquals('Propel\Tests\Bookstore\Base\BookQuery', $method->getDeclaringClass()->getName(), 'BaseQuery overrides findPk()');
  181. }
  182. /**
  183. * @return void
  184. */
  185. public function testFindPkReturnsCorrectObjectForSimplePrimaryKey()
  186. {
  187. $b = new Book();
  188. $b->setTitle('bar');
  189. $b->setISBN('FA404');
  190. $b->save($this->con);
  191. $count = $this->con->getQueryCount();
  192. BookTableMap::clearInstancePool();
  193. $book = BookQuery::create()->findPk($b->getId(), $this->con);
  194. $this->assertEquals($b, $book);
  195. $this->assertEquals($count + 1, $this->con->getQueryCount(), 'findPk() issues a database query when instance is not in pool');
  196. }
  197. /**
  198. * @return void
  199. */
  200. public function testFindPkUsesInstancePoolingForSimplePrimaryKey()
  201. {
  202. $b = new Book();
  203. $b->setTitle('foo');
  204. $b->setISBN('FA404');
  205. $b->save($this->con);
  206. $count = $this->con->getQueryCount();
  207. $book = BookQuery::create()->findPk($b->getId(), $this->con);
  208. $this->assertSame($b, $book);
  209. $this->assertEquals($count, $this->con->getQueryCount(), 'findPk() does not issue a database query when instance is in pool');
  210. }
  211. /**
  212. * @return void
  213. */
  214. public function testFindPkReturnsCorrectObjectForCompositePrimaryKey()
  215. {
  216. BookstoreDataPopulator::depopulate();
  217. BookstoreDataPopulator::populate();
  218. // save all books to make sure related objects are also saved - BookstoreDataPopulator keeps some unsaved
  219. $c = new ModelCriteria('bookstore', '\Propel\Tests\Bookstore\Book');
  220. $books = $c->find();
  221. foreach ($books as $book) {
  222. $book->save();
  223. }
  224. BookTableMap::clearInstancePool();
  225. // retrieve the test data
  226. $c = new ModelCriteria('bookstore', '\Propel\Tests\Bookstore\BookListRel');
  227. $bookListRelTest = $c->findOne();
  228. $pk = $bookListRelTest->getPrimaryKey();
  229. $q = new BookListRelQuery();
  230. $bookListRel = $q->findPk($pk);
  231. $this->assertEquals($bookListRelTest, $bookListRel, 'BaseQuery overrides findPk() for composite primary keysto make it faster');
  232. }
  233. /**
  234. * @return void
  235. */
  236. public function testFindPkUsesFindPkSimpleOnEmptyQueries()
  237. {
  238. BookQuery::create()->findPk(123, $this->con);
  239. $expected = 'SELECT id, title, isbn, price, publisher_id, author_id FROM book WHERE id = 123';
  240. $this->assertEquals($expected, $this->con->getLastExecutedQuery());
  241. }
  242. /**
  243. * @return void
  244. */
  245. public function testFindPkSimpleAddsObjectToInstancePool()
  246. {
  247. $b = new Book();
  248. $b->setTitle('foo');
  249. $b->setISBN('FA404');
  250. $b->save($this->con);
  251. BookTableMap::clearInstancePool();
  252. BookQuery::create()->findPk($b->getId(), $this->con);
  253. $count = $this->con->getQueryCount();
  254. $book = BookQuery::create()->findPk($b->getId(), $this->con);
  255. $this->assertEquals($b, $book);
  256. $this->assertEquals($count, $this->con->getQueryCount());
  257. }
  258. /**
  259. * @return void
  260. */
  261. public function testFindPkUsesFindPkComplexOnNonEmptyQueries()
  262. {
  263. BookQuery::create('b')->findPk(123, $this->con);
  264. $expected = $this->getSql('SELECT book.id, book.title, book.isbn, book.price, book.publisher_id, book.author_id FROM book WHERE book.id=123');
  265. $this->assertEquals($expected, $this->con->getLastExecutedQuery());
  266. }
  267. /**
  268. * @return void
  269. */
  270. public function testFindPkNotUsesInstancePoolingForNonEmptyQueries()
  271. {
  272. $b = new Book();
  273. $b->setTitle('foo');
  274. $b->setISBN('FA404');
  275. $b->save($this->con);
  276. $book = BookQuery::create()->select(['Book.Title', 'Book.ISBN'])->findPk($b->getId(), $this->con);
  277. $this->assertIsArray($book);
  278. $book = BookQuery::create()->filterByTitle('bar')->findPk($b->getId(), $this->con);
  279. $this->assertNull($book);
  280. }
  281. /**
  282. * @return void
  283. */
  284. public function testFindPkComplexAddsObjectToInstancePool()
  285. {
  286. $b = new Book();
  287. $b->setTitle('foo');
  288. $b->setISBN('FA404');
  289. $b->save($this->con);
  290. BookTableMap::clearInstancePool();
  291. BookQuery::create('b')->findPk($b->getId(), $this->con);
  292. $count = $this->con->getQueryCount();
  293. $book = BookQuery::create()->findPk($b->getId(), $this->con);
  294. $this->assertEquals($b, $book);
  295. $this->assertEquals($count, $this->con->getQueryCount());
  296. }
  297. /**
  298. * @return void
  299. */
  300. public function testFindPkCallsPreSelect()
  301. {
  302. $q = new MySecondBookQuery();
  303. $this->assertFalse($q::$preSelectWasCalled);
  304. $q->findPk(123);
  305. $this->assertTrue($q::$preSelectWasCalled);
  306. }
  307. /**
  308. * @return void
  309. */
  310. public function testFindPks()
  311. {
  312. $method = new ReflectionMethod('\Propel\Tests\Bookstore\BookQuery', 'findPks');
  313. $this->assertEquals('Propel\Tests\Bookstore\Base\BookQuery', $method->getDeclaringClass()->getName(), 'BaseQuery overrides findPks()');
  314. }
  315. /**
  316. * @return void
  317. */
  318. public function testFindPksSimpleKey()
  319. {
  320. BookstoreDataPopulator::depopulate();
  321. BookstoreDataPopulator::populate();
  322. BookTableMap::clearInstancePool();
  323. // prepare the test data
  324. $c = new ModelCriteria('bookstore', '\Propel\Tests\Bookstore\Book');
  325. $c->orderBy('Book.Id', 'desc');
  326. $testBooks = $c->find();
  327. $testBook1 = $testBooks->pop();
  328. $testBook2 = $testBooks->pop();
  329. $q = new BookQuery();
  330. $books = $q->findPks([$testBook1->getId(), $testBook2->getId()]);
  331. $this->assertEquals([$testBook1, $testBook2], $books->getData(), 'BaseQuery overrides findPks() to make it faster');
  332. }
  333. /**
  334. * @return void
  335. */
  336. public function testFindPksCompositeKey()
  337. {
  338. BookstoreDataPopulator::depopulate();
  339. BookstoreDataPopulator::populate();
  340. // save all books to make sure related objects are also saved - BookstoreDataPopulator keeps some unsaved
  341. $c = new ModelCriteria('bookstore', '\Propel\Tests\Bookstore\Book');
  342. $books = $c->find();
  343. foreach ($books as $book) {
  344. $book->save();
  345. }
  346. BookTableMap::clearInstancePool();
  347. // retrieve the test data
  348. $c = new ModelCriteria('bookstore', '\Propel\Tests\Bookstore\BookListRel');
  349. $bookListRelTest = $c->find();
  350. $search = [];
  351. foreach ($bookListRelTest as $obj) {
  352. $search[] = $obj->getPrimaryKey();
  353. }
  354. $q = new BookListRelQuery();
  355. $objs = $q->findPks($search);
  356. $this->assertEquals($bookListRelTest->getArrayCopy(), $objs->getArrayCopy(), 'BaseQuery overrides findPks() for composite primary keys to make it work');
  357. }
  358. /**
  359. * @return void
  360. */
  361. public function testFilterBy()
  362. {
  363. foreach (BookTableMap::getFieldNames(TableMap::TYPE_PHPNAME) as $colName) {
  364. $filterMethod = 'filterBy' . $colName;
  365. $this->assertTrue(method_exists('\Propel\Tests\Bookstore\BookQuery', $filterMethod), 'QueryBuilder adds filterByColumn() methods for every column');
  366. $q = BookQuery::create()->$filterMethod(1);
  367. $this->assertTrue($q instanceof BookQuery, 'filterByColumn() returns the current query instance');
  368. }
  369. }
  370. /**
  371. * @return void
  372. */
  373. public function testFilterByPrimaryKeySimpleKey()
  374. {
  375. $q = BookQuery::create()->filterByPrimaryKey(12);
  376. $q1 = BookQuery::create()->add(BookTableMap::COL_ID, 12, Criteria::EQUAL);
  377. $this->assertEquals($q1, $q, 'filterByPrimaryKey() translates to a Criteria::EQUAL in the PK column');
  378. $q = BookQuery::create()->setModelAlias('b', true)->filterByPrimaryKey(12);
  379. $q1 = BookQuery::create()->setModelAlias('b', true)->add('b.id', 12, Criteria::EQUAL);
  380. $this->assertEquals($q1, $q, 'filterByPrimaryKey() uses true table alias if set');
  381. }
  382. /**
  383. * @return void
  384. */
  385. public function testFilterByPrimaryKeyCompositeKey()
  386. {
  387. BookstoreDataPopulator::depopulate();
  388. BookstoreDataPopulator::populate();
  389. // save all books to make sure related objects are also saved - BookstoreDataPopulator keeps some unsaved
  390. $c = new ModelCriteria('bookstore', '\Propel\Tests\Bookstore\Book');
  391. $books = $c->find();
  392. foreach ($books as $book) {
  393. $book->save();
  394. }
  395. BookTableMap::clearInstancePool();
  396. // retrieve the test data
  397. $c = new ModelCriteria('bookstore', '\Propel\Tests\Bookstore\BookListRel');
  398. $bookListRelTest = $c->findOne();
  399. $pk = $bookListRelTest->getPrimaryKey();
  400. $q = new BookListRelQuery();
  401. $q->filterByPrimaryKey($pk);
  402. $q1 = BookListRelQuery::create()
  403. ->add(BookListRelTableMap::COL_BOOK_ID, $pk[0], Criteria::EQUAL)
  404. ->add(BookListRelTableMap::COL_BOOK_CLUB_LIST_ID, $pk[1], Criteria::EQUAL);
  405. $this->assertEquals($q1, $q, 'filterByPrimaryKey() translates to a Criteria::EQUAL in the PK columns');
  406. }
  407. /**
  408. * @return void
  409. */
  410. public function testFilterByPrimaryKeysSimpleKey()
  411. {
  412. $q = BookQuery::create()->filterByPrimaryKeys([10, 11, 12]);
  413. $q1 = BookQuery::create()->add(BookTableMap::COL_ID, [10, 11, 12], Criteria::IN);
  414. $this->assertEquals($q1, $q, 'filterByPrimaryKeys() translates to a Criteria::IN on the PK column');
  415. $q = BookQuery::create()->setModelAlias('b', true)->filterByPrimaryKeys([10, 11, 12]);
  416. $q1 = BookQuery::create()->setModelAlias('b', true)->add('b.id', [10, 11, 12], Criteria::IN);
  417. $this->assertEquals($q1, $q, 'filterByPrimaryKeys() uses true table alias if set');
  418. }
  419. /**
  420. * @return void
  421. */
  422. public function testFilterByPrimaryKeysCompositeKey()
  423. {
  424. BookstoreDataPopulator::depopulate();
  425. BookstoreDataPopulator::populate();
  426. // save all books to make sure related objects are also saved - BookstoreDataPopulator keeps some unsaved
  427. $c = new ModelCriteria('bookstore', '\Propel\Tests\Bookstore\Book');
  428. $books = $c->find();
  429. foreach ($books as $book) {
  430. $book->save();
  431. }
  432. BookTableMap::clearInstancePool();
  433. // retrieve the test data
  434. $c = new ModelCriteria('bookstore', '\Propel\Tests\Bookstore\BookListRel');
  435. $bookListRelTest = $c->find();
  436. $search = [];
  437. foreach ($bookListRelTest as $obj) {
  438. $search[] = $obj->getPrimaryKey();
  439. }
  440. $q = new BookListRelQuery();
  441. $q->filterByPrimaryKeys($search);
  442. $q1 = BookListRelQuery::create();
  443. foreach ($search as $key) {
  444. $cton0 = $q1->getNewCriterion(BookListRelTableMap::COL_BOOK_ID, $key[0], Criteria::EQUAL);
  445. $cton1 = $q1->getNewCriterion(BookListRelTableMap::COL_BOOK_CLUB_LIST_ID, $key[1], Criteria::EQUAL);
  446. $cton0->addAnd($cton1);
  447. $q1->addOr($cton0);
  448. }
  449. $this->assertEquals($q1, $q, 'filterByPrimaryKeys() translates to a series of Criteria::EQUAL in the PK columns');
  450. $q = new BookListRelQuery();
  451. $q->filterByPrimaryKeys([]);
  452. $q1 = BookListRelQuery::create();
  453. $q1->add(null, '1<>1', Criteria::CUSTOM);
  454. $this->assertEquals($q1, $q, 'filterByPrimaryKeys() translates to an always failing test on empty arrays');
  455. }
  456. /**
  457. * @return void
  458. */
  459. public function testFilterByIntegerPk()
  460. {
  461. $q = BookQuery::create()->filterById(12);
  462. $q1 = BookQuery::create()->add(BookTableMap::COL_ID, 12, Criteria::EQUAL);
  463. $this->assertEquals($q1, $q, 'filterByPkColumn() translates to a Criteria::EQUAL by default');
  464. $q = BookQuery::create()->filterById(12, Criteria::NOT_EQUAL);
  465. $q1 = BookQuery::create()->add(BookTableMap::COL_ID, 12, Criteria::NOT_EQUAL);
  466. $this->assertEquals($q1, $q, 'filterByPkColumn() accepts an optional comparison operator');
  467. $q = BookQuery::create()->setModelAlias('b', true)->filterById(12);
  468. $q1 = BookQuery::create()->setModelAlias('b', true)->add('b.id', 12, Criteria::EQUAL);
  469. $this->assertEquals($q1, $q, 'filterByPkColumn() uses true table alias if set');
  470. $q = BookQuery::create()->filterById([10, 11, 12]);
  471. $q1 = BookQuery::create()->add(BookTableMap::COL_ID, [10, 11, 12], Criteria::IN);
  472. $this->assertEquals($q1, $q, 'filterByPkColumn() translates to a Criteria::IN when passed a simple array key');
  473. $q = BookQuery::create()->filterById([10, 11, 12], Criteria::NOT_IN);
  474. $q1 = BookQuery::create()->add(BookTableMap::COL_ID, [10, 11, 12], Criteria::NOT_IN);
  475. $this->assertEquals($q1, $q, 'filterByPkColumn() accepts a comparison when passed a simple array key');
  476. }
  477. /**
  478. * @return void
  479. */
  480. public function testFilterByNumber()
  481. {
  482. $q = BookQuery::create()->filterByPrice(12);
  483. $q1 = BookQuery::create()->add(BookTableMap::COL_PRICE, 12, Criteria::EQUAL);
  484. $this->assertEquals($q1, $q, 'filterByNumColumn() translates to a Criteria::EQUAL by default');
  485. $q = BookQuery::create()->filterByPrice(12, Criteria::NOT_EQUAL);
  486. $q1 = BookQuery::create()->add(BookTableMap::COL_PRICE, 12, Criteria::NOT_EQUAL);
  487. $this->assertEquals($q1, $q, 'filterByNumColumn() accepts an optional comparison operator');
  488. $q = BookQuery::create()->setModelAlias('b', true)->filterByPrice(12);
  489. $q1 = BookQuery::create()->setModelAlias('b', true)->add('b.price', 12, Criteria::EQUAL);
  490. $this->assertEquals($q1, $q, 'filterByNumColumn() uses true table alias if set');
  491. $q = BookQuery::create()->filterByPrice([10, 11, 12]);
  492. $q1 = BookQuery::create()->add(BookTableMap::COL_PRICE, [10, 11, 12], Criteria::IN);
  493. $this->assertEquals($q1, $q, 'filterByNumColumn() translates to a Criteria::IN when passed a simple array key');
  494. $q = BookQuery::create()->filterByPrice([10, 11, 12], Criteria::NOT_IN);
  495. $q1 = BookQuery::create()->add(BookTableMap::COL_PRICE, [10, 11, 12], Criteria::NOT_IN);
  496. $this->assertEquals($q1, $q, 'filterByNumColumn() accepts a comparison when passed a simple array key');
  497. $q = BookQuery::create()->filterByPrice(['min' => 10]);
  498. $q1 = BookQuery::create()->add(BookTableMap::COL_PRICE, 10, Criteria::GREATER_EQUAL);
  499. $this->assertEquals($q1, $q, 'filterByNumColumn() translates to a Criteria::GREATER_EQUAL when passed a \'min\' key');
  500. $q = BookQuery::create()->filterByPrice(['max' => 12]);
  501. $q1 = BookQuery::create()->add(BookTableMap::COL_PRICE, 12, Criteria::LESS_EQUAL);
  502. $this->assertEquals($q1, $q, 'filterByNumColumn() translates to a Criteria::LESS_EQUAL when passed a \'max\' key');
  503. $q = BookQuery::create()->filterByPrice(['min' => 10, 'max' => 12]);
  504. $q1 = BookQuery::create()
  505. ->add(BookTableMap::COL_PRICE, 10, Criteria::GREATER_EQUAL)
  506. ->addAnd(BookTableMap::COL_PRICE, 12, Criteria::LESS_EQUAL);
  507. $this->assertEquals($q1, $q, 'filterByNumColumn() translates to a between when passed both a \'min\' and a \'max\' key');
  508. }
  509. /**
  510. * @return void
  511. */
  512. public function testFilterByTimestamp()
  513. {
  514. $q = BookstoreEmployeeAccountQuery::create()->filterByCreated(12);
  515. $q1 = BookstoreEmployeeAccountQuery::create()->add(BookstoreEmployeeAccountTableMap::COL_CREATED, 12, Criteria::EQUAL);
  516. $this->assertEquals($q1, $q, 'filterByDateColumn() translates to a Criteria::EQUAL by default');
  517. $q = BookstoreEmployeeAccountQuery::create()->filterByCreated(12, Criteria::NOT_EQUAL);
  518. $q1 = BookstoreEmployeeAccountQuery::create()->add(BookstoreEmployeeAccountTableMap::COL_CREATED, 12, Criteria::NOT_EQUAL);
  519. $this->assertEquals($q1, $q, 'filterByDateColumn() accepts an optional comparison operator');
  520. $q = BookstoreEmployeeAccountQuery::create()->setModelAlias('b', true)->filterByCreated(12);
  521. $q1 = BookstoreEmployeeAccountQuery::create()->setModelAlias('b', true)->add('b.created', 12, Criteria::EQUAL);
  522. $this->assertEquals($q1, $q, 'filterByDateColumn() uses true table alias if set');
  523. $q = BookstoreEmployeeAccountQuery::create()->filterByCreated(['min' => 10]);
  524. $q1 = BookstoreEmployeeAccountQuery::create()->add(BookstoreEmployeeAccountTableMap::COL_CREATED, 10, Criteria::GREATER_EQUAL);
  525. $this->assertEquals($q1, $q, 'filterByDateColumn() translates to a Criteria::GREATER_EQUAL when passed a \'min\' key');
  526. $q = BookstoreEmployeeAccountQuery::create()->filterByCreated(['max' => 12]);
  527. $q1 = BookstoreEmployeeAccountQuery::create()->add(BookstoreEmployeeAccountTableMap::COL_CREATED, 12, Criteria::LESS_EQUAL);
  528. $this->assertEquals($q1, $q, 'filterByDateColumn() translates to a Criteria::LESS_EQUAL when passed a \'max\' key');
  529. $q = BookstoreEmployeeAccountQuery::create()->filterByCreated(['min' => 10, 'max' => 12]);
  530. $q1 = BookstoreEmployeeAccountQuery::create()
  531. ->add(BookstoreEmployeeAccountTableMap::COL_CREATED, 10, Criteria::GREATER_EQUAL)
  532. ->addAnd(BookstoreEmployeeAccountTableMap::COL_CREATED, 12, Criteria::LESS_EQUAL);
  533. $this->assertEquals($q1, $q, 'filterByDateColumn() translates to a between when passed both a \'min\' and a \'max\' key');
  534. }
  535. /**
  536. * @return void
  537. */
  538. public function testFilterByString()
  539. {
  540. $q = BookQuery::create()->filterByTitle('foo');
  541. $q1 = BookQuery::create()->add(BookTableMap::COL_TITLE, 'foo', Criteria::EQUAL);
  542. $this->assertEquals($q1, $q, 'filterByStringColumn() translates to a Criteria::EQUAL by default');
  543. $q = BookQuery::create()->filterByTitle('foo', Criteria::NOT_EQUAL);
  544. $q1 = BookQuery::create()->add(BookTableMap::COL_TITLE, 'foo', Criteria::NOT_EQUAL);
  545. $this->assertEquals($q1, $q, 'filterByStringColumn() accepts an optional comparison operator');
  546. $q = BookQuery::create()->setModelAlias('b', true)->filterByTitle('foo');
  547. $q1 = BookQuery::create()->setModelAlias('b', true)->add('b.title', 'foo', Criteria::EQUAL);
  548. $this->assertEquals($q1, $q, 'filterByStringColumn() uses true table alias if set');
  549. $q = BookQuery::create()->filterByTitle(['foo', 'bar']);
  550. $q1 = BookQuery::create()->add(BookTableMap::COL_TITLE, ['foo', 'bar'], Criteria::IN);
  551. $this->assertEquals($q1, $q, 'filterByStringColumn() translates to a Criteria::IN when passed an array');
  552. $q = BookQuery::create()->filterByTitle(['foo', 'bar'], Criteria::NOT_IN);
  553. $q1 = BookQuery::create()->add(BookTableMap::COL_TITLE, ['foo', 'bar'], Criteria::NOT_IN);
  554. $this->assertEquals($q1, $q, 'filterByStringColumn() accepts a comparison when passed an array');
  555. $q = BookQuery::create()->filterByTitle('foo%', Criteria::LIKE);
  556. $q1 = BookQuery::create()->add(BookTableMap::COL_TITLE, 'foo%', Criteria::LIKE);
  557. $this->assertEquals($q1, $q, 'filterByStringColumn() translates to a Criteria::LIKE when passed a string with a % wildcard');
  558. $q = BookQuery::create()->filterByTitle('foo%', Criteria::NOT_LIKE);
  559. $q1 = BookQuery::create()->add(BookTableMap::COL_TITLE, 'foo%', Criteria::NOT_LIKE);
  560. $this->assertEquals($q1, $q, 'filterByStringColumn() accepts a comparison when passed a string with a % wildcard');
  561. $q = BookQuery::create()->filterByTitle('foo%', Criteria::EQUAL);
  562. $q1 = BookQuery::create()->add(BookTableMap::COL_TITLE, 'foo%', Criteria::EQUAL);
  563. $this->assertEquals($q1, $q, 'filterByStringColumn() accepts a comparison when passed a string with a % wildcard');
  564. }
  565. /**
  566. * @return void
  567. */
  568. public function testFilterByBoolean()
  569. {
  570. $q = ReviewQuery::create()->filterByRecommended(true);
  571. $q1 = ReviewQuery::create()->add(ReviewTableMap::COL_RECOMMENDED, true, Criteria::EQUAL);
  572. $this->assertEquals($q1, $q, 'filterByBooleanColumn() translates to a Criteria::EQUAL by default');
  573. $q = ReviewQuery::create()->filterByRecommended(true, Criteria::NOT_EQUAL);
  574. $q1 = ReviewQuery::create()->add(ReviewTableMap::COL_RECOMMENDED, true, Criteria::NOT_EQUAL);
  575. $this->assertEquals($q1, $q, 'filterByBooleanColumn() accepts an optional comparison operator');
  576. $q = ReviewQuery::create()->filterByRecommended(false);
  577. $q1 = ReviewQuery::create()->add(ReviewTableMap::COL_RECOMMENDED, false, Criteria::EQUAL);
  578. $this->assertEquals($q1, $q, 'filterByBooleanColumn() translates to a Criteria::EQUAL by default');
  579. $q = ReviewQuery::create()->setModelAlias('b', true)->filterByRecommended(true);
  580. $q1 = ReviewQuery::create()->setModelAlias('b', true)->add('b.recommended', true, Criteria::EQUAL);
  581. $this->assertEquals($q1, $q, 'filterByBooleanColumn() uses true table alias if set');
  582. $q = ReviewQuery::create()->filterByRecommended('true');
  583. $q1 = ReviewQuery::create()->add(ReviewTableMap::COL_RECOMMENDED, true, Criteria::EQUAL);
  584. $this->assertEquals($q1, $q, 'filterByBooleanColumn() translates to a = true when passed a true string');
  585. $q = ReviewQuery::create()->filterByRecommended('yes');
  586. $q1 = ReviewQuery::create()->add(ReviewTableMap::COL_RECOMMENDED, true, Criteria::EQUAL);
  587. $this->assertEquals($q1, $q, 'filterByBooleanColumn() translates to a = true when passed a true string');
  588. $q = ReviewQuery::create()->filterByRecommended('1');
  589. $q1 = ReviewQuery::create()->add(ReviewTableMap::COL_RECOMMENDED, true, Criteria::EQUAL);
  590. $this->assertEquals($q1, $q, 'filterByBooleanColumn() translates to a = true when passed a true string');
  591. $q = ReviewQuery::create()->filterByRecommended('false');
  592. $q1 = ReviewQuery::create()->add(ReviewTableMap::COL_RECOMMENDED, false, Criteria::EQUAL);
  593. $this->assertEquals($q1, $q, 'filterByBooleanColumn() translates to a = false when passed a false string');
  594. $q = ReviewQuery::create()->filterByRecommended('no');
  595. $q1 = ReviewQuery::create()->add(ReviewTableMap::COL_RECOMMENDED, false, Criteria::EQUAL);
  596. $this->assertEquals($q1, $q, 'filterByBooleanColumn() translates to a = false when passed a false string');
  597. $q = ReviewQuery::create()->filterByRecommended('0');
  598. $q1 = ReviewQuery::create()->add(ReviewTableMap::COL_RECOMMENDED, false, Criteria::EQUAL);
  599. $this->assertEquals($q1, $q, 'filterByBooleanColumn() translates to a = false when passed a false string');
  600. $q = ReviewQuery::create()->filterByRecommended('');
  601. $q1 = ReviewQuery::create()->add(ReviewTableMap::COL_RECOMMENDED, false, Criteria::EQUAL);
  602. $this->assertEquals($q1, $q, 'filterByBooleanColumn() translates to a = false when passed an empty string');
  603. }
  604. /**
  605. * @return void
  606. */
  607. public function testFilterByFk()
  608. {
  609. $this->assertTrue(method_exists('\Propel\Tests\Bookstore\BookQuery', 'filterByAuthor'), 'QueryBuilder adds filterByFk() methods');
  610. $this->assertTrue(method_exists('\Propel\Tests\Bookstore\BookQuery', 'filterByPublisher'), 'QueryBuilder adds filterByFk() methods for all fkeys');
  611. $this->assertTrue(method_exists('\Propel\Tests\Bookstore\EssayQuery', 'filterByFirstAuthor'), 'QueryBuilder adds filterByFk() methods for several fkeys on the same table');
  612. $this->assertTrue(method_exists('\Propel\Tests\Bookstore\EssayQuery', 'filterBySecondAuthor'), 'QueryBuilder adds filterByFk() methods for several fkeys on the same table');
  613. }
  614. /**
  615. * @return void
  616. */
  617. public function testFilterByFkSimpleKey()
  618. {
  619. BookstoreDataPopulator::depopulate();
  620. BookstoreDataPopulator::populate();
  621. // prepare the test data
  622. $testBook = BookQuery::create()
  623. ->innerJoin('Book.Author') // just in case there are books with no author
  624. ->findOne();
  625. $testAuthor = $testBook->getAuthor();
  626. $book = BookQuery::create()
  627. ->filterByAuthor($testAuthor)
  628. ->findOne();
  629. $this->assertEquals($testBook, $book, 'Generated query handles filterByFk() methods correctly for simple fkeys');
  630. $q = BookQuery::create()->filterByAuthor($testAuthor);
  631. $q1 = BookQuery::create()->add(BookTableMap::COL_AUTHOR_ID, $testAuthor->getId(), Criteria::EQUAL);
  632. $this->assertEquals($q1, $q, 'filterByFk() translates to a Criteria::EQUAL by default');
  633. $q = BookQuery::create()->filterByAuthor($testAuthor, Criteria::NOT_EQUAL);
  634. $q1 = BookQuery::create()->add(BookTableMap::COL_AUTHOR_ID, $testAuthor->getId(), Criteria::NOT_EQUAL);
  635. $this->assertEquals($q1, $q, 'filterByFk() accepts an optional comparison operator');
  636. }
  637. /**
  638. * @return void
  639. */
  640. public function testFilterByFkCompositeKey()
  641. {
  642. BookstoreDataPopulator::depopulate();
  643. BookstoreDataPopulator::populate();
  644. BookstoreDataPopulator::populateOpinionFavorite();
  645. // prepare the test data
  646. $testOpinion = BookOpinionQuery::create()
  647. ->innerJoin('BookOpinion.ReaderFavorite') // just in case there are books with no author
  648. ->findOne();
  649. $testFavorite = $testOpinion->getReaderFavorite();
  650. $favorite = ReaderFavoriteQuery::create()
  651. ->filterByBookOpinion($testOpinion)
  652. ->findOne();
  653. $this->assertEquals($testFavorite, $favorite, 'Generated query handles filterByFk() methods correctly for composite fkeys');
  654. }
  655. /**
  656. * @return void
  657. */
  658. public function testFilterByFkObjectCollection()
  659. {
  660. BookstoreDataPopulator::depopulate($this->con);
  661. BookstoreDataPopulator::populate($this->con);
  662. $authors = AuthorQuery::create()
  663. ->orderByFirstName()
  664. ->limit(2)
  665. ->find($this->con);
  666. $books = BookQuery::create()
  667. ->filterByAuthor($authors)
  668. ->find($this->con);
  669. $q1 = $this->con->getLastExecutedQuery();
  670. $books = BookQuery::create()
  671. ->add(BookTableMap::COL_AUTHOR_ID, $authors->getPrimaryKeys(), Criteria::IN)
  672. ->find($this->con);
  673. $q2 = $this->con->getLastExecutedQuery();
  674. $this->assertEquals($q2, $q1, 'filterByFk() accepts a collection and results to an IN query');
  675. }
  676. /**
  677. * @return void
  678. */
  679. public function testFilterByRefFk()
  680. {
  681. $this->assertTrue(method_exists('\Propel\Tests\Bookstore\BookQuery', 'filterByReview'), 'QueryBuilder adds filterByRefFk() methods');
  682. $this->assertTrue(method_exists('\Propel\Tests\Bookstore\BookQuery', 'filterByMedia'), 'QueryBuilder adds filterByRefFk() methods for all fkeys');
  683. $this->assertTrue(method_exists('\Propel\Tests\Bookstore\AuthorQuery', 'filterByEssayRelatedByFirstAuthorId'), 'QueryBuilder adds filterByRefFk() methods for several fkeys on the same table');
  684. $this->assertTrue(method_exists('\Propel\Tests\Bookstore\AuthorQuery', 'filterByEssayRelatedBySecondAuthorId'), 'QueryBuilder adds filterByRefFk() methods for several fkeys on the same table');
  685. }
  686. /**
  687. * @return void
  688. */
  689. public function testFilterByRefFkSimpleKey()
  690. {
  691. BookstoreDataPopulator::depopulate();
  692. BookstoreDataPopulator::populate();
  693. // prepare the test data
  694. $testBook = BookQuery::create()
  695. ->innerJoin('Book.Author') // just in case there are books with no author
  696. ->findOne();
  697. $testAuthor = $testBook->getAuthor();
  698. $author = AuthorQuery::create()
  699. ->filterByBook($testBook)
  700. ->findOne();
  701. $this->assertEquals($testAuthor, $author, 'Generated query handles filterByRefFk() methods correctly for simple fkeys');
  702. $q = AuthorQuery::create()->filterByBook($testBook);
  703. $q1 = AuthorQuery::create()->add(AuthorTableMap::COL_ID, $testBook->getAuthorId(), Criteria::EQUAL);
  704. $this->assertEquals($q1, $q, 'filterByRefFk() translates to a Criteria::EQUAL by default');
  705. $q = AuthorQuery::create()->filterByBook($testBook, Criteria::NOT_EQUAL);
  706. $q1 = AuthorQuery::create()->add(AuthorTableMap::COL_ID, $testBook->getAuthorId(), Criteria::NOT_EQUAL);
  707. $this->assertEquals($q1, $q, 'filterByRefFk() accepts an optional comparison operator');
  708. }
  709. /**
  710. * @return void
  711. */
  712. public function testFilterByRelationNameCompositePk()
  713. {
  714. BookstoreDataPopulator::depopulate();
  715. BookstoreDataPopulator::populate();
  716. $testLabel = RecordLabelQuery::create()
  717. ->findOne($this->con);
  718. $testRelease = ReleasePoolQuery::create()
  719. ->addJoin(ReleasePoolTableMap::COL_RECORD_LABEL_ID, RecordLabelTableMap::COL_ID)
  720. ->filterByRecordLabel($testLabel)
  721. ->find($this->con);
  722. $q1 = $this->con->getLastExecutedQuery();
  723. $releasePool = ReleasePoolQuery::create()
  724. ->addJoin(ReleasePoolTableMap::COL_RECORD_LABEL_ID, RecordLabelTableMap::COL_ID)
  725. ->add(ReleasePoolTableMap::COL_RECORD_LABEL_ID, $testLabel->getId(), Criteria::EQUAL)
  726. ->add(ReleasePoolTableMap::COL_RECORD_LABEL_ABBR, $testLabel->getAbbr(), Criteria::EQUAL)
  727. ->find($this->con);
  728. $q2 = $this->con->getLastExecutedQuery();
  729. $this->assertEquals($q2, $q1, 'Generated query handles filterByRefFk() methods correctly for composite fkeys');
  730. $this->assertEquals($releasePool, $testRelease);
  731. }
  732. /**
  733. * @return void
  734. */
  735. public function testFilterUsingCollectionByRelationNameCompositePk()
  736. {
  737. $this->expectException(PropelException::class);
  738. BookstoreDataPopulator::depopulate();
  739. BookstoreDataPopulator::populate();
  740. $testLabel = RecordLabelQuery::create()
  741. ->limit(2)
  742. ->find($this->con);
  743. ReleasePoolQuery::create()
  744. ->addJoin(ReleasePoolTableMap::COL_RECORD_LABEL_ID, RecordLabelTableMap::COL_ID)
  745. ->filterByRecordLabel($testLabel)
  746. ->find($this->con);
  747. $this->fail('Expected PropelException : filterBy{RelationName}() only accepts arguments of type {RelationName}');
  748. }
  749. /**
  750. * @return void
  751. */
  752. public function testFilterByRefNonPrimaryFKey()
  753. {
  754. BookstoreDataPopulator::depopulate();
  755. BookstoreDataPopulator::populate();
  756. $testBookstoreEmployeeAccount = BookstoreEmployeeAccountQuery::create()
  757. ->findOne();
  758. $testAccAuditLog = $testBookstoreEmployeeAccount->getAcctAuditLogs();
  759. $result = AcctAuditLogQuery::create()
  760. ->addJoin(AcctAuditLogTableMap::COL_UID, BookstoreEmployeeAccountTableMap::COL_LOGIN)
  761. ->filterByBookstoreEmployeeAccount($testBookstoreEmployeeAccount)
  762. ->find($this->con);
  763. $this->assertEquals($testAccAuditLog, $result, 'Generated query handles filterByRefFk() methods correctly for non primary fkeys');
  764. }
  765. /**
  766. * @return void
  767. */
  768. public function testFilterByRefFkCompositeKey()
  769. {
  770. BookstoreDataPopulator::depopulate();
  771. BookstoreDataPopulator::populate();
  772. BookstoreDataPopulator::populateOpinionFavorite();
  773. // prepare the test data
  774. $testOpinion = BookOpinionQuery::create()
  775. ->innerJoin('BookOpinion.ReaderFavorite') // just in case there are books with no author
  776. ->findOne();
  777. $testFavorite = $testOpinion->getReaderFavorite();
  778. $opinion = BookOpinionQuery::create()
  779. ->filterByReaderFavorite($testFavorite)
  780. ->findOne();
  781. $this->assertEquals($testOpinion, $opinion, 'Generated query handles filterByRefFk() methods correctly for composite fkeys');
  782. }
  783. /**
  784. * @return void
  785. */
  786. public function testFilterByRefFkObjectCollection()
  787. {
  788. BookstoreDataPopulator::depopulate($this->con);
  789. BookstoreDataPopulator::populate($this->con);
  790. $books = BookQuery::create()
  791. ->orderByTitle()
  792. ->limit(2)
  793. ->find($this->con);
  794. $authors = AuthorQuery::create()
  795. ->filterByBook($books)
  796. ->find($this->con);
  797. $q1 = $this->con->getLastExecutedQuery();
  798. $authors = AuthorQuery::create()
  799. ->addJoin(AuthorTableMap::COL_ID, BookTableMap::COL_AUTHOR_ID, Criteria::LEFT_JOIN)
  800. ->add(BookTableMap::COL_ID, $books->getPrimaryKeys(), Criteria::IN)
  801. ->find($this->con);
  802. $q2 = $this->con->getLastExecutedQuery();
  803. $this->assertEquals($q2, $q1, 'filterByRefFk() accepts a collection and results to an IN query in the joined table');
  804. }
  805. /**
  806. * @return void
  807. */
  808. public function testFilterByCrossFK()
  809. {
  810. $this->assertTrue(method_exists('\Propel\Tests\Bookstore\BookQuery', 'filterByBookClubList'), 'Generated query handles filterByCrossRefFK() for many-to-many relationships');
  811. $this->assertFalse(method_exists('\Propel\Tests\Bookstore\BookQuery', 'filterByBook'), 'Generated query handles filterByCrossRefFK() for many-to-many relationships');
  812. BookstoreDataPopulator::depopulate();
  813. BookstoreDataPopulator::populate();
  814. $blc1 = BookClubListQuery::create()->findOneByGroupLeader('Crazyleggs');
  815. $nbBooks = BookQuery::create()
  816. ->filterByBookClubList($blc1)
  817. ->count();
  818. $this->assertEquals(2, $nbBooks, 'Generated query handles filterByCrossRefFK() methods correctly');
  819. }
  820. /**
  821. * @return void
  822. */
  823. public function testJoinFk()
  824. {
  825. $q = BookQuery::create()
  826. ->joinAuthor();
  827. $q1 = BookQuery::create()
  828. ->join('Book.Author', Criteria::LEFT_JOIN);
  829. $this->assertTrue($q->equals($q1), 'joinFk() translates to a left join on non-required columns');
  830. $q = BookSummaryQuery::create()
  831. ->joinSummarizedBook();
  832. $q1 = BookSummaryQuery::create()
  833. ->join('BookSummary.SummarizedBook', Criteria::INNER_JOIN);
  834. $this->assertTrue($q->equals($q1), 'joinFk() translates to an inner join on required columns');
  835. $q = BookQuery::create()
  836. ->joinAuthor('a');
  837. $q1 = BookQuery::create()
  838. ->join('Book.Author a', Criteria::LEFT_JOIN);
  839. $this->assertTrue($q->equals($q1), 'joinFk() accepts a relation alias as first parameter');
  840. $q = BookQuery::create()
  841. ->joinAuthor('', Criteria::INNER_JOIN);
  842. $q1 = BookQuery::create()
  843. ->join('Book.Author', Criteria::INNER_JOIN);
  844. $this->assertTrue($q->equals($q1), 'joinFk() accepts a join type as second parameter');
  845. $q = EssayQuery::create()
  846. ->innerJoinSecondAuthor();
  847. $q1 = EssayQuery::create()
  848. ->join('Essay.SecondAuthor', 'INNER JOIN');
  849. $this->assertTrue($q->equals($q1), 'joinFk() translates to a "INNER JOIN" when this is defined as defaultJoin in the schema');
  850. }
  851. /**
  852. * @return void
  853. */
  854. public function testJoinFkAlias()
  855. {
  856. $q = BookQuery::create('b')
  857. ->joinAuthor('a');
  858. $q1 = BookQuery::create('b')
  859. ->join('b.Author a', Criteria::LEFT_JOIN);
  860. $this->assertTrue($q->equals($q1), 'joinFk() works fine with table aliases');
  861. $q = BookQuery::create()
  862. ->setModelAlias('b', true)
  863. ->joinAuthor('a');
  864. $q1 = BookQuery::create()
  865. ->setModelAlias('b', true)
  866. ->join('b.Author a', Criteria::LEFT_JOIN);
  867. $this->assertTrue($q->equals($q1), 'joinFk() works fine with true table aliases');
  868. }
  869. /**
  870. * @return void
  871. */
  872. public function testJoinRefFk()
  873. {
  874. $q = AuthorQuery::create()
  875. ->joinBook();
  876. $q1 = AuthorQuery::create()
  877. ->join('Author.Book', Criteria::LEFT_JOIN);
  878. $this->assertTrue($q->equals($q1), 'joinRefFk() translates to a left join on non-required columns');
  879. $q = BookQuery::create()
  880. ->joinBookSummary();
  881. $q1 = BookQuery::create()
  882. ->join('Book.BookSummary', Criteria::INNER_JOIN);
  883. $this->assertTrue($q->equals($q1), 'joinRefFk() translates to an inner join on required columns');
  884. $q = AuthorQuery::create()
  885. ->joinBook('b');
  886. $q1 = AuthorQuery::create()
  887. ->join('Author.Book b', Criteria::LEFT_JOIN);
  888. $this->assertTrue($q->equals($q1), 'joinRefFk() accepts a relation alias as first parameter');
  889. $q = AuthorQuery::create()
  890. ->joinBook('', Criteria::INNER_JOIN);
  891. $q1 = AuthorQuery::create()
  892. ->join('Author.Book', Criteria::INNER_JOIN);
  893. $this->assertTrue($q->equals($q1), 'joinRefFk() accepts a join type as second parameter');
  894. $q = AuthorQuery::create()
  895. ->joinEssayRelatedBySecondAuthorId();
  896. $q1 = AuthorQuery::create()
  897. ->join('Author.EssayRelatedBySecondAuthorId', Criteria::INNER_JOIN);
  898. $this->assertTrue($q->equals($q1), 'joinRefFk() translates to a "INNER JOIN" when this is defined as defaultJoin in the schema');
  899. }
  900. /**
  901. * @return void
  902. */
  903. public function testUseFkQuerySimple()
  904. {
  905. $q = BookQuery::create()
  906. ->useAuthorQuery()
  907. ->filterByFirstName('Leo')
  908. ->endUse();
  909. $q1 = BookQuery::create()
  910. ->join('Book.Author', Criteria::LEFT_JOIN)
  911. ->add(AuthorTableMap::COL_FIRST_NAME, 'Leo', Criteria::EQUAL);
  912. $this->assertTrue($q->equals($q1), 'useFkQuery() translates to a condition on a left join on non-required columns');
  913. $q = BookSummaryQuery::create()
  914. ->useSummarizedBookQuery()
  915. ->filterByTitle('War And Peace')
  916. ->endUse();
  917. $q1 = BookSummaryQuery::create()
  918. ->join('BookSummary.SummarizedBook', Criteria::INNER_JOIN)
  919. ->add(BookTableMap::COL_TITLE, 'War And Peace', Criteria::EQUAL);
  920. $this->assertTrue($q->equals($q1), 'useFkQuery() translates to a condition on an inner join on required columns');
  921. }
  922. /**
  923. * @return void
  924. */
  925. public function testUseFkQueryWith()
  926. {
  927. $q = BookQuery::create()
  928. ->withAuthorQuery(
  929. function (AuthorQuery $q) {
  930. return $q->filterByFirstName('Leo');
  931. }
  932. );
  933. $q1 = BookQuery::create()
  934. ->useAuthorQuery()
  935. ->filterByFirstName('Leo')
  936. ->endUse();
  937. $this->assertTrue($q->equals($q1), 'useFkQuery() translates to a condition on a left join on non-required columns');
  938. $q = BookSummaryQuery::create()
  939. ->withSummarizedBookQuery(
  940. function (BookQuery $q) {
  941. return $q->filterByTitle('War and Peace');
  942. }
  943. );
  944. $q1 = BookSummaryQuery::create()
  945. ->useSummarizedBookQuery()
  946. ->filterByTitle('War and Peace')
  947. ->endUse();
  948. $this->assertEquals($q1, $q, 'useFkQuery() translates to a condition on an inner join on required columns');
  949. }
  950. /**
  951. * @return void
  952. */
  953. public function testUseFkQueryJoinType()
  954. {
  955. $q = BookQuery::create()
  956. ->useAuthorQuery(null, Criteria::LEFT_JOIN)
  957. ->filterByFirstName('Leo')
  958. ->endUse();
  959. $q1 = BookQuery::create()
  960. ->join('Book.Author', Criteria::LEFT_JOIN)
  961. ->add(AuthorTableMap::COL_FIRST_NAME, 'Leo', Criteria::EQUAL);
  962. $this->assertTrue($q->equals($q1), 'useFkQuery() accepts a join type as second parameter');
  963. }
  964. /**
  965. * @return void
  966. */
  967. public function testUseFkQueryAlias()
  968. {
  969. $q = BookQuery::create()
  970. ->useAuthorQuery('a')
  971. ->filterByFirstName('Leo')
  972. ->endUse();
  973. $join = new ModelJoin();
  974. $join->setJoinType(Criteria::LEFT_JOIN);
  975. $join->setTableMap(AuthorTableMap::getTableMap());
  976. $join->setRelationMap(BookTableMap::getTableMap()->getRelation('Author'), null, 'a');
  977. $join->setRelationAlias('a');
  978. $q1 = BookQuery::create()
  979. ->addAlias('a', AuthorTableMap::TABLE_NAME)
  980. ->addJoinObject($join, 'a')
  981. ->add('a.first_name', 'Leo', Criteria::EQUAL);
  982. $this->assertTrue($q->equals($q1), 'useFkQuery() uses the first argument as a table alias');
  983. }
  984. /**
  985. * @return void
  986. */
  987. public function testUseFkQueryMixed()
  988. {
  989. $q = BookQuery::create()
  990. ->useAuthorQuery()
  991. ->filterByFirstName('Leo')
  992. ->endUse()
  993. ->filterByTitle('War And Peace');
  994. $q1 = BookQuery::create()
  995. ->join('Book.Author', Criteria::LEFT_JOIN)
  996. ->add(AuthorTableMap::COL_FIRST_NAME, 'Leo', Criteria::EQUAL)
  997. ->add(BookTableMap::COL_TITLE, 'War And Peace', Criteria::EQUAL);
  998. $this->assertTrue($q->equals($q1), 'useFkQuery() allows combining conditions on main and related query');
  999. }
  1000. /**
  1001. * @return void
  1002. */
  1003. public function testUseFkQueryTwice()
  1004. {
  1005. $q = BookQuery::create()
  1006. ->useAuthorQuery()
  1007. ->filterByFirstName('Leo')
  1008. ->endUse()
  1009. ->useAuthorQuery()
  1010. ->filterByLastName('Tolstoi')
  1011. ->endUse();
  1012. $q1 = BookQuery::create()
  1013. ->join('Book.Author', Criteria::LEFT_JOIN)
  1014. ->add(AuthorTableMap::COL_FIRST_NAME, 'Leo', Criteria::EQUAL)
  1015. ->add(AuthorTableMap::COL_LAST_NAME, 'Tolstoi', Criteria::EQUAL);
  1016. $this->assertTrue($q->equals($q1), 'useFkQuery() called twice on the same relation does not create two joins');
  1017. }
  1018. /**
  1019. * @return void
  1020. */
  1021. public function testUseFkQueryTwiceTwoAliases()
  1022. {
  1023. $q = BookQuery::create()
  1024. ->useAuthorQuery('a')
  1025. ->filterByFirstName('Leo')
  1026. ->endUse()
  1027. ->useAuthorQuery('b')
  1028. ->filterByLastName('Tolstoi')
  1029. ->endUse();
  1030. $join1 = new ModelJoin();
  1031. $join1->setJoinType(Criteria::LEFT_JOIN);
  1032. $join1->setTableMap(AuthorTableMap::getTableMap());
  1033. $join1->setRelationMap(BookTableMap::getTableMap()->getRelation('Author'), null, 'a');
  1034. $join1->setRelationAlias('a');
  1035. $join2 = new ModelJoin();
  1036. $join2->setJoinType(Criteria::LEFT_JOIN);
  1037. $join2->setTableMap(AuthorTableMap::getTableMap());
  1038. $join2->setRelationMap(BookTableMap::getTableMap()->getRelation('Author'), null, 'b');
  1039. $join2->setRelationAlias('b');
  1040. $q1 = BookQuery::create()
  1041. ->addAlias('a', AuthorTableMap::TABLE_NAME)
  1042. ->addJoinObject($join1, 'a')
  1043. ->add('a.first_name', 'Leo', Criteria::EQUAL)
  1044. ->addAlias('b', AuthorTableMap::TABLE_NAME)
  1045. ->addJoinObject($join2, 'b')
  1046. ->add('b.last_name', 'Tolstoi', Criteria::EQUAL);
  1047. $this->assertTrue($q->equals($q1), 'useFkQuery() called twice on the same relation with two aliases creates two joins');
  1048. }
  1049. /**
  1050. * @return void
  1051. */
  1052. public function testUseFkQueryNested()
  1053. {
  1054. $q = ReviewQuery::create()
  1055. ->useBookQuery()
  1056. ->useAuthorQuery()
  1057. ->filterByFirstName('Leo')
  1058. ->endUse()
  1059. ->endUse();
  1060. $q1 = ReviewQuery::create()
  1061. ->join('Review.Book', Criteria::LEFT_JOIN)
  1062. ->join('Book.Author', Criteria::LEFT_JOIN)
  1063. ->add(AuthorTableMap::COL_FIRST_NAME, 'Leo', Criteria::EQUAL);
  1064. // embedded queries create joins that keep a relation to the parent
  1065. // as this is not testable, we need to use another testing technique
  1066. $params = [];
  1067. $result = $q->createSelectSql($params);
  1068. $expectedParams = [];
  1069. $expectedResult = $q1->createSelectSql($expectedParams);
  1070. $this->assertEquals($expectedParams, $params, 'useFkQuery() called nested creates two joins');
  1071. $this->assertEquals($expectedResult, $result, 'useFkQuery() called nested creates two joins');
  1072. }
  1073. /**
  1074. * @return void
  1075. */
  1076. public function testUseFkQueryTwoRelations()
  1077. {
  1078. $q = BookQuery::create()
  1079. ->useAuthorQuery()
  1080. ->filterByFirstName('Leo')
  1081. ->endUse()
  1082. ->usePublisherQuery()
  1083. ->filterByName('Penguin')
  1084. ->endUse();
  1085. $q1 = BookQuery::create()
  1086. ->join('\Propel\Tests\Bookstore\Book.Author', Criteria::LEFT_JOIN)
  1087. ->add(AuthorTableMap::COL_FIRST_NAME, 'Leo', Criteria::EQUAL)
  1088. ->join('\Propel\Tests\Bookstore\Book.Publisher', Criteria::LEFT_JOIN)
  1089. ->add(PublisherTableMap::COL_NAME, 'Penguin', Criteria::EQUAL);
  1090. $this->assertTrue($q->equals($q1), 'useFkQuery() called twice on two relations creates two joins');
  1091. }
  1092. /**
  1093. * @return void
  1094. */
  1095. public function testUseFkQueryNoAliasThenWith()
  1096. {
  1097. $con = Propel::getServiceContainer()->getReadConnection(BookTableMap::DATABASE_NAME);
  1098. $books = BookQuery::create()
  1099. ->useAuthorQuery()
  1100. ->filterByFirstName('Leo')
  1101. ->endUse()
  1102. ->with('Author')
  1103. ->find($con);
  1104. $q1 = $con->getLastExecutedQuery();
  1105. $books = BookQuery::create()
  1106. ->leftJoinWithAuthor()
  1107. ->add(AuthorTableMap::COL_FIRST_NAME, 'Leo', Criteria::EQUAL)
  1108. ->find($con);
  1109. $q2 = $con->getLastExecutedQuery();
  1110. $this->assertEquals($q1, $q2, 'with() can be used after a call to useFkQuery() with no alias');
  1111. }
  1112. /**
  1113. * @return void
  1114. */
  1115. public function testUseRelationExistsQuery()
  1116. {
  1117. $expected = BookQuery::create()
  1118. ->useExistsQuery('Author')
  1119. ->filterByFirstName('Leo')
  1120. ->endUse();
  1121. $actual = BookQuery::create()
  1122. ->useAuthorExistsQuery()
  1123. ->filterByFirstName('Leo')
  1124. ->endUse();
  1125. $this->assertEquals($expected, $actual, 'useExistsQuery() is available and calls correct parent method');
  1126. }
  1127. /**
  1128. * @return void
  1129. */
  1130. public function testUseRelationNotExistsQuery()
  1131. {
  1132. $expected = BookQuery::create()
  1133. ->useExistsQuery('Author', null, null, ExistsCriterion::TYPE_NOT_EXISTS)
  1134. ->filterByFirstName('Leo')
  1135. ->endUse();
  1136. $actual = BookQuery::create()
  1137. ->useAuthorNotExistsQuery()
  1138. ->filterByFirstName('Leo')
  1139. ->endUse();
  1140. $this->assertEquals($expected, $actual, 'useNotExistsQuery() is available and calls correct parent method');
  1141. }
  1142. /**
  1143. * @return void
  1144. */
  1145. public function testUseRelationExistsQueryWithCustomQueryClass()
  1146. {
  1147. $query = BookQuery::create()->useAuthorExistsQuery(null, BookClubListQuery::class, false);
  1148. $this->assertInstanceOf(BookClubListQuery::class, $query, 'useExistsQuery() passes on given query class');
  1149. }
  1150. /**
  1151. * @return void
  1152. */
  1153. public function testUseRelationNotExistsQueryWithCustomQueryClass()
  1154. {
  1155. $query = BookQuery::create()->useAuthorNotExistsQuery(null, BookClubListQuery::class);
  1156. $this->assertInstanceOf(BookClubListQuery::class, $query, 'useNotExistsQuery() passes on given query class');
  1157. }
  1158. /**
  1159. * @return void
  1160. */
  1161. public function testPrune()
  1162. {
  1163. $q = BookQuery::create()->prune();
  1164. $this->assertTrue($q instanceof BookQuery, 'prune() returns the current Query object');
  1165. }
  1166. /**
  1167. * @return void
  1168. */
  1169. public function testPruneSimpleKey()
  1170. {
  1171. BookstoreDataPopulator::depopulate();
  1172. BookstoreDataPopulator::populate();
  1173. $nbBooks = BookQuery::create()->prune()->count();
  1174. $this->assertEquals(4, $nbBooks, 'prune() does nothing when passed a null object');
  1175. $testBook = BookQuery::create()->findOne();
  1176. $nbBooks = BookQuery::create()->prune($testBook)->count();
  1177. $this->assertEquals(3, $nbBooks, 'prune() removes an object from the result');
  1178. }
  1179. /**
  1180. * @return void
  1181. */
  1182. public function testPruneCompositeKey()
  1183. {
  1184. BookstoreDataPopulator::depopulate();
  1185. BookstoreDataPopulator::populate();
  1186. // save all books to make sure related objects are also saved - BookstoreDataPopulator keeps some unsaved
  1187. $c = new ModelCriteria('bookstore', '\Propel\Tests\Bookstore\Book');
  1188. $books = $c->find();
  1189. foreach ($books as $book) {
  1190. $book->save();
  1191. }
  1192. BookTableMap::clearInstancePool();
  1193. $nbBookListRel = BookListRelQuery::create()->prune()->count();
  1194. $this->assertEquals(2, $nbBookListRel, 'prune() does nothing when passed a null object');
  1195. $testBookListRel = BookListRelQuery::create()->findOne();
  1196. $nbBookListRel = BookListRelQuery::create()->prune($testBookListRel)->count();
  1197. $this->assertEquals(1, $nbBookListRel, 'prune() removes an object from the result');
  1198. }
  1199. /**
  1200. * @return void
  1201. */
  1202. public function testFindPkSimpleThrowsExceptionWhenTableIsAbstract(): void
  1203. {
  1204. $databaseXml = '
  1205. <database>
  1206. <table name="my_table" abstract="true">
  1207. <column name="id" type="integer" primaryKey="true"/>
  1208. </table>
  1209. </database>
  1210. ';
  1211. $script = TestableQueryBuilder::forTableFromXml($databaseXml, 'my_table')->buildScript('addFindPkSimple');
  1212. $throwStatement = 'throw new PropelException(\'MyTable is declared abstract, you cannot query it.\');';
  1213. $msg = 'Query class for abstract table should throw exception when calling findPkSimple()';
  1214. $this->assertStringContainsString($throwStatement, $script, $msg);
  1215. }
  1216. /**
  1217. * @return void
  1218. */
  1219. public function testFindPkSimpleThrowsNoExceptionWhenTableIsAbstractWithInheritance(): void
  1220. {
  1221. $databaseXml = '
  1222. <database>
  1223. <table name="my_table" abstract="true">
  1224. <column name="id" type="integer" primaryKey="true"/>
  1225. <column name="class_key" type="integer" inheritance="single">
  1226. <inheritance key="1" class="class1"/>
  1227. <inheritance key="2" class="class2" extends="my_table"/>
  1228. </column>
  1229. </table>
  1230. </database>
  1231. ';
  1232. $script = TestableQueryBuilder::forTableFromXml($databaseXml, 'my_table')->buildScript('addFindPkSimple');
  1233. $throwStatement = 'throw new PropelException(\'MyTable is declared abstract, you cannot query it.\');';
  1234. $msg = 'Query class for abstract table should not have abstract findPkSimple() method if table uses inheritance';
  1235. $this->assertStringNotContainsString($throwStatement, $script, $msg);
  1236. }
  1237. }