SqlserverTest.php 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. <?php
  2. /**
  3. * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
  4. * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
  5. *
  6. * Licensed under The MIT License
  7. * For full copyright and license information, please see the LICENSE.txt
  8. * Redistributions of files must retain the above copyright notice.
  9. *
  10. * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
  11. * @link http://cakephp.org CakePHP(tm) Project
  12. * @since 3.0.0
  13. * @license http://www.opensource.org/licenses/mit-license.php MIT License
  14. */
  15. namespace Cake\Test\TestCase\Database\Driver;
  16. use Cake\Database\Query;
  17. use Cake\TestSuite\TestCase;
  18. use \PDO;
  19. /**
  20. * Tests Sqlserver driver
  21. */
  22. class SqlserverTest extends TestCase
  23. {
  24. /**
  25. * Set up
  26. *
  27. * @return void
  28. */
  29. public function setUp()
  30. {
  31. parent::setUp();
  32. $this->missingExtension = !defined('PDO::SQLSRV_ENCODING_UTF8');
  33. }
  34. /**
  35. * Test connecting to Sqlserver with custom configuration
  36. *
  37. * @return void
  38. */
  39. public function testConnectionConfigCustom()
  40. {
  41. $this->skipIf($this->missingExtension, 'pdo_sqlsrv is not installed.');
  42. $config = [
  43. 'persistent' => false,
  44. 'host' => 'foo',
  45. 'username' => 'Administrator',
  46. 'password' => 'blablabla',
  47. 'database' => 'bar',
  48. 'encoding' => 'a-language',
  49. 'flags' => [1 => true, 2 => false],
  50. 'init' => ['Execute this', 'this too'],
  51. 'settings' => ['config1' => 'value1', 'config2' => 'value2'],
  52. ];
  53. $driver = $this->getMockBuilder('Cake\Database\Driver\Sqlserver')
  54. ->setMethods(['_connect', 'connection'])
  55. ->setConstructorArgs([$config])
  56. ->getMock();
  57. $dsn = 'sqlsrv:Server=foo;Database=bar;MultipleActiveResultSets=false';
  58. $expected = $config;
  59. $expected['flags'] += [
  60. PDO::ATTR_PERSISTENT => false,
  61. PDO::ATTR_EMULATE_PREPARES => false,
  62. PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
  63. PDO::SQLSRV_ATTR_ENCODING => 'a-language'
  64. ];
  65. $connection = $this->getMockBuilder('stdClass')
  66. ->setMethods(['exec', 'quote'])
  67. ->getMock();
  68. $connection->expects($this->any())
  69. ->method('quote')
  70. ->will($this->onConsecutiveCalls(
  71. $this->returnArgument(0),
  72. $this->returnArgument(0),
  73. $this->returnArgument(0)
  74. ));
  75. $connection->expects($this->at(0))->method('exec')->with('Execute this');
  76. $connection->expects($this->at(1))->method('exec')->with('this too');
  77. $connection->expects($this->at(2))->method('exec')->with('SET config1 value1');
  78. $connection->expects($this->at(3))->method('exec')->with('SET config2 value2');
  79. $driver->connection($connection);
  80. $driver->expects($this->once())->method('_connect')
  81. ->with($dsn, $expected);
  82. $driver->expects($this->any())->method('connection')
  83. ->will($this->returnValue($connection));
  84. $driver->connect();
  85. }
  86. /**
  87. * Test select with limit only and SQLServer2012+
  88. *
  89. * @return void
  90. */
  91. public function testSelectLimitVersion12()
  92. {
  93. $driver = $this->getMockBuilder('Cake\Database\Driver\Sqlserver')
  94. ->setMethods(['_connect', 'connection', '_version'])
  95. ->setConstructorArgs([[]])
  96. ->getMock();
  97. $driver
  98. ->expects($this->any())
  99. ->method('_version')
  100. ->will($this->returnValue(12));
  101. $connection = $this->getMockBuilder('\Cake\Database\Connection')
  102. ->setMethods(['connect', 'driver'])
  103. ->setConstructorArgs([['log' => false]])
  104. ->getMock();
  105. $connection
  106. ->expects($this->any())
  107. ->method('driver')
  108. ->will($this->returnValue($driver));
  109. $query = new Query($connection);
  110. $query->select(['id', 'title'])
  111. ->from('articles')
  112. ->order(['id'])
  113. ->offset(10);
  114. $this->assertEquals('SELECT id, title FROM articles ORDER BY id OFFSET 10 ROWS', $query->sql());
  115. $query = new Query($connection);
  116. $query->select(['id', 'title'])
  117. ->from('articles')
  118. ->order(['id'])
  119. ->limit(10)
  120. ->offset(50);
  121. $this->assertEquals('SELECT id, title FROM articles ORDER BY id OFFSET 50 ROWS FETCH FIRST 10 ROWS ONLY', $query->sql());
  122. $query = new Query($connection);
  123. $query->select(['id', 'title'])
  124. ->from('articles')
  125. ->offset(10);
  126. $this->assertEquals('SELECT id, title FROM articles ORDER BY (SELECT NULL) OFFSET 10 ROWS', $query->sql());
  127. $query = new Query($connection);
  128. $query->select(['id', 'title'])
  129. ->from('articles')
  130. ->limit(10);
  131. $this->assertEquals('SELECT TOP 10 id, title FROM articles', $query->sql());
  132. }
  133. /**
  134. * Test select with limit on lte SQLServer2008
  135. *
  136. * @return void
  137. */
  138. public function testSelectLimitOldServer()
  139. {
  140. $driver = $this->getMockBuilder('Cake\Database\Driver\Sqlserver')
  141. ->setMethods(['_connect', 'connection', '_version'])
  142. ->setConstructorArgs([[]])
  143. ->getMock();
  144. $driver
  145. ->expects($this->any())
  146. ->method('_version')
  147. ->will($this->returnValue(8));
  148. $connection = $this->getMockBuilder('\Cake\Database\Connection')
  149. ->setMethods(['connect', 'driver'])
  150. ->setConstructorArgs([['log' => false]])
  151. ->getMock();
  152. $connection
  153. ->expects($this->any())
  154. ->method('driver')
  155. ->will($this->returnValue($driver));
  156. $query = new Query($connection);
  157. $query->select(['id', 'title'])
  158. ->from('articles')
  159. ->limit(10);
  160. $expected = 'SELECT TOP 10 id, title FROM articles';
  161. $this->assertEquals($expected, $query->sql());
  162. $query = new Query($connection);
  163. $query->select(['id', 'title'])
  164. ->from('articles')
  165. ->offset(10);
  166. $expected = 'SELECT * FROM (SELECT id, title, (ROW_NUMBER() OVER (ORDER BY (SELECT NULL))) AS [_cake_page_rownum_] ' .
  167. 'FROM articles) _cake_paging_ ' .
  168. 'WHERE _cake_paging_._cake_page_rownum_ > 10';
  169. $this->assertEquals($expected, $query->sql());
  170. $query = new Query($connection);
  171. $query->select(['id', 'title'])
  172. ->from('articles')
  173. ->order(['id'])
  174. ->offset(10);
  175. $expected = 'SELECT * FROM (SELECT id, title, (ROW_NUMBER() OVER (ORDER BY id)) AS [_cake_page_rownum_] ' .
  176. 'FROM articles) _cake_paging_ ' .
  177. 'WHERE _cake_paging_._cake_page_rownum_ > 10';
  178. $this->assertEquals($expected, $query->sql());
  179. $query = new Query($connection);
  180. $query->select(['id', 'title'])
  181. ->from('articles')
  182. ->order(['id'])
  183. ->where(['title' => 'Something'])
  184. ->limit(10)
  185. ->offset(50);
  186. $expected = 'SELECT * FROM (SELECT id, title, (ROW_NUMBER() OVER (ORDER BY id)) AS [_cake_page_rownum_] ' .
  187. 'FROM articles WHERE title = :c0) _cake_paging_ ' .
  188. 'WHERE (_cake_paging_._cake_page_rownum_ > 50 AND _cake_paging_._cake_page_rownum_ <= 60)';
  189. $this->assertEquals($expected, $query->sql());
  190. }
  191. /**
  192. * Test that insert queries have results available to them.
  193. *
  194. * @return void
  195. */
  196. public function testInsertUsesOutput()
  197. {
  198. $driver = $this->getMockBuilder('Cake\Database\Driver\Sqlserver')
  199. ->setMethods(['_connect', 'connection'])
  200. ->setConstructorArgs([[]])
  201. ->getMock();
  202. $connection = $this->getMockBuilder('\Cake\Database\Connection')
  203. ->setMethods(['connect', 'driver'])
  204. ->setConstructorArgs([['log' => false]])
  205. ->getMock();
  206. $connection
  207. ->expects($this->any())
  208. ->method('driver')
  209. ->will($this->returnValue($driver));
  210. $query = new Query($connection);
  211. $query->insert(['title'])
  212. ->into('articles')
  213. ->values(['title' => 'A new article']);
  214. $expected = 'INSERT INTO articles (title) OUTPUT INSERTED.* VALUES (:c0)';
  215. $this->assertEquals($expected, $query->sql());
  216. }
  217. }