PageRenderTime 30ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 1ms

/test/testsuite/runtime/query/ModelCriteriaTest.php

https://github.com/1989gaurav/Propel
PHP | 1249 lines | 1061 code | 149 blank | 39 comment | 1 complexity | 97c3be789444437f8f6eaea6fb385006 MD5 | raw file
  1. <?php
  2. /**
  3. * 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. * @license MIT License
  8. */
  9. require_once dirname(__FILE__) . '/../../../tools/helpers/bookstore/BookstoreTestBase.php';
  10. require_once dirname(__FILE__) . '/../../../tools/helpers/bookstore/BookstoreDataPopulator.php';
  11. /**
  12. * Test class for ModelCriteria.
  13. *
  14. * @author Francois Zaninotto
  15. * @version $Id$
  16. * @package runtime.query
  17. */
  18. class ModelCriteriaTest extends BookstoreTestBase
  19. {
  20. protected function assertCriteriaTranslation($criteria, $expectedSql, $expectedParams, $message = '')
  21. {
  22. $params = array();
  23. $result = BasePeer::createSelectSql($criteria, $params);
  24. $this->assertEquals($expectedSql, $result, $message);
  25. $this->assertEquals($expectedParams, $params, $message);
  26. }
  27. public function testGetModelName()
  28. {
  29. $c = new ModelCriteria('bookstore', 'Book');
  30. $this->assertEquals('Book', $c->getModelName(), 'getModelName() returns the name of the class associated to the model class');
  31. }
  32. public function testGetModelPeerName()
  33. {
  34. $c = new ModelCriteria('bookstore', 'Book');
  35. $this->assertEquals('BookPeer', $c->getModelPeerName(), 'getModelPeerName() returns the name of the Peer class associated to the model class');
  36. }
  37. public function testFormatter()
  38. {
  39. $c = new ModelCriteria('bookstore', 'Book');
  40. $this->assertTrue($c->getFormatter() instanceof PropelFormatter, 'getFormatter() returns a PropelFormatter instance');
  41. $c = new ModelCriteria('bookstore', 'Book');
  42. $c->setFormatter(ModelCriteria::FORMAT_STATEMENT);
  43. $this->assertTrue($c->getFormatter() instanceof PropelStatementFormatter, 'setFormatter() accepts the name of a PropelFormatter class');
  44. try {
  45. $c->setFormatter('Book');
  46. $this->fail('setFormatter() throws an exception when passed the name of a class not extending PropelFormatter');
  47. } catch(PropelException $e) {
  48. $this->assertTrue(true, 'setFormatter() throws an exception when passed the name of a class not extending PropelFormatter');
  49. }
  50. $c = new ModelCriteria('bookstore', 'Book');
  51. $formatter = new PropelStatementFormatter();
  52. $c->setFormatter($formatter);
  53. $this->assertTrue($c->getFormatter() instanceof PropelStatementFormatter, 'setFormatter() accepts a PropelFormatter instance');
  54. try {
  55. $formatter = new Book();
  56. $c->setFormatter($formatter);
  57. $this->fail('setFormatter() throws an exception when passed an object not extending PropelFormatter');
  58. } catch(PropelException $e) {
  59. $this->assertTrue(true, 'setFormatter() throws an exception when passedan object not extending PropelFormatter');
  60. }
  61. }
  62. public static function conditionsForTestReplaceNames()
  63. {
  64. return array(
  65. array('Book.Title = ?', 'Title', 'book.TITLE = ?'), // basic case
  66. array('Book.Title=?', 'Title', 'book.TITLE=?'), // without spaces
  67. array('Book.Id<= ?', 'Id', 'book.ID<= ?'), // with non-equal comparator
  68. array('Book.AuthorId LIKE ?', 'AuthorId', 'book.AUTHOR_ID LIKE ?'), // with SQL keyword separator
  69. array('(Book.AuthorId) LIKE ?', 'AuthorId', '(book.AUTHOR_ID) LIKE ?'), // with parenthesis
  70. array('(Book.Id*1.5)=1', 'Id', '(book.ID*1.5)=1'), // ignore numbers
  71. // dealing with quotes
  72. array("Book.Id + ' ' + Book.AuthorId", null, "book.ID + ' ' + book.AUTHOR_ID"),
  73. array("'Book.Id' + Book.AuthorId", null, "'Book.Id' + book.AUTHOR_ID"),
  74. array("Book.Id + 'Book.AuthorId'", null, "book.ID + 'Book.AuthorId'"),
  75. array('1=1', null, '1=1'), // with no name
  76. array('', null, '') // with empty string
  77. );
  78. }
  79. /**
  80. * @dataProvider conditionsForTestReplaceNames
  81. */
  82. public function testReplaceNames($origClause, $columnPhpName = false, $modifiedClause)
  83. {
  84. $c = new TestableModelCriteria('bookstore', 'Book');
  85. $this->doTestReplaceNames($c, BookPeer::getTableMap(), $origClause, $columnPhpName = false, $modifiedClause);
  86. }
  87. public function doTestReplaceNames($c, $tableMap, $origClause, $columnPhpName = false, $modifiedClause)
  88. {
  89. $c->replaceNames($origClause);
  90. $columns = $c->replacedColumns;
  91. if ($columnPhpName) {
  92. $this->assertEquals(array($tableMap->getColumnByPhpName($columnPhpName)), $columns);
  93. }
  94. $this->assertEquals($modifiedClause, $origClause);
  95. }
  96. public static function conditionsForTestReplaceMultipleNames()
  97. {
  98. return array(
  99. array('(Book.Id+Book.Id)=1', array('Id', 'Id'), '(book.ID+book.ID)=1'), // match multiple names
  100. array('CONCAT(Book.Title,"Book.Id")= ?', array('Title', 'Id'), 'CONCAT(book.TITLE,"Book.Id")= ?'), // ignore names in strings
  101. array('CONCAT(Book.Title," Book.Id ")= ?', array('Title', 'Id'), 'CONCAT(book.TITLE," Book.Id ")= ?'), // ignore names in strings
  102. array('MATCH (Book.Title,Book.ISBN) AGAINST (?)', array('Title', 'ISBN'), 'MATCH (book.TITLE,book.ISBN) AGAINST (?)'),
  103. );
  104. }
  105. /**
  106. * @dataProvider conditionsForTestReplaceMultipleNames
  107. */
  108. public function testReplaceMultipleNames($origClause, $expectedColumns, $modifiedClause)
  109. {
  110. $c = new TestableModelCriteria('bookstore', 'Book');
  111. $c->replaceNames($origClause);
  112. $foundColumns = $c->replacedColumns;
  113. foreach ($foundColumns as $column) {
  114. $expectedColumn = BookPeer::getTableMap()->getColumnByPhpName(array_shift($expectedColumns));
  115. $this->assertEquals($expectedColumn, $column);
  116. }
  117. $this->assertEquals($modifiedClause, $origClause);
  118. }
  119. public function testTableAlias()
  120. {
  121. $c = new ModelCriteria('bookstore', 'Book');
  122. $c->setModelAlias('b');
  123. $c->where('b.Title = ?', 'foo');
  124. $sql = "SELECT FROM `book` WHERE book.TITLE = :p1";
  125. $params = array(
  126. array('table' => 'book', 'column' => 'TITLE', 'value' => 'foo'),
  127. );
  128. $this->assertCriteriaTranslation($c, $sql, $params, 'setModelAlias() allows the definition of the alias after constrution');
  129. $c = new ModelCriteria('bookstore', 'Book', 'b');
  130. $c->where('b.Title = ?', 'foo');
  131. $sql = "SELECT FROM `book` WHERE book.TITLE = :p1";
  132. $params = array(
  133. array('table' => 'book', 'column' => 'TITLE', 'value' => 'foo'),
  134. );
  135. $this->assertCriteriaTranslation($c, $sql, $params, 'A ModelCriteria accepts a model name with an alias');
  136. }
  137. public function testTrueTableAlias()
  138. {
  139. $c = new ModelCriteria('bookstore', 'Book');
  140. $c->setModelAlias('b', true);
  141. $c->where('b.Title = ?', 'foo');
  142. $c->join('b.Author a');
  143. $c->where('a.FirstName = ?', 'john');
  144. $sql = "SELECT FROM `book` `b` INNER JOIN `author` `a` ON (b.AUTHOR_ID=a.ID) WHERE b.TITLE = :p1 AND a.FIRST_NAME = :p2";
  145. $params = array(
  146. array('table' => 'book', 'column' => 'TITLE', 'value' => 'foo'),
  147. array('table' => 'author', 'column' => 'FIRST_NAME', 'value' => 'john'),
  148. );
  149. $this->assertCriteriaTranslation($c, $sql, $params, 'setModelAlias() allows the definition of a true SQL alias after constrution');
  150. }
  151. public function testCondition()
  152. {
  153. $c = new ModelCriteria('bookstore', 'Book');
  154. $c->condition('cond1', 'Book.Title <> ?', 'foo');
  155. $c->condition('cond2', 'Book.Title like ?', '%bar%');
  156. $c->combine(array('cond1', 'cond2'), 'or');
  157. $sql = "SELECT FROM `book` WHERE (book.TITLE <> :p1 OR book.TITLE like :p2)";
  158. $params = array(
  159. array('table' => 'book', 'column' => 'TITLE', 'value' => 'foo'),
  160. array('table' => 'book', 'column' => 'TITLE', 'value' => '%bar%'),
  161. );
  162. $this->assertCriteriaTranslation($c, $sql, $params, 'condition() can store condition for later combination');
  163. }
  164. public static function conditionsForTestWhere()
  165. {
  166. return array(
  167. array('Book.Title = ?', 'foo', 'book.TITLE = :p1', array(array('table' => 'book', 'column' => 'TITLE', 'value' => 'foo'))),
  168. array('Book.AuthorId = ?', 12, 'book.AUTHOR_ID = :p1', array(array('table' => 'book', 'column' => 'AUTHOR_ID', 'value' => 12))),
  169. array('Book.AuthorId IS NULL', null, 'book.AUTHOR_ID IS NULL', array()),
  170. array('Book.Id BETWEEN ? AND ?', array(3, 4), 'book.ID BETWEEN :p1 AND :p2', array(array('table' => 'book', 'column' => 'ID', 'value' => 3), array('table' => 'book', 'column' => 'ID', 'value' => 4))),
  171. array('Book.Id betWEen ? and ?', array(3, 4), 'book.ID betWEen :p1 and :p2', array(array('table' => 'book', 'column' => 'ID', 'value' => 3), array('table' => 'book', 'column' => 'ID', 'value' => 4))),
  172. array('Book.Id IN ?', array(1, 2, 3), 'book.ID IN (:p1,:p2,:p3)', array(array('table' => 'book', 'column' => 'ID', 'value' => 1), array('table' => 'book', 'column' => 'ID', 'value' => 2), array('table' => 'book', 'column' => 'ID', 'value' => 3))),
  173. array('Book.Id in ?', array(1, 2, 3), 'book.ID in (:p1,:p2,:p3)', array(array('table' => 'book', 'column' => 'ID', 'value' => 1), array('table' => 'book', 'column' => 'ID', 'value' => 2), array('table' => 'book', 'column' => 'ID', 'value' => 3))),
  174. array('Book.Id IN ?', array(), '1<>1', array()),
  175. array('Book.Id not in ?', array(), '1=1', array()),
  176. array('UPPER(Book.Title) = ?', 'foo', 'UPPER(book.TITLE) = :p1', array(array('table' => 'book', 'column' => 'TITLE', 'value' => 'foo'))),
  177. array('MATCH (Book.Title,Book.ISBN) AGAINST (?)', 'foo', 'MATCH (book.TITLE,book.ISBN) AGAINST (:p1)', array(array('table' => 'book', 'column' => 'TITLE', 'value' => 'foo'))),
  178. );
  179. }
  180. /**
  181. * @dataProvider conditionsForTestWhere
  182. */
  183. public function testWhere($clause, $value, $sql, $params)
  184. {
  185. $c = new ModelCriteria('bookstore', 'Book');
  186. $c->where($clause, $value);
  187. $sql = 'SELECT FROM `book` WHERE ' . $sql;
  188. $this->assertCriteriaTranslation($c, $sql, $params, 'where() accepts a string clause');
  189. }
  190. public function testWhereUsesDefaultOperator()
  191. {
  192. $c = new ModelCriteria('bookstore', 'Book');
  193. $c->where('Book.Id = ?', 12);
  194. $c->_or();
  195. $c->where('Book.Title = ?', 'foo');
  196. $sql = 'SELECT FROM `book` WHERE (book.ID = :p1 OR book.TITLE = :p2)';
  197. $params = array(
  198. array('table' => 'book', 'column' => 'ID', 'value' => '12'),
  199. array('table' => 'book', 'column' => 'TITLE', 'value' => 'foo'),
  200. );
  201. $this->assertCriteriaTranslation($c, $sql, $params, 'where() uses the default operator');
  202. }
  203. public function testWhereTwiceSameColumn()
  204. {
  205. $c = new ModelCriteria('bookstore', 'Book');
  206. $c->where('Book.Id IN ?', array(1, 2, 3));
  207. $c->where('Book.Id <> ?', 5);
  208. $params = array(
  209. array('table' => 'book', 'column' => 'ID', 'value' => '1'),
  210. array('table' => 'book', 'column' => 'ID', 'value' => '2'),
  211. array('table' => 'book', 'column' => 'ID', 'value' => '3'),
  212. array('table' => 'book', 'column' => 'ID', 'value' => '5'),
  213. );
  214. $sql = 'SELECT FROM `book` WHERE (book.ID IN (:p1,:p2,:p3) AND book.ID <> :p4)';
  215. $this->assertCriteriaTranslation($c, $sql, $params, 'where() adds clauses on the same column correctly');
  216. }
  217. public function testWhereConditions()
  218. {
  219. $c = new ModelCriteria('bookstore', 'Book');
  220. $c->condition('cond1', 'Book.Title <> ?', 'foo');
  221. $c->condition('cond2', 'Book.Title like ?', '%bar%');
  222. $c->where(array('cond1', 'cond2'));
  223. $sql = "SELECT FROM `book` WHERE (book.TITLE <> :p1 AND book.TITLE like :p2)";
  224. $params = array(
  225. array('table' => 'book', 'column' => 'TITLE', 'value' => 'foo'),
  226. array('table' => 'book', 'column' => 'TITLE', 'value' => '%bar%'),
  227. );
  228. $this->assertCriteriaTranslation($c, $sql, $params, 'where() accepts an array of named conditions');
  229. $c = new ModelCriteria('bookstore', 'Book');
  230. $c->condition('cond1', 'Book.Title <> ?', 'foo');
  231. $c->condition('cond2', 'Book.Title like ?', '%bar%');
  232. $c->where(array('cond1', 'cond2'), Criteria::LOGICAL_OR);
  233. $sql = "SELECT FROM `book` WHERE (book.TITLE <> :p1 OR book.TITLE like :p2)";
  234. $this->assertCriteriaTranslation($c, $sql, $params, 'where() accepts an array of named conditions with operator');
  235. }
  236. public function testWhereNoReplacement()
  237. {
  238. $c = new ModelCriteria('bookstore', 'Book', 'b');
  239. $c->where('b.Title = ?', 'foo');
  240. $c->where('1=1');
  241. $sql = "SELECT FROM `book` WHERE book.TITLE = :p1 AND 1=1";
  242. $params = array(
  243. array('table' => 'book', 'column' => 'TITLE', 'value' => 'foo'),
  244. );
  245. $this->assertCriteriaTranslation($c, $sql, $params, 'where() results in a Criteria::CUSTOM if no column name is matched');
  246. $c = new ModelCriteria('bookstore', 'Book');
  247. try {
  248. $c->where('b.Title = ?', 'foo');
  249. $this->fail('where() throws an exception when it finds a ? but cannot determine a column');
  250. } catch (PropelException $e) {
  251. $this->assertTrue(true, 'where() throws an exception when it finds a ? but cannot determine a column');
  252. }
  253. }
  254. public function testWhereFunction()
  255. {
  256. $c = new ModelCriteria('bookstore', 'Book', 'b');
  257. $c->where('UPPER(b.Title) = ?', 'foo');
  258. $sql = "SELECT FROM `book` WHERE UPPER(book.TITLE) = :p1";
  259. $params = array(
  260. array('table' => 'book', 'column' => 'TITLE', 'value' => 'foo'),
  261. );
  262. $this->assertCriteriaTranslation($c, $sql, $params, 'where() accepts a complex calculation');
  263. }
  264. public function testOrWhere()
  265. {
  266. $c = new ModelCriteria('bookstore', 'Book');
  267. $c->where('Book.Title <> ?', 'foo');
  268. $c->orWhere('Book.Title like ?', '%bar%');
  269. $sql = "SELECT FROM `book` WHERE (book.TITLE <> :p1 OR book.TITLE like :p2)";
  270. $params = array(
  271. array('table' => 'book', 'column' => 'TITLE', 'value' => 'foo'),
  272. array('table' => 'book', 'column' => 'TITLE', 'value' => '%bar%'),
  273. );
  274. $this->assertCriteriaTranslation($c, $sql, $params, 'orWhere() combines the clause with the previous one using OR');
  275. }
  276. public function testOrWhereConditions()
  277. {
  278. $c = new ModelCriteria('bookstore', 'Book');
  279. $c->where('Book.Id = ?', 12);
  280. $c->condition('cond1', 'Book.Title <> ?', 'foo');
  281. $c->condition('cond2', 'Book.Title like ?', '%bar%');
  282. $c->orWhere(array('cond1', 'cond2'));
  283. $sql = "SELECT FROM `book` WHERE (book.ID = :p1 OR (book.TITLE <> :p2 AND book.TITLE like :p3))";
  284. $params = array(
  285. array('table' => 'book', 'column' => 'ID', 'value' => 12),
  286. array('table' => 'book', 'column' => 'TITLE', 'value' => 'foo'),
  287. array('table' => 'book', 'column' => 'TITLE', 'value' => '%bar%'),
  288. );
  289. $this->assertCriteriaTranslation($c, $sql, $params, 'orWhere() accepts an array of named conditions');
  290. $c = new ModelCriteria('bookstore', 'Book');
  291. $c->where('Book.Id = ?', 12);
  292. $c->condition('cond1', 'Book.Title <> ?', 'foo');
  293. $c->condition('cond2', 'Book.Title like ?', '%bar%');
  294. $c->orWhere(array('cond1', 'cond2'), Criteria::LOGICAL_OR);
  295. $sql = "SELECT FROM `book` WHERE (book.ID = :p1 OR (book.TITLE <> :p2 OR book.TITLE like :p3))";
  296. $this->assertCriteriaTranslation($c, $sql, $params, 'orWhere() accepts an array of named conditions with operator');
  297. }
  298. public function testMixedCriteria()
  299. {
  300. $c = new ModelCriteria('bookstore', 'Book');
  301. $c->where('Book.Title = ?', 'foo');
  302. $c->add(BookPeer::ID, array(1, 2), Criteria::IN);
  303. $sql = 'SELECT FROM `book` WHERE book.TITLE = :p1 AND book.ID IN (:p2,:p3)';
  304. $params = array(
  305. array('table' => 'book', 'column' => 'TITLE', 'value' => 'foo'),
  306. array('table' => 'book', 'column' => 'ID', 'value' => 1),
  307. array('table' => 'book', 'column' => 'ID', 'value' => 2)
  308. );
  309. $this->assertCriteriaTranslation($c, $sql, $params, 'ModelCriteria accepts Criteria operators');
  310. }
  311. public function testFilterBy()
  312. {
  313. $c = new ModelCriteria('bookstore', 'Book');
  314. $c->filterBy('Title', 'foo');
  315. $sql = 'SELECT FROM `book` WHERE book.TITLE=:p1';
  316. $params = array(
  317. array('table' => 'book', 'column' => 'TITLE', 'value' => 'foo'),
  318. );
  319. $this->assertCriteriaTranslation($c, $sql, $params, 'filterBy() accepts a simple column name');
  320. $c = new ModelCriteria('bookstore', 'Book');
  321. $c->filterBy('Title', 'foo', Criteria::NOT_EQUAL);
  322. $sql = 'SELECT FROM `book` WHERE book.TITLE<>:p1';
  323. $params = array(
  324. array('table' => 'book', 'column' => 'TITLE', 'value' => 'foo'),
  325. );
  326. $this->assertCriteriaTranslation($c, $sql, $params, 'filterBy() accepts a sicustom comparator');
  327. $c = new ModelCriteria('bookstore', 'Book', 'b');
  328. $c->filterBy('Title', 'foo');
  329. $sql = 'SELECT FROM `book` WHERE book.TITLE=:p1';
  330. $params = array(
  331. array('table' => 'book', 'column' => 'TITLE', 'value' => 'foo'),
  332. );
  333. $this->assertCriteriaTranslation($c, $sql, $params, 'filterBy() accepts a simple column name, even if initialized with an alias');
  334. }
  335. public function testHaving()
  336. {
  337. $c = new ModelCriteria('bookstore', 'Book');
  338. $c->having('Book.Title <> ?', 'foo');
  339. $sql = "SELECT FROM HAVING book.TITLE <> :p1";
  340. $params = array(
  341. array('table' => 'book', 'column' => 'TITLE', 'value' => 'foo'),
  342. );
  343. $this->assertCriteriaTranslation($c, $sql, $params, 'having() accepts a string clause');
  344. }
  345. public function testHavingConditions()
  346. {
  347. $c = new ModelCriteria('bookstore', 'Book');
  348. $c->condition('cond1', 'Book.Title <> ?', 'foo');
  349. $c->condition('cond2', 'Book.Title like ?', '%bar%');
  350. $c->having(array('cond1', 'cond2'));
  351. $sql = "SELECT FROM HAVING (book.TITLE <> :p1 AND book.TITLE like :p2)";
  352. $params = array(
  353. array('table' => 'book', 'column' => 'TITLE', 'value' => 'foo'),
  354. array('table' => 'book', 'column' => 'TITLE', 'value' => '%bar%'),
  355. );
  356. $this->assertCriteriaTranslation($c, $sql, $params, 'having() accepts an array of named conditions');
  357. $c = new ModelCriteria('bookstore', 'Book');
  358. $c->condition('cond1', 'Book.Title <> ?', 'foo');
  359. $c->condition('cond2', 'Book.Title like ?', '%bar%');
  360. $c->having(array('cond1', 'cond2'), Criteria::LOGICAL_OR);
  361. $sql = "SELECT FROM HAVING (book.TITLE <> :p1 OR book.TITLE like :p2)";
  362. $this->assertCriteriaTranslation($c, $sql, $params, 'having() accepts an array of named conditions with an operator');
  363. }
  364. public function testOrderBy()
  365. {
  366. $c = new ModelCriteria('bookstore', 'Book');
  367. $c->orderBy('Book.Title');
  368. $sql = 'SELECT FROM ORDER BY book.TITLE ASC';
  369. $params = array();
  370. $this->assertCriteriaTranslation($c, $sql, $params, 'orderBy() accepts a column name and adds an ORDER BY clause');
  371. $c = new ModelCriteria('bookstore', 'Book');
  372. $c->orderBy('Book.Title', 'desc');
  373. $sql = 'SELECT FROM ORDER BY book.TITLE DESC';
  374. $this->assertCriteriaTranslation($c, $sql, $params, 'orderBy() accepts an order parameter');
  375. $c = new ModelCriteria('bookstore', 'Book');
  376. try {
  377. $c->orderBy('Book.Foo');
  378. $this->fail('orderBy() throws an exception when called with an unkown column name');
  379. } catch (PropelException $e) {
  380. $this->assertTrue(true, 'orderBy() throws an exception when called with an unkown column name');
  381. }
  382. $c = new ModelCriteria('bookstore', 'Book');
  383. try {
  384. $c->orderBy('Book.Title', 'foo');
  385. $this->fail('orderBy() throws an exception when called with an unkown order');
  386. } catch (PropelException $e) {
  387. $this->assertTrue(true, 'orderBy() throws an exception when called with an unkown order');
  388. }
  389. }
  390. public function testOrderBySimpleColumn()
  391. {
  392. $c = new ModelCriteria('bookstore', 'Book');
  393. $c->orderBy('Title');
  394. $sql = 'SELECT FROM ORDER BY book.TITLE ASC';
  395. $params = array();
  396. $this->assertCriteriaTranslation($c, $sql, $params, 'orderBy() accepts a simple column name and adds an ORDER BY clause');
  397. }
  398. public function testOrderByAlias()
  399. {
  400. $c = new ModelCriteria('bookstore', 'Book');
  401. $c->addAsColumn('t', BookPeer::TITLE);
  402. $c->orderBy('t');
  403. $sql = 'SELECT book.TITLE AS t FROM ORDER BY t ASC';
  404. $params = array();
  405. $this->assertCriteriaTranslation($c, $sql, $params, 'orderBy() accepts a column alias and adds an ORDER BY clause');
  406. }
  407. public function testGroupBy()
  408. {
  409. $c = new ModelCriteria('bookstore', 'Book');
  410. $c->groupBy('Book.AuthorId');
  411. $sql = 'SELECT FROM GROUP BY book.AUTHOR_ID';
  412. $params = array();
  413. $this->assertCriteriaTranslation($c, $sql, $params, 'groupBy() accepts a column name and adds a GROUP BY clause');
  414. $c = new ModelCriteria('bookstore', 'Book');
  415. try {
  416. $c->groupBy('Book.Foo');
  417. $this->fail('groupBy() throws an exception when called with an unkown column name');
  418. } catch (PropelException $e) {
  419. $this->assertTrue(true, 'groupBy() throws an exception when called with an unkown column name');
  420. }
  421. }
  422. public function testGroupBySimpleColumn()
  423. {
  424. $c = new ModelCriteria('bookstore', 'Book');
  425. $c->groupBy('AuthorId');
  426. $sql = 'SELECT FROM GROUP BY book.AUTHOR_ID';
  427. $params = array();
  428. $this->assertCriteriaTranslation($c, $sql, $params, 'groupBy() accepts a simple column name and adds a GROUP BY clause');
  429. }
  430. public function testGroupByAlias()
  431. {
  432. $c = new ModelCriteria('bookstore', 'Book');
  433. $c->addAsColumn('t', BookPeer::TITLE);
  434. $c->groupBy('t');
  435. $sql = 'SELECT book.TITLE AS t FROM GROUP BY t';
  436. $params = array();
  437. $this->assertCriteriaTranslation($c, $sql, $params, 'groupBy() accepts a column alias and adds a GROUP BY clause');
  438. }
  439. /**
  440. * @expectedException PropelException
  441. */
  442. public function testGroupByClassThrowsExceptionOnUnkownClass()
  443. {
  444. $c = new ModelCriteria('bookstore', 'Book');
  445. $c->groupByClass('Author');
  446. }
  447. public function testGroupByClass()
  448. {
  449. $c = new ModelCriteria('bookstore', 'Book');
  450. $c->groupByClass('Book');
  451. $sql = 'SELECT FROM GROUP BY book.ID,book.TITLE,book.ISBN,book.PRICE,book.PUBLISHER_ID,book.AUTHOR_ID';
  452. $params = array();
  453. $this->assertCriteriaTranslation($c, $sql, $params, 'groupByClass() accepts a class name and adds a GROUP BY clause for all columns of the class');
  454. }
  455. public function testGroupByClassAlias()
  456. {
  457. $c = new ModelCriteria('bookstore', 'Book', 'b');
  458. $c->groupByClass('b');
  459. $sql = 'SELECT FROM GROUP BY book.ID,book.TITLE,book.ISBN,book.PRICE,book.PUBLISHER_ID,book.AUTHOR_ID';
  460. $params = array();
  461. $this->assertCriteriaTranslation($c, $sql, $params, 'groupByClass() accepts a class alias and adds a GROUP BY clause for all columns of the class');
  462. }
  463. public function testGroupByClassTrueAlias()
  464. {
  465. $c = new ModelCriteria('bookstore', 'Book');
  466. $c->setModelAlias('b', true);
  467. $c->groupByClass('b');
  468. $sql = 'SELECT FROM GROUP BY b.ID,b.TITLE,b.ISBN,b.PRICE,b.PUBLISHER_ID,b.AUTHOR_ID';
  469. $params = array();
  470. $this->assertCriteriaTranslation($c, $sql, $params, 'groupByClass() accepts a true class alias and adds a GROUP BY clause for all columns of the class');
  471. }
  472. public function testGroupByClassJoinedModel()
  473. {
  474. $c = new ModelCriteria('bookstore', 'Author');
  475. $c->join('Author.Book');
  476. $c->groupByClass('Book');
  477. $sql = 'SELECT FROM `author` INNER JOIN `book` ON (author.ID=book.AUTHOR_ID) GROUP BY book.ID,book.TITLE,book.ISBN,book.PRICE,book.PUBLISHER_ID,book.AUTHOR_ID';
  478. $params = array();
  479. $this->assertCriteriaTranslation($c, $sql, $params, 'groupByClass() accepts the class name of a joined model');
  480. }
  481. public function testGroupByClassJoinedModelWithAlias()
  482. {
  483. $c = new ModelCriteria('bookstore', 'Author');
  484. $c->join('Author.Book b');
  485. $c->groupByClass('b');
  486. $sql = 'SELECT FROM `author` INNER JOIN `book` `b` ON (author.ID=b.AUTHOR_ID) GROUP BY b.ID,b.TITLE,b.ISBN,b.PRICE,b.PUBLISHER_ID,b.AUTHOR_ID';
  487. $params = array();
  488. $this->assertCriteriaTranslation($c, $sql, $params, 'groupByClass() accepts the alias of a joined model');
  489. }
  490. public function testDistinct()
  491. {
  492. $c = new ModelCriteria('bookstore', 'Book');
  493. $c->distinct();
  494. $sql = 'SELECT DISTINCT FROM ';
  495. $params = array();
  496. $this->assertCriteriaTranslation($c, $sql, $params, 'distinct() adds a DISTINCT clause');
  497. }
  498. public function testLimit()
  499. {
  500. $c = new ModelCriteria('bookstore', 'Book');
  501. $c->limit(10);
  502. $sql = 'SELECT FROM LIMIT 10';
  503. $params = array();
  504. $this->assertCriteriaTranslation($c, $sql, $params, 'limit() adds a LIMIT clause');
  505. }
  506. public function testOffset()
  507. {
  508. $c = new ModelCriteria('bookstore', 'Book');
  509. $c->limit(50);
  510. $c->offset(10);
  511. $sql = 'SELECT FROM LIMIT 10, 50';
  512. $params = array();
  513. $this->assertCriteriaTranslation($c, $sql, $params, 'offset() adds an OFFSET clause');
  514. }
  515. public function testAddJoin()
  516. {
  517. $c = new ModelCriteria('bookstore', 'Book');
  518. $c->addJoin(BookPeer::AUTHOR_ID, AuthorPeer::ID);
  519. $c->addJoin(BookPeer::PUBLISHER_ID, PublisherPeer::ID);
  520. $sql = 'SELECT FROM `book` INNER JOIN `author` ON (book.AUTHOR_ID=author.ID) INNER JOIN `publisher` ON (book.PUBLISHER_ID=publisher.ID)';
  521. $params = array();
  522. $this->assertCriteriaTranslation($c, $sql, $params, 'addJoin() works the same as in Criteria');
  523. }
  524. public function testJoin()
  525. {
  526. $c = new ModelCriteria('bookstore', 'Book');
  527. $c->join('Book.Author');
  528. $sql = 'SELECT FROM `book` INNER JOIN `author` ON (book.AUTHOR_ID=author.ID)';
  529. $params = array();
  530. $this->assertCriteriaTranslation($c, $sql, $params, 'join() uses a relation to guess the columns');
  531. $c = new ModelCriteria('bookstore', 'Book');
  532. try {
  533. $c->join('Book.Foo');
  534. $this->fail('join() throws an exception when called with a non-existing relation');
  535. } catch (PropelException $e) {
  536. $this->assertTrue(true, 'join() throws an exception when called with a non-existing relation');
  537. }
  538. $c = new ModelCriteria('bookstore', 'Book');
  539. $c->join('Book.Author');
  540. $c->where('Author.FirstName = ?', 'Leo');
  541. $sql = 'SELECT FROM `book` INNER JOIN `author` ON (book.AUTHOR_ID=author.ID) WHERE author.FIRST_NAME = :p1';
  542. $params = array(
  543. array('table' => 'author', 'column' => 'FIRST_NAME', 'value' => 'Leo'),
  544. );
  545. $this->assertCriteriaTranslation($c, $sql, $params, 'join() uses a relation to guess the columns');
  546. $c = new ModelCriteria('bookstore', 'Book');
  547. $c->join('Author');
  548. $c->where('Author.FirstName = ?', 'Leo');
  549. $sql = 'SELECT FROM `book` INNER JOIN `author` ON (book.AUTHOR_ID=author.ID) WHERE author.FIRST_NAME = :p1';
  550. $params = array(
  551. array('table' => 'author', 'column' => 'FIRST_NAME', 'value' => 'Leo'),
  552. );
  553. $this->assertCriteriaTranslation($c, $sql, $params, 'join() uses the current model name when given a simple relation name');
  554. }
  555. public function testJoinQuery()
  556. {
  557. $con = Propel::getConnection(BookPeer::DATABASE_NAME);
  558. BookstoreDataPopulator::depopulate($con);
  559. BookstoreDataPopulator::populate($con);
  560. $c = new ModelCriteria('bookstore', 'Book');
  561. $c->join('Book.Author');
  562. $c->where('Author.FirstName = ?', 'Neal');
  563. $books = BookPeer::doSelect($c);
  564. $expectedSQL = "SELECT book.ID, book.TITLE, book.ISBN, book.PRICE, book.PUBLISHER_ID, book.AUTHOR_ID FROM `book` INNER JOIN `author` ON (book.AUTHOR_ID=author.ID) WHERE author.FIRST_NAME = 'Neal'";
  565. $this->assertEquals($expectedSQL, $con->getLastExecutedQuery(), 'join() issues a real JOIN query');
  566. $this->assertEquals(1, count($books), 'join() issues a real JOIN query');
  567. }
  568. public function testJoinRelationName()
  569. {
  570. $c = new ModelCriteria('bookstore', 'BookstoreEmployee');
  571. $c->join('BookstoreEmployee.Supervisor');
  572. $sql = 'SELECT FROM INNER JOIN `bookstore_employee` ON (bookstore_employee.SUPERVISOR_ID=bookstore_employee.ID)';
  573. $params = array();
  574. $this->assertCriteriaTranslation($c, $sql, $params, 'join() uses relation names as defined in schema.xml');
  575. }
  576. public function testJoinComposite()
  577. {
  578. $c = new ModelCriteria('bookstore', 'ReaderFavorite');
  579. $c->join('ReaderFavorite.BookOpinion');
  580. $sql = 'SELECT FROM `reader_favorite` INNER JOIN `book_opinion` ON (reader_favorite.BOOK_ID=book_opinion.BOOK_ID AND reader_favorite.READER_ID=book_opinion.READER_ID)';
  581. $params = array();
  582. $this->assertCriteriaTranslation($c, $sql, $params, 'join() knows how to create a JOIN clause for relationships with composite fkeys');
  583. }
  584. public function testJoinType()
  585. {
  586. $c = new ModelCriteria('bookstore', 'Book');
  587. $c->join('Book.Author');
  588. $sql = 'SELECT FROM `book` INNER JOIN `author` ON (book.AUTHOR_ID=author.ID)';
  589. $params = array();
  590. $this->assertCriteriaTranslation($c, $sql, $params, 'join() adds an INNER JOIN by default');
  591. $c = new ModelCriteria('bookstore', 'Book');
  592. $c->join('Book.Author', Criteria::INNER_JOIN);
  593. $sql = 'SELECT FROM `book` INNER JOIN `author` ON (book.AUTHOR_ID=author.ID)';
  594. $params = array();
  595. $this->assertCriteriaTranslation($c, $sql, $params, 'join() adds an INNER JOIN by default');
  596. $c = new ModelCriteria('bookstore', 'Book');
  597. $c->join('Book.Author', Criteria::LEFT_JOIN);
  598. $sql = 'SELECT FROM `book` LEFT JOIN `author` ON (book.AUTHOR_ID=author.ID)';
  599. $params = array();
  600. $this->assertCriteriaTranslation($c, $sql, $params, 'join() can add a LEFT JOIN');
  601. $c = new ModelCriteria('bookstore', 'Book');
  602. $c->join('Book.Author', Criteria::RIGHT_JOIN);
  603. $sql = 'SELECT FROM `book` RIGHT JOIN `author` ON (book.AUTHOR_ID=author.ID)';
  604. $params = array();
  605. $this->assertCriteriaTranslation($c, $sql, $params, 'join() can add a RIGHT JOIN');
  606. $c = new ModelCriteria('bookstore', 'Book');
  607. $c->join('Book.Author', 'incorrect join');
  608. $sql = 'SELECT FROM `book` incorrect join `author` ON (book.AUTHOR_ID=author.ID)';
  609. $params = array();
  610. $this->assertCriteriaTranslation($c, $sql, $params, 'join() accepts any join string');
  611. }
  612. public function testJoinDirection()
  613. {
  614. $c = new ModelCriteria('bookstore', 'Book');
  615. $c->join('Book.Author');
  616. $sql = 'SELECT FROM `book` INNER JOIN `author` ON (book.AUTHOR_ID=author.ID)';
  617. $params = array();
  618. $this->assertCriteriaTranslation($c, $sql, $params, 'join() adds a JOIN clause correctly for many to one relationship');
  619. $c = new ModelCriteria('bookstore', 'Author');
  620. $c->join('Author.Book');
  621. $sql = 'SELECT FROM `author` INNER JOIN `book` ON (author.ID=book.AUTHOR_ID)';
  622. $params = array();
  623. $this->assertCriteriaTranslation($c, $sql, $params, 'join() adds a JOIN clause correctly for one to many relationship');
  624. $c = new ModelCriteria('bookstore', 'BookstoreEmployee');
  625. $c->join('BookstoreEmployee.BookstoreEmployeeAccount');
  626. $sql = 'SELECT FROM `bookstore_employee` INNER JOIN `bookstore_employee_account` ON (bookstore_employee.ID=bookstore_employee_account.EMPLOYEE_ID)';
  627. $params = array();
  628. $this->assertCriteriaTranslation($c, $sql, $params, 'join() adds a JOIN clause correctly for one to one relationship');
  629. $c = new ModelCriteria('bookstore', 'BookstoreEmployeeAccount');
  630. $c->join('BookstoreEmployeeAccount.BookstoreEmployee');
  631. $sql = 'SELECT FROM `bookstore_employee_account` INNER JOIN `bookstore_employee` ON (bookstore_employee_account.EMPLOYEE_ID=bookstore_employee.ID)';
  632. $params = array();
  633. $this->assertCriteriaTranslation($c, $sql, $params, 'join() adds a JOIN clause correctly for one to one relationship');
  634. }
  635. public function testJoinSeveral()
  636. {
  637. $c = new ModelCriteria('bookstore', 'Author');
  638. $c->join('Author.Book');
  639. $c->join('Book.Publisher');
  640. $c->where('Publisher.Name = ?', 'foo');
  641. $sql = 'SELECT FROM `author` INNER JOIN `book` ON (author.ID=book.AUTHOR_ID) INNER JOIN `publisher` ON (book.PUBLISHER_ID=publisher.ID) WHERE publisher.NAME = :p1';
  642. $params = array(
  643. array('table' => 'publisher', 'column' => 'NAME', 'value' => 'foo'),
  644. );
  645. $this->assertCriteriaTranslation($c, $sql, $params, 'join() can guess relationships from related tables');
  646. }
  647. public function testJoinAlias()
  648. {
  649. $c = new ModelCriteria('bookstore', 'Book', 'b');
  650. $c->join('b.Author');
  651. $sql = 'SELECT FROM `book` INNER JOIN `author` ON (book.AUTHOR_ID=author.ID)';
  652. $params = array();
  653. $this->assertCriteriaTranslation($c, $sql, $params, 'join() supports relation on main alias');
  654. $c = new ModelCriteria('bookstore', 'Book', 'b');
  655. $c->join('Author');
  656. $sql = 'SELECT FROM `book` INNER JOIN `author` ON (book.AUTHOR_ID=author.ID)';
  657. $params = array();
  658. $this->assertCriteriaTranslation($c, $sql, $params, 'join() can use a simple relation name when the model has an alias');
  659. $c = new ModelCriteria('bookstore', 'Book');
  660. $c->join('Book.Author a');
  661. $sql = 'SELECT FROM `book` INNER JOIN `author` `a` ON (book.AUTHOR_ID=a.ID)';
  662. $params = array();
  663. $this->assertCriteriaTranslation($c, $sql, $params, 'join() supports relation alias');
  664. $c = new ModelCriteria('bookstore', 'Book', 'b');
  665. $c->join('b.Author a');
  666. $sql = 'SELECT FROM `book` INNER JOIN `author` `a` ON (book.AUTHOR_ID=a.ID)';
  667. $params = array();
  668. $this->assertCriteriaTranslation($c, $sql, $params, 'join() supports relation alias on main alias');
  669. $con = Propel::getConnection(BookPeer::DATABASE_NAME);
  670. $c = new ModelCriteria('bookstore', 'Book', 'b');
  671. $c->join('b.Author a');
  672. $c->where('a.FirstName = ?', 'Leo');
  673. $sql = 'SELECT FROM `book` INNER JOIN `author` `a` ON (book.AUTHOR_ID=a.ID) WHERE a.FIRST_NAME = :p1';
  674. $params = array(
  675. array('table' => 'author', 'column' => 'FIRST_NAME', 'value' => 'Leo'),
  676. );
  677. $this->assertCriteriaTranslation($c, $sql, $params, 'join() allows the use of relation alias in where()');
  678. $c = new ModelCriteria('bookstore', 'Author', 'a');
  679. $c->join('a.Book b');
  680. $c->join('b.Publisher p');
  681. $c->where('p.Name = ?', 'foo');
  682. $sql = 'SELECT FROM `author` INNER JOIN `book` `b` ON (author.ID=b.AUTHOR_ID) INNER JOIN `publisher` `p` ON (b.PUBLISHER_ID=p.ID) WHERE p.NAME = :p1';
  683. $params = array(
  684. array('table' => 'publisher', 'column' => 'NAME', 'value' => 'foo'),
  685. );
  686. $this->assertCriteriaTranslation($c, $sql, $params, 'join() allows the use of relation alias in further join()');
  687. }
  688. public function testJoinTrueTableAlias()
  689. {
  690. $c = new ModelCriteria('bookstore', 'Book');
  691. $c->setModelAlias('b', true);
  692. $c->join('b.Author');
  693. $sql = 'SELECT FROM `book` `b` INNER JOIN `author` ON (b.AUTHOR_ID=author.ID)';
  694. $params = array();
  695. $this->assertCriteriaTranslation($c, $sql, $params, 'join() supports relation on true table alias');
  696. $c = new ModelCriteria('bookstore', 'Book');
  697. $c->setModelAlias('b', true);
  698. $c->join('Author');
  699. $sql = 'SELECT FROM `book` `b` INNER JOIN `author` ON (b.AUTHOR_ID=author.ID)';
  700. $params = array();
  701. $this->assertCriteriaTranslation($c, $sql, $params, 'join() supports relation without alias name on true table alias');
  702. }
  703. public function testJoinOnSameTable()
  704. {
  705. $c = new ModelCriteria('bookstore', 'BookstoreEmployee', 'be');
  706. $c->join('be.Supervisor sup');
  707. $c->join('sup.Subordinate sub');
  708. $c->where('sub.Name = ?', 'Foo');
  709. $sql = 'SELECT FROM `bookstore_employee` INNER JOIN `bookstore_employee` `sup` ON (bookstore_employee.SUPERVISOR_ID=sup.ID) INNER JOIN `bookstore_employee` `sub` ON (sup.ID=sub.SUPERVISOR_ID) WHERE sub.NAME = :p1';
  710. $params = array(
  711. array('table' => 'bookstore_employee', 'column' => 'NAME', 'value' => 'Foo'),
  712. );
  713. $this->assertCriteriaTranslation($c, $sql, $params, 'join() allows two joins on the same table thanks to aliases');
  714. }
  715. public function testJoinAliasQuery()
  716. {
  717. $con = Propel::getConnection(BookPeer::DATABASE_NAME);
  718. $c = new ModelCriteria('bookstore', 'Book', 'b');
  719. $c->join('b.Author a');
  720. $c->where('a.FirstName = ?', 'Leo');
  721. $books = BookPeer::doSelect($c, $con);
  722. $expectedSQL = "SELECT book.ID, book.TITLE, book.ISBN, book.PRICE, book.PUBLISHER_ID, book.AUTHOR_ID FROM `book` INNER JOIN `author` `a` ON (book.AUTHOR_ID=a.ID) WHERE a.FIRST_NAME = 'Leo'";
  723. $this->assertEquals($expectedSQL, $con->getLastExecutedQuery(), 'join() allows the use of relation alias in where()');
  724. $c = new ModelCriteria('bookstore', 'BookstoreEmployee', 'be');
  725. $c->join('be.Supervisor sup');
  726. $c->join('sup.Subordinate sub');
  727. $c->where('sub.Name = ?', 'Foo');
  728. $employees = BookstoreEmployeePeer::doSelect($c, $con);
  729. $expectedSQL = "SELECT bookstore_employee.ID, bookstore_employee.CLASS_KEY, bookstore_employee.NAME, bookstore_employee.JOB_TITLE, bookstore_employee.SUPERVISOR_ID FROM `bookstore_employee` INNER JOIN `bookstore_employee` `sup` ON (bookstore_employee.SUPERVISOR_ID=sup.ID) INNER JOIN `bookstore_employee` `sub` ON (sup.ID=sub.SUPERVISOR_ID) WHERE sub.NAME = 'Foo'";
  730. $this->assertEquals($expectedSQL, $con->getLastExecutedQuery(), 'join() allows the use of relation alias in further joins()');
  731. }
  732. public function testAddJoinConditionSimple()
  733. {
  734. $con = Propel::getConnection(BookPeer::DATABASE_NAME);
  735. $c = new ModelCriteria('bookstore', 'Book');
  736. $c->join('Book.Author', Criteria::INNER_JOIN);
  737. $c->addJoinCondition('Author', 'Book.Title IS NOT NULL');
  738. $books = BookPeer::doSelect($c, $con);
  739. $expectedSQL = "SELECT book.ID, book.TITLE, book.ISBN, book.PRICE, book.PUBLISHER_ID, book.AUTHOR_ID FROM `book` INNER JOIN `author` ON (book.AUTHOR_ID=author.ID AND book.TITLE IS NOT NULL)";
  740. $this->assertEquals($expectedSQL, $con->getLastExecutedQuery(), 'addJoinCondition() allows the use of custom conditions');
  741. }
  742. public function testAddJoinConditionBinding()
  743. {
  744. $con = Propel::getConnection(BookPeer::DATABASE_NAME);
  745. $c = new ModelCriteria('bookstore', 'Book');
  746. $c->join('Book.Author', Criteria::INNER_JOIN);
  747. $c->addJoinCondition('Author', 'Book.Title = ?', 'foo');
  748. $books = BookPeer::doSelect($c, $con);
  749. $expectedSQL = "SELECT book.ID, book.TITLE, book.ISBN, book.PRICE, book.PUBLISHER_ID, book.AUTHOR_ID FROM `book` INNER JOIN `author` ON (book.AUTHOR_ID=author.ID AND book.TITLE = 'foo')";
  750. $this->assertEquals($expectedSQL, $con->getLastExecutedQuery(), 'addJoinCondition() allows the use of custom conditions with values to bind');
  751. }
  752. public function testAddJoinConditionSeveral()
  753. {
  754. $con = Propel::getConnection(BookPeer::DATABASE_NAME);
  755. $c = new ModelCriteria('bookstore', 'Book');
  756. $c->join('Book.Author', Criteria::INNER_JOIN);
  757. $c->addJoinCondition('Author', 'Book.Title = ?', 'foo');
  758. $c->addJoinCondition('Author', 'Book.ISBN IS NOT NULL');
  759. $books = BookPeer::doSelect($c, $con);
  760. $expectedSQL = "SELECT book.ID, book.TITLE, book.ISBN, book.PRICE, book.PUBLISHER_ID, book.AUTHOR_ID FROM `book` INNER JOIN `author` ON ((book.AUTHOR_ID=author.ID AND book.TITLE = 'foo') AND book.ISBN IS NOT NULL)";
  761. $this->assertEquals($expectedSQL, $con->getLastExecutedQuery(), 'addJoinCondition() allows the use of several custom conditions');
  762. }
  763. public function testAddJoinConditionBindingAndWhere()
  764. {
  765. $con = Propel::getConnection(BookPeer::DATABASE_NAME);
  766. $c = new ModelCriteria('bookstore', 'Book');
  767. $c->where('Book.Title LIKE ?', 'foo%');
  768. $c->join('Book.Author', Criteria::INNER_JOIN);
  769. $c->addJoinCondition('Author', 'Book.Title = ?', 'foo');
  770. $books = BookPeer::doSelect($c, $con);
  771. $expectedSQL = "SELECT book.ID, book.TITLE, book.ISBN, book.PRICE, book.PUBLISHER_ID, book.AUTHOR_ID FROM `book` INNER JOIN `author` ON (book.AUTHOR_ID=author.ID AND book.TITLE = 'foo') WHERE book.TITLE LIKE 'foo%'";
  772. $this->assertEquals($expectedSQL, $con->getLastExecutedQuery(), 'addJoinCondition() allows the use of custom conditions with values and lives well with WHERE conditions');
  773. }
  774. public function testAddJoinConditionAlias()
  775. {
  776. $con = Propel::getConnection(BookPeer::DATABASE_NAME);
  777. $c = new ModelCriteria('bookstore', 'Book');
  778. $c->join('Book.Author a', Criteria::INNER_JOIN);
  779. $c->addJoinCondition('a', 'Book.Title IS NOT NULL');
  780. $books = BookPeer::doSelect($c, $con);
  781. $expectedSQL = "SELECT book.ID, book.TITLE, book.ISBN, book.PRICE, book.PUBLISHER_ID, book.AUTHOR_ID FROM `book` INNER JOIN `author` `a` ON (book.AUTHOR_ID=a.ID AND book.TITLE IS NOT NULL)";
  782. $this->assertEquals($expectedSQL, $con->getLastExecutedQuery(), 'addJoinCondition() allows the use of custom conditions even on aliased relations');
  783. }
  784. public function testAddJoinConditionOperator()
  785. {
  786. $con = Propel::getConnection(BookPeer::DATABASE_NAME);
  787. $c = new ModelCriteria('bookstore', 'Book');
  788. $c->join('Book.Author', Criteria::INNER_JOIN);
  789. $c->addJoinCondition('Author', 'Book.Title IS NOT NULL', null, Criteria::LOGICAL_OR);
  790. $books = BookPeer::doSelect($c, $con);
  791. $expectedSQL = "SELECT book.ID, book.TITLE, book.ISBN, book.PRICE, book.PUBLISHER_ID, book.AUTHOR_ID FROM `book` INNER JOIN `author` ON (book.AUTHOR_ID=author.ID OR book.TITLE IS NOT NULL)";
  792. $this->assertEquals($expectedSQL, $con->getLastExecutedQuery(), 'addJoinCondition() allows the use of custom conditions with a custom operator');
  793. }
  794. public function testSetJoinConditionCriterion()
  795. {
  796. $con = Propel::getConnection(BookPeer::DATABASE_NAME);
  797. $c = new ModelCriteria('bookstore', 'Book');
  798. $c->join('Book.Author', Criteria::INNER_JOIN);
  799. $criterion = $c->getNewCriterion(BookPeer::TITLE, BookPeer::TITLE . ' = ' . AuthorPeer::FIRST_NAME, Criteria::CUSTOM);
  800. $c->setJoinCondition('Author', $criterion);
  801. $books = BookPeer::doSelect($c, $con);
  802. $expectedSQL = "SELECT book.ID, book.TITLE, book.ISBN, book.PRICE, book.PUBLISHER_ID, book.AUTHOR_ID FROM `book` INNER JOIN `author` ON book.TITLE = author.FIRST_NAME";
  803. $this->assertEquals($expectedSQL, $con->getLastExecutedQuery(), 'setJoinCondition() can override a previous join condition with a Criterion');
  804. }
  805. public function testSetJoinConditionNamedCondition()
  806. {
  807. $con = Propel::getConnection(BookPeer::DATABASE_NAME);
  808. $c = new ModelCriteria('bookstore', 'Book');
  809. $c->join('Book.Author', Criteria::INNER_JOIN);
  810. $c->condition('cond1', 'Book.Title = Author.FirstName');
  811. $c->setJoinCondition('Author', 'cond1');
  812. $books = BookPeer::doSelect($c, $con);
  813. $expectedSQL = "SELECT book.ID, book.TITLE, book.ISBN, book.PRICE, book.PUBLISHER_ID, book.AUTHOR_ID FROM `book` INNER JOIN `author` ON book.TITLE = author.FIRST_NAME";
  814. $this->assertEquals($expectedSQL, $con->getLastExecutedQuery(), 'setJoinCondition() can override a previous join condition with a named condition');
  815. }
  816. public function testGetJoin()
  817. {
  818. $c = new ModelCriteria('bookstore', 'Book');
  819. $c->join('Book.Author');
  820. $joins = $c->getJoins();
  821. $this->assertEquals($joins['Author'], $c->getJoin('Author'), "getJoin() returns a specific Join from the ModelCriteria");
  822. }
  823. public function testWith()
  824. {
  825. $c = new TestableModelCriteria('bookstore', 'Book');
  826. $c->join('Book.Author');
  827. $c->with('Author');
  828. $withs = $c->getWith();
  829. $this->assertTrue(array_key_exists('Author', $withs), 'with() adds an entry to the internal list of Withs');
  830. $this->assertTrue($withs['Author'] instanceof ModelWith, 'with() references the ModelWith object');
  831. }
  832. /**
  833. * @expectedException PropelException
  834. */
  835. public function testWithThrowsExceptionWhenJoinLacks()
  836. {
  837. $c = new ModelCriteria('bookstore', 'Book');
  838. $c->with('Author');
  839. }
  840. public function testWithAlias()
  841. {
  842. $c = new TestableModelCriteria('bookstore', 'Book');
  843. $c->join('Book.Author a');
  844. $c->with('a');
  845. $withs = $c->getWith();
  846. $this->assertTrue(array_key_exists('a', $withs), 'with() uses the alias for the index of the internal list of Withs');
  847. }
  848. /**
  849. * @expectedException PropelException
  850. */
  851. public function testWithThrowsExceptionWhenNotUsingAlias()
  852. {
  853. $c = new ModelCriteria('bookstore', 'Book');
  854. $c->join('Book.Author a');
  855. $c->with('Author');
  856. }
  857. public function testWithAddsSelectColumns()
  858. {
  859. $c = new TestableModelCriteria('bookstore', 'Book');
  860. BookPeer::addSelectColumns($c);
  861. $c->join('Book.Author');
  862. $c->with('Author');
  863. $expectedColumns = array(
  864. BookPeer::ID,
  865. BookPeer::TITLE,
  866. BookPeer::ISBN,
  867. BookPeer::PRICE,
  868. BookPeer::PUBLISHER_ID,
  869. BookPeer::AUTHOR_ID,
  870. AuthorPeer::ID,
  871. AuthorPeer::FIRST_NAME,
  872. AuthorPeer::LAST_NAME,
  873. AuthorPeer::EMAIL,
  874. AuthorPeer::AGE
  875. );
  876. $this->assertEquals($expectedColumns, $c->getSelectColumns(), 'with() adds the columns of the related table');
  877. }
  878. public function testWithAliasAddsSelectColumns()
  879. {
  880. $c = new TestableModelCriteria('bookstore', 'Book');
  881. BookPeer::addSelectColumns($c);
  882. $c->join('Book.Author a');
  883. $c->with('a');
  884. $expectedColumns = array(
  885. BookPeer::ID,
  886. BookPeer::TITLE,
  887. BookPeer::ISBN,
  888. BookPeer::PRICE,
  889. BookPeer::PUBLISHER_ID,
  890. BookPeer::AUTHOR_ID,
  891. 'a.ID',
  892. 'a.FIRST_NAME',
  893. 'a.LAST_NAME',
  894. 'a.EMAIL',
  895. 'a.AGE'
  896. );
  897. $this->assertEquals($expectedColumns, $c->getSelectColumns(), 'with() adds the columns of the related table');
  898. }
  899. public function testWithAddsSelectColumnsOfMainTable()
  900. {
  901. $c = new TestableModelCriteria('bookstore', 'Book');
  902. $c->join('Book.Author');
  903. $c->with('Author');
  904. $expectedColumns = array(
  905. BookPeer::ID,
  906. BookPeer::TITLE,
  907. BookPeer::ISBN,
  908. BookPeer::PRICE,
  909. BookPeer::PUBLISHER_ID,
  910. BookPeer::AUTHOR_ID,
  911. AuthorPeer::ID,
  912. AuthorPeer::FIRST_NAME,
  913. AuthorPeer::LAST_NAME,
  914. AuthorPeer::EMAIL,
  915. AuthorPeer::AGE
  916. );
  917. $this->assertEquals($expectedColumns, $c->getSelectColumns(), 'with() adds the columns of the main table if required');
  918. }
  919. public function testWithAliasAddsSelectColumnsOfMainTable()
  920. {
  921. $c = new TestableModelCriteria('bookstore', 'Book');
  922. $c->setModelAlias('b', true);
  923. $c->join('b.Author a');
  924. $c->with('a');
  925. $expectedColumns = array(
  926. 'b.ID',
  927. 'b.TITLE',
  928. 'b.ISBN',
  929. 'b.PRICE',
  930. 'b.PUBLISHER_ID',
  931. 'b.AUTHOR_ID',
  932. 'a.ID',
  933. 'a.FIRST_NAME',
  934. 'a.LAST_NAME',
  935. 'a.EMAIL',
  936. 'a.AGE'
  937. );
  938. $this->assertEquals($expectedColumns, $c->getSelectColumns(), 'with() adds the columns of the main table with an alias if required');
  939. }
  940. public function testWithOneToManyAddsSelectColumns()
  941. {
  942. $c = new TestableModelCriteria('bookstore', 'Author');
  943. AuthorPeer::addSelectColumns($c);
  944. $c->leftJoin('Author.Book');
  945. $c->with('Book');
  946. $expectedColumns = array(
  947. AuthorPeer::ID,
  948. AuthorPeer::FIRST_NAME,
  949. AuthorPeer::LAST_NAME,
  950. AuthorPeer::EMAIL,
  951. AuthorPeer::AGE,
  952. BookPeer::ID,
  953. BookPeer::TITLE,
  954. BookPeer::ISBN,
  955. BookPeer::PRICE,
  956. BookPeer::PUBLISHER_ID,
  957. BookPeer::AUTHOR_ID,
  958. );
  959. $this->assertEquals($expectedColumns, $c->getSelectColumns(), 'with() adds the columns of the related table even in a one-to-many relationship');
  960. }
  961. public function testJoinWith()
  962. {
  963. $c = new TestableModelCriteria('bookstore', 'Book');
  964. $c->joinWith('Book.Author');
  965. $expectedColumns = array(
  966. BookPeer::ID,
  967. BookPeer::TITLE,
  968. BookPeer::ISBN,
  969. BookPeer::PRICE,
  970. BookPeer::PUBLISHER_ID,
  971. BookPeer::AUTHOR_ID,
  972. AuthorPeer::ID,
  973. AuthorPeer::FIRST_NAME,
  974. AuthorPeer::LAST_NAME,
  975. AuthorPeer::EMAIL,
  976. AuthorPeer::AGE
  977. );
  978. $this->assertEquals($expectedColumns, $c->getSelectColumns(), 'joinWith() adds the join');
  979. $joins = $c->getJoins();
  980. $join = $joins['Author'];
  981. $this->assertEquals(Criteria::INNER_JOIN, $join->getJoinType(), 'joinWith() adds an INNER JOIN by default');
  982. }
  983. public function testJoinWithType()
  984. {
  985. $c = new TestableModelCriteria('bookstore', 'Book');
  986. $c->joinWith('Book.Author', Criteria::LEFT_JOIN);
  987. $joins = $c->getJoins();
  988. $join = $joins['Author'];
  989. $this->assertEquals(Criteria::LEFT_JOIN, $join->getJoinType(), 'joinWith() accepts a join type as second parameter');
  990. }
  991. public function testJoinWithAlias()
  992. {
  993. $c = new TestableModelCriteria('bookstore', 'Book');
  994. $c->joinWith('Book.Author a');
  995. $expectedColumns = array(
  996. BookPeer::ID,
  997. BookPeer::TITLE,
  998. BookPeer::ISBN,
  999. BookPeer::PRICE,
  1000. BookPeer::PUBLISHER_ID,
  1001. BookPeer::AUTHOR_ID,
  1002. 'a.ID',
  1003. 'a.FIRST_NAME',
  1004. 'a.LAST_NAME',
  1005. 'a.EMAIL',
  1006. 'a.AGE'
  1007. );
  1008. $this->assertEquals($expectedColumns, $c->getSelectColumns(), 'joinWith() adds the join with the alias');
  1009. }
  1010. public function testJoinWithSeveral()
  1011. {
  1012. $c = new TestableModelCriteria('bookstore', 'Review');
  1013. $c->joinWith('Review.Book');
  1014. $c->joinWith('Book.Author');
  1015. $c->joinWith('Book.Publisher');
  1016. $expectedColumns = array(
  1017. ReviewPeer::ID,
  1018. ReviewPeer::REVIEWED_BY,
  1019. ReviewPeer::REVIEW_DATE,
  1020. ReviewPeer::RECOMMENDED,
  1021. ReviewPeer::STATUS,
  1022. ReviewPeer::BOOK_ID,
  1023. BookPeer::ID,
  1024. BookPeer::TITLE,
  1025. BookPeer::ISBN,
  1026. BookPeer::PRICE,
  1027. BookPeer::PUBLISHER_ID,
  1028. BookPeer::AUTHOR_ID,
  1029. AuthorPeer::ID,
  1030. AuthorPeer::FIRST_NAME,
  1031. AuthorPeer::LAST_NAME,
  1032. AuthorPeer::EMAIL,
  1033. AuthorPeer::AGE,
  1034. PublisherPeer::ID,
  1035. PublisherPeer::NAME
  1036. );
  1037. $this->assertEquals($expectedColumns, $c->getSelectColumns(), 'joinWith() adds the with');
  1038. $joins = $c->getJoins();
  1039. $expectedJoinKeys = array('Book', 'Author', 'Publisher');
  1040. $this->assertEquals($expectedJoinKeys, array_keys($joins), 'joinWith() adds the join');
  1041. }
  1042. public function testJoinWithTwice()
  1043. {
  1044. $c = new TestableModelCriteria('bookstore', 'Book');
  1045. $c->join('Book.Review');
  1046. $c->joinWith('Book.Author');
  1047. $c->joinWith('Book.Review');
  1048. $expectedColumns = array(
  1049. BookPeer::ID,
  1050. BookPeer::TITLE,
  1051. BookPeer::ISBN,
  1052. BookPeer::PRICE,
  1053. BookPeer::PUBLISHER_ID,
  1054. BookPeer::AUTHOR_ID,
  1055. AuthorPeer::ID,
  1056. AuthorPeer::FIRST_NAME,
  1057. AuthorPeer::LAST_NAME,
  1058. AuthorPeer::EMAIL,
  1059. AuthorPeer::AGE,
  1060. ReviewPeer::ID,
  1061. ReviewPeer::REVIEWED_BY,
  1062. ReviewPeer::REVIEW_DATE,
  1063. ReviewPeer::RECOMMENDED,
  1064. ReviewPeer::STATUS,
  1065. ReviewPeer::BOOK_ID,
  1066. );
  1067. $this->assertEquals($expectedColumns, $c->getSelectColumns(), 'joinWith() adds the with');
  1068. $joins = $c->getJoins();
  1069. $expectedJoinKeys = array('Review', 'Author');
  1070. $this->assertEquals($expectedJoinKeys, array_keys($joins), 'joinWith() adds the join');
  1071. }
  1072. public static function conditionsForTestWithColumn()
  1073. {
  1074. return array(
  1075. array('Book.Title', 'BookTitle', 'book.TITLE AS BookTitle'),
  1076. array('Book.Title', null, 'book.TITLE AS BookTitle'),
  1077. array('UPPER(Book.Title)', null, 'UPPER(book.TITLE) AS UPPERBookTitle'),
  1078. array('CONCAT(Book.Title, Book.ISBN)', 'foo', 'CONCAT(book.TITLE, book.ISBN) AS foo'),
  1079. );
  1080. }
  1081. /**
  1082. * @dataProvider conditionsForTestWithColumn
  1083. */
  1084. public function testWithColumn($clause, $alias, $selectTranslation)
  1085. {
  1086. $c = new ModelCriteria('bookstore', 'Book');
  1087. $c->withColumn($clause, $alias);
  1088. $sql = 'SELECT book.ID, book.TITLE, book.ISBN, book.PRICE, book.PUBLISHER_ID, book.AUTHOR_ID, ' . $selectTranslation . ' FROM `book`';
  1089. $params = array();
  1090. $this->assertCriteriaTranslation($c, $sql, $params, 'withColumn() adds a calculated column to the select clause');
  1091. }
  1092. public static function conditionsForTestWithColumnAndQuotes()
  1093. {
  1094. return array(
  1095. // Examples for simple string concatenation needed for MSSQL.
  1096. // MSSQL has no CONCAT() function so uses + to join strings.
  1097. array("CONVERT(varchar, Author.Age, 120) + \' GMT\'", 'GMTCreatedAt', "CONVERT(varchar, author.AGE, 120) + \' GMT\' AS GMTCreatedAt"),
  1098. array("(Author.FirstName + ' ' + Author.LastName)", 'AuthorFullname', "(author.FIRST_NAME + ' ' + author.LAST_NAME) AS AuthorFullname"),
  1099. array("('\"' + Author.FirstName + ' ' + Author.LastName + '\"')", 'QuotedAuthorFullname', "('\"' + author.FIRST_NAME + ' ' + author.LAST_NAME + '\"') AS QuotedAuthorFullname"),
  1100. //