SqlserverTest.php 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  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\Core\Configure;
  17. use Cake\Database\Connection;
  18. use Cake\Database\Driver\Sqlserver;
  19. use Cake\Database\Query;
  20. use Cake\TestSuite\TestCase;
  21. use \PDO;
  22. /**
  23. * Tests Sqlserver driver
  24. */
  25. class SqlserverTest extends TestCase
  26. {
  27. /**
  28. * Set up
  29. *
  30. * @return void
  31. */
  32. public function setUp()
  33. {
  34. parent::setUp();
  35. $this->skipUnless(defined('PDO::SQLSRV_ENCODING_UTF8'), 'SQL Server extension not present');
  36. }
  37. /**
  38. * Test connecting to Sqlserver with custom configuration
  39. *
  40. * @return void
  41. */
  42. public function testConnectionConfigCustom()
  43. {
  44. $config = [
  45. 'persistent' => false,
  46. 'host' => 'foo',
  47. 'username' => 'Administrator',
  48. 'password' => 'blablabla',
  49. 'database' => 'bar',
  50. 'encoding' => 'a-language',
  51. 'flags' => [1 => true, 2 => false],
  52. 'init' => ['Execute this', 'this too'],
  53. 'settings' => ['config1' => 'value1', 'config2' => 'value2'],
  54. ];
  55. $driver = $this->getMock(
  56. 'Cake\Database\Driver\Sqlserver',
  57. ['_connect', 'connection'],
  58. [$config]
  59. );
  60. $dsn = 'sqlsrv:Server=foo;Database=bar;MultipleActiveResultSets=false';
  61. $expected = $config;
  62. $expected['flags'] += [
  63. PDO::ATTR_PERSISTENT => false,
  64. PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
  65. PDO::SQLSRV_ATTR_ENCODING => 'a-language'
  66. ];
  67. $connection = $this->getMock('stdClass', ['exec', 'quote']);
  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->getMock(
  94. 'Cake\Database\Driver\Sqlserver',
  95. ['_connect', 'connection', '_version'],
  96. [[]]
  97. );
  98. $driver
  99. ->expects($this->any())
  100. ->method('_version')
  101. ->will($this->returnValue(12));
  102. $connection = $this->getMock(
  103. '\Cake\Database\Connection',
  104. ['connect', 'driver'],
  105. [['log' => false]]
  106. );
  107. $connection
  108. ->expects($this->any())
  109. ->method('driver')
  110. ->will($this->returnValue($driver));
  111. $query = new \Cake\Database\Query($connection);
  112. $query->select(['id', 'title'])
  113. ->from('articles')
  114. ->order(['id'])
  115. ->offset(10);
  116. $this->assertEquals('SELECT id, title FROM articles ORDER BY id OFFSET 10 ROWS', $query->sql());
  117. $query = new \Cake\Database\Query($connection);
  118. $query->select(['id', 'title'])
  119. ->from('articles')
  120. ->order(['id'])
  121. ->limit(10)
  122. ->offset(50);
  123. $this->assertEquals('SELECT id, title FROM articles ORDER BY id OFFSET 50 ROWS FETCH FIRST 10 ROWS ONLY', $query->sql());
  124. $query = new \Cake\Database\Query($connection);
  125. $query->select(['id', 'title'])
  126. ->from('articles')
  127. ->offset(10);
  128. $this->assertEquals('SELECT id, title FROM articles ORDER BY (SELECT NULL) OFFSET 10 ROWS', $query->sql());
  129. $query = new \Cake\Database\Query($connection);
  130. $query->select(['id', 'title'])
  131. ->from('articles')
  132. ->limit(10);
  133. $this->assertEquals('SELECT TOP 10 id, title FROM articles', $query->sql());
  134. }
  135. /**
  136. * Test select with limit on lte SQLServer2008
  137. *
  138. * @return void
  139. */
  140. public function testSelectLimitOldServer()
  141. {
  142. $driver = $this->getMock(
  143. 'Cake\Database\Driver\Sqlserver',
  144. ['_connect', 'connection', '_version'],
  145. [[]]
  146. );
  147. $driver
  148. ->expects($this->any())
  149. ->method('_version')
  150. ->will($this->returnValue(8));
  151. $connection = $this->getMock(
  152. '\Cake\Database\Connection',
  153. ['connect', 'driver'],
  154. [['log' => false]]
  155. );
  156. $connection
  157. ->expects($this->any())
  158. ->method('driver')
  159. ->will($this->returnValue($driver));
  160. $query = new \Cake\Database\Query($connection);
  161. $query->select(['id', 'title'])
  162. ->from('articles')
  163. ->limit(10);
  164. $expected = 'SELECT TOP 10 id, title FROM articles';
  165. $this->assertEquals($expected, $query->sql());
  166. $query = new \Cake\Database\Query($connection);
  167. $query->select(['id', 'title'])
  168. ->from('articles')
  169. ->offset(10);
  170. $expected = 'SELECT * FROM (SELECT id, title, (ROW_NUMBER() OVER (ORDER BY (SELECT NULL))) AS [_cake_page_rownum_] ' .
  171. 'FROM articles) _cake_paging_ ' .
  172. 'WHERE _cake_paging_._cake_page_rownum_ > :c0';
  173. $this->assertEquals($expected, $query->sql());
  174. $query = new \Cake\Database\Query($connection);
  175. $query->select(['id', 'title'])
  176. ->from('articles')
  177. ->order(['id'])
  178. ->offset(10);
  179. $expected = 'SELECT * FROM (SELECT id, title, (ROW_NUMBER() OVER (ORDER BY id)) AS [_cake_page_rownum_] ' .
  180. 'FROM articles) _cake_paging_ ' .
  181. 'WHERE _cake_paging_._cake_page_rownum_ > :c0';
  182. $this->assertEquals($expected, $query->sql());
  183. $query = new \Cake\Database\Query($connection);
  184. $query->select(['id', 'title'])
  185. ->from('articles')
  186. ->order(['id'])
  187. ->where(['title' => 'Something'])
  188. ->limit(10)
  189. ->offset(50);
  190. $expected = 'SELECT * FROM (SELECT id, title, (ROW_NUMBER() OVER (ORDER BY id)) AS [_cake_page_rownum_] ' .
  191. 'FROM articles WHERE title = :c0) _cake_paging_ ' .
  192. 'WHERE (_cake_paging_._cake_page_rownum_ > :c1 AND _cake_paging_._cake_page_rownum_ <= :c2)';
  193. $this->assertEquals($expected, $query->sql());
  194. }
  195. /**
  196. * Test that insert queries have results available to them.
  197. *
  198. * @return void
  199. */
  200. public function testInsertUsesOutput()
  201. {
  202. $driver = $this->getMock(
  203. 'Cake\Database\Driver\Sqlserver',
  204. ['_connect', 'connection'],
  205. [[]]
  206. );
  207. $connection = $this->getMock(
  208. '\Cake\Database\Connection',
  209. ['connect', 'driver'],
  210. [['log' => false]]
  211. );
  212. $connection
  213. ->expects($this->any())
  214. ->method('driver')
  215. ->will($this->returnValue($driver));
  216. $query = new \Cake\Database\Query($connection);
  217. $query->insert(['title'])
  218. ->into('articles')
  219. ->values(['title' => 'A new article']);
  220. $expected = 'INSERT INTO articles (title) OUTPUT INSERTED.* VALUES (:c0)';
  221. $this->assertEquals($expected, $query->sql());
  222. }
  223. }