PageRenderTime 28ms CodeModel.GetById 32ms RepoModel.GetById 0ms app.codeStats 0ms

/tests/framework/db/schema/COciTest.php

https://gitlab.com/RECITEC/yii
PHP | 378 lines | 307 code | 53 blank | 18 comment | 14 complexity | 317b39b79fc35fd9840eec8b1815362a MD5 | raw file
  1. <?php
  2. Yii::import('system.db.CDbConnection');
  3. Yii::import('system.db.schema.oci.COciSchema');
  4. /**
  5. * @group oci
  6. */
  7. class COciTest extends CTestCase
  8. {
  9. const DB_DSN_PREFIX='oci';
  10. const DB_HOST='127.0.0.1';
  11. const DB_PORT='1521';
  12. const DB_SERVICE='xe';
  13. const DB_USER='test';
  14. const DB_PASS='test';
  15. /**
  16. * @var CDbConnection
  17. */
  18. private $db;
  19. public function setUp()
  20. {
  21. if((!extension_loaded('oci8') && !extension_loaded('oci8_11g')) || !extension_loaded('pdo') || !extension_loaded('pdo_oci'))
  22. $this->markTestSkipped('PDO and OCI extensions are required.');
  23. $dsn=self::DB_DSN_PREFIX.':dbname='.self::DB_HOST.':'.self::DB_PORT.'/'.self::DB_SERVICE.';charset=UTF8';
  24. $schemaFilePath=realpath(dirname(__FILE__).'/../data/oci.sql');
  25. $this->db=new CDbConnection($dsn, self::DB_USER, self::DB_PASS);
  26. $this->db->charset='UTF8';
  27. try
  28. {
  29. $this->db->active=true;
  30. }
  31. catch(Exception $e)
  32. {
  33. echo $e->getMessage();
  34. $this->markTestSkipped("Please read {$schemaFilePath} for details on setting up the test environment for OCI test case.");
  35. }
  36. $tables=array('comments', 'post_category', 'posts', 'categories', 'profiles', 'users', 'items', 'orders', 'types');
  37. // delete existing sequences
  38. foreach($tables as $table)
  39. {
  40. if($table==='post_category' || $table==='orders' || $table==='types')
  41. continue;
  42. $sequence=$table.'_id_sequence';
  43. $sql=<<<EOD
  44. DECLARE c INT;
  45. BEGIN
  46. SELECT COUNT(*) INTO c FROM user_sequences WHERE sequence_name = '{$sequence}';
  47. IF c = 1 THEN EXECUTE IMMEDIATE 'DROP SEQUENCE "{$sequence}"'; END IF;
  48. END;
  49. EOD;
  50. $this->db->createCommand($sql)->execute();
  51. }
  52. // delete existing tables
  53. foreach($tables as $table)
  54. {
  55. $sql=<<<EOD
  56. DECLARE c INT;
  57. BEGIN
  58. SELECT COUNT(*) INTO c FROM user_tables WHERE table_name = '{$table}';
  59. IF c = 1 THEN EXECUTE IMMEDIATE 'DROP TABLE "{$table}"'; END IF;
  60. END;
  61. EOD;
  62. $this->db->createCommand($sql)->execute();
  63. }
  64. $sqls='';
  65. foreach(explode("\n", file_get_contents($schemaFilePath)) as $line)
  66. {
  67. if(substr($line, 0, 2)==='--')
  68. continue;
  69. $sqls.=$line."\n";
  70. }
  71. foreach(array_filter(explode("\n\n", $sqls)) as $sql)
  72. {
  73. if(trim($sql)!=='')
  74. {
  75. if(mb_substr($sql, -4)!=='END;') // do not remove semicolons after BEGIN END blocks
  76. $sql=rtrim($sql, ';');
  77. $this->db->createCommand($sql)->execute();
  78. }
  79. }
  80. }
  81. public function tearDown()
  82. {
  83. $this->db->active=false;
  84. }
  85. public function testSchema()
  86. {
  87. $schema=$this->db->schema;
  88. $this->assertInstanceOf('CDbSchema', $schema);
  89. $this->assertEquals($schema->dbConnection, $this->db);
  90. $this->assertInstanceOf('CDbCommandBuilder', $schema->commandBuilder);
  91. $this->assertEquals('"users"', $schema->quoteTableName('users'));
  92. $this->assertEquals('"id"', $schema->quoteColumnName('id'));
  93. $this->assertInstanceOf('CDbTableSchema', $schema->getTable('users'));
  94. $this->assertNull($schema->getTable('foo'));
  95. }
  96. public function testTable()
  97. {
  98. $table=$this->db->schema->getTable('posts');
  99. $this->assertInstanceOf('CDbTableSchema', $table);
  100. $this->assertEquals('posts', $table->name);
  101. $this->assertEquals('"posts"', $table->rawName);
  102. $this->assertEquals('id', $table->primaryKey);
  103. $this->assertEquals(array('author_id'=>array('users', 'id')), $table->foreignKeys);
  104. $this->assertEmpty($table->sequenceName);
  105. $this->assertCount(5, $table->columns);
  106. $this->assertInstanceOf('CDbColumnSchema', $table->getColumn('id'));
  107. $this->assertNull($table->getColumn('foo'));
  108. $this->assertEquals(array('id', 'title', 'create_time', 'author_id', 'content'), $table->columnNames);
  109. $table=$this->db->schema->getTable('orders');
  110. $this->assertEquals(array('key1', 'key2'), $table->primaryKey);
  111. $table=$this->db->schema->getTable('items');
  112. $this->assertEquals('id', $table->primaryKey);
  113. $this->assertEquals(array('col1'=>array('orders', 'key1'), 'col2'=>array('orders', 'key2')), $table->foreignKeys);
  114. $table=$this->db->schema->getTable('types');
  115. $this->assertInstanceOf('CDbTableSchema', $table);
  116. $this->assertEquals('types', $table->name);
  117. $this->assertEquals('"types"', $table->rawName);
  118. $this->assertNull($table->primaryKey);
  119. $this->assertEmpty($table->foreignKeys);
  120. $this->assertNull($table->sequenceName);
  121. $table=$this->db->schema->getTable('invalid');
  122. $this->assertNull($table);
  123. }
  124. public function testColumn()
  125. {
  126. $values=array(
  127. 'name'=>array('id', 'title', 'create_time', 'author_id', 'content'),
  128. 'rawName'=>array('"id"', '"title"', '"create_time"', '"author_id"', '"content"'),
  129. 'defaultValue'=>array(null, null, null, null, null),
  130. 'size'=>array(null, 512, 6, null, 4000),
  131. 'precision'=>array(null, 512, 6, null, 4000),
  132. 'scale'=>array(null, null, null, null, null),
  133. 'dbType'=>array('NUMBER','VARCHAR2(512)','TIMESTAMP(6)(11)','NUMBER','CLOB(4000)'),
  134. 'type'=>array('double','string','string','double','string'),
  135. 'isPrimaryKey'=>array(true,false,false,false,false),
  136. 'isForeignKey'=>array(false,false,false,true,false),
  137. );
  138. $this->checkColumns('posts',$values);
  139. }
  140. protected function checkColumns($tableName,$values)
  141. {
  142. $table=$this->db->schema->getTable($tableName);
  143. foreach($values as $name=>$value)
  144. {
  145. foreach(array_values($table->columns) as $i=>$column)
  146. {
  147. $type1=gettype($column->$name);
  148. $type2=gettype($value[$i]);
  149. $this->assertTrue($column->$name===$value[$i], "$tableName.{$column->name}.$name is {$column->$name} ($type1), different from the expected {$value[$i]} ($type2).");
  150. }
  151. }
  152. }
  153. public function testCommandBuilder()
  154. {
  155. $schema=$this->db->schema;
  156. $builder=$schema->commandBuilder;
  157. $this->assertTrue($builder instanceof CDbCommandBuilder);
  158. $table=$schema->getTable('posts');
  159. $c=$builder->createInsertCommand($table,array('title'=>'test post','create_time'=>new CDbExpression('TO_TIMESTAMP(:ts_value, \'YYYY-MM-DD\')', array(':ts_value'=>'2000-01-01')),'author_id'=>1,'content'=>'test content'));
  160. $this->assertEquals('INSERT INTO "posts" ("title", "create_time", "author_id", "content") VALUES (:yp0, TO_TIMESTAMP(:ts_value, \'YYYY-MM-DD\'), :yp1, :yp2) RETURNING "id" INTO :RETURN_ID',$c->text);
  161. $c->execute();
  162. $this->assertEquals(6,$builder->getLastInsertId($table));
  163. $c=$builder->createCountCommand($table,new CDbCriteria);
  164. $this->assertEquals('SELECT COUNT(*) FROM "posts" "t"',$c->text);
  165. $this->assertEquals(6,$c->queryScalar());
  166. $c=$builder->createDeleteCommand($table,new CDbCriteria(array(
  167. 'condition'=>'"id"=:id',
  168. 'params'=>array('id'=>6))));
  169. $this->assertEquals('DELETE FROM "posts" WHERE "id"=:id',$c->text);
  170. $c->execute();
  171. $c=$builder->createCountCommand($table,new CDbCriteria);
  172. $this->assertEquals(5,$c->queryScalar());
  173. $c=$builder->createFindCommand($table,new CDbCriteria(array(
  174. 'select'=>'"id", "title"',
  175. 'condition'=>'"id"=:id',
  176. 'params'=>array(':id'=>5),
  177. 'order'=>'"title"',
  178. 'limit'=>2,
  179. 'offset'=>0)));
  180. $this->assertEquals('WITH USER_SQL AS (SELECT "id", "title" FROM "posts" "t" WHERE "id"=:id ORDER BY "title"),
  181. PAGINATION AS (SELECT USER_SQL.*, rownum as rowNumId FROM USER_SQL)
  182. SELECT *
  183. FROM PAGINATION
  184. WHERE rownum <= 2', $c->text);
  185. $rows=$c->query()->readAll();
  186. $this->assertEquals(1,count($rows));
  187. $this->assertEquals('post 5',$rows[0]['title']);
  188. $c=$builder->createUpdateCommand($table,array('title'=>'new post 5'),new CDbCriteria(array(
  189. 'condition'=>'"id"=:id',
  190. 'params'=>array('id'=>5))));
  191. $c->execute();
  192. $c=$builder->createFindCommand($table,new CDbCriteria(array(
  193. 'select'=>'"title"',
  194. 'condition'=>'"id"=:id',
  195. 'params'=>array('id'=>5))));
  196. $this->assertEquals('new post 5',$c->queryScalar());
  197. $c=$builder->createSqlCommand('SELECT "title" FROM "posts" WHERE "id"=:id',array(':id'=>3));
  198. $this->assertEquals('post 3',$c->queryScalar());
  199. $c=$builder->createUpdateCounterCommand($table,array('author_id'=>-1),new CDbCriteria(array('condition'=>'"id"=5')));
  200. $this->assertEquals('UPDATE "posts" SET "author_id"="author_id"-1 WHERE "id"=5',$c->text);
  201. $c->execute();
  202. $c=$builder->createSqlCommand('SELECT "author_id" FROM "posts" WHERE "id"=5');
  203. $this->assertEquals(2,$c->queryScalar());
  204. // Oracle does not support UPDATE with JOINs so there are no tests of them
  205. // test bind by position
  206. $c=$builder->createFindCommand($table,new CDbCriteria(array(
  207. 'select'=>'"title"',
  208. 'condition'=>'"id"=?',
  209. 'params'=>array(4))));
  210. $this->assertEquals('SELECT "title" FROM "posts" "t" WHERE "id"=?',$c->text);
  211. $this->assertEquals('post 4',$c->queryScalar());
  212. // another bind by position
  213. $c=$builder->createUpdateCommand($table,array('title'=>'new post 4'),new CDbCriteria(array(
  214. 'condition'=>'"id"=?',
  215. 'params'=>array(4))));
  216. $c->execute();
  217. $c=$builder->createSqlCommand('SELECT "title" FROM "posts" WHERE "id"=4');
  218. $this->assertEquals('new post 4',$c->queryScalar());
  219. // testCreateCriteria
  220. $c=$builder->createCriteria('column=:value',array(':value'=>'value'));
  221. $this->assertEquals('column=:value',$c->condition);
  222. $this->assertEquals(array(':value'=>'value'),$c->params);
  223. $c=$builder->createCriteria(array('condition'=>'column=:value','params'=>array(':value'=>'value')));
  224. $this->assertEquals('column=:value',$c->condition);
  225. $this->assertEquals(array(':value'=>'value'),$c->params);
  226. $c2=$builder->createCriteria($c);
  227. $this->assertTrue($c2!==$c);
  228. $this->assertEquals('column=:value',$c2->condition);
  229. $this->assertEquals(array(':value'=>'value'),$c2->params);
  230. // testCreatePkCriteria
  231. $c=$builder->createPkCriteria($table,1,'author_id>1');
  232. $this->assertEquals('"posts"."id"=1 AND (author_id>1)',$c->condition);
  233. $c=$builder->createPkCriteria($table,array(1,2));
  234. $this->assertEquals('"posts"."id" IN (1, 2)',$c->condition);
  235. $c=$builder->createPkCriteria($table,array());
  236. $this->assertEquals('0=1',$c->condition);
  237. $table2=$schema->getTable('orders');
  238. $c=$builder->createPkCriteria($table2,array('key1'=>1,'key2'=>2),'name=""');
  239. $this->assertEquals('"orders"."key1"=1 AND "orders"."key2"=2 AND (name="")',$c->condition);
  240. $c=$builder->createPkCriteria($table2,array(array('key1'=>1,'key2'=>2),array('key1'=>3,'key2'=>4)));
  241. $this->assertEquals('("orders"."key1", "orders"."key2") IN ((1, 2), (3, 4))',$c->condition);
  242. // createColumnCriteria
  243. $c=$builder->createColumnCriteria($table,array('id'=>1,'author_id'=>2),'title=""');
  244. $this->assertEquals('"posts"."id"=:yp0 AND "posts"."author_id"=:yp1 AND (title="")',$c->condition);
  245. $c=$builder->createPkCriteria($table2,array());
  246. $this->assertEquals('0=1',$c->condition);
  247. }
  248. public function testResetSequence()
  249. {
  250. // we're assuming in this test that COciSchema::resetSequence() is not implemented
  251. // empty CDbSchema::resetSequence() being used
  252. $max=$this->db->createCommand('SELECT MAX("id") FROM "users"')->queryScalar();
  253. $this->db->createCommand('DELETE FROM "users"')->execute();
  254. $this->db->createCommand('INSERT INTO "users" ("username", "password", "email") VALUES (\'user4\', \'pass4\', \'email4\')')->execute();
  255. $max2=$this->db->createCommand('SELECT MAX("id") FROM "users"')->queryScalar();
  256. $this->assertEquals($max+1, $max2);
  257. $userTable=$this->db->schema->getTable('users');
  258. $this->db->createCommand('DELETE FROM "users"')->execute();
  259. $this->db->schema->resetSequence($userTable);
  260. $this->db->createCommand('INSERT INTO "users" ("username", "password", "email") VALUES (\'user4\', \'pass4\', \'email4\')')->execute();
  261. $max=$this->db->createCommand('SELECT MAX("id") FROM "users"')->queryScalar();
  262. $this->assertEquals(6, $max);
  263. $this->db->createCommand('INSERT INTO "users" ("username", "password", "email") VALUES (\'user4\', \'pass4\', \'email4\')')->execute();
  264. $max=$this->db->createCommand('SELECT MAX("id") FROM "users"')->queryScalar();
  265. $this->assertEquals(7, $max);
  266. $this->db->createCommand('DELETE FROM "users"')->execute();
  267. $this->db->schema->resetSequence($userTable, 10);
  268. $this->db->createCommand('INSERT INTO "users" ("username", "password", "email") VALUES (\'user4\', \'pass4\', \'email4\')')->execute();
  269. $max=$this->db->createCommand('SELECT MAX("id") FROM "users"')->queryScalar();
  270. $this->assertEquals(8, $max);
  271. $this->db->createCommand('INSERT INTO "users" ("username", "password", "email") VALUES (\'user4\', \'pass4\', \'email4\')')->execute();
  272. $max=$this->db->createCommand('SELECT MAX("id") FROM "users"')->queryScalar();
  273. $this->assertEquals(9, $max);
  274. }
  275. public function testColumnComments()
  276. {
  277. $tables=$this->db->schema->tables;
  278. // specified comments
  279. $usersColumns=$tables['users']->columns;
  280. $this->assertEquals('User\'s entry primary key', $usersColumns['id']->comment);
  281. $this->assertEquals('Имя пользователя', $usersColumns['username']->comment);
  282. $this->assertEquals('用户的密码', $usersColumns['password']->comment);
  283. $this->assertEquals('דוא"ל של המשתמש', $usersColumns['email']->comment);
  284. // empty comments
  285. $postsColumns=$tables['posts']->columns;
  286. $this->assertEmpty($postsColumns['id']->comment);
  287. $this->assertEmpty($postsColumns['title']->comment);
  288. $this->assertEmpty($postsColumns['create_time']->comment);
  289. $this->assertEmpty($postsColumns['author_id']->comment);
  290. $this->assertEmpty($postsColumns['content']->comment);
  291. }
  292. public function testMultipleInsert()
  293. {
  294. $builder=$this->db->getSchema()->getCommandBuilder();
  295. $tableName='types';
  296. $data=array(
  297. array(
  298. 'int_col'=>1,
  299. 'char_col'=>'char_col_1',
  300. 'char_col2'=>'char_col_2_1',
  301. 'float_col'=>1,
  302. 'bool_col'=>true,
  303. ),
  304. array(
  305. 'int_col'=>2,
  306. 'char_col'=>'char_col_2',
  307. 'float_col'=>2,
  308. 'bool_col'=>false,
  309. ),
  310. );
  311. $command=$builder->createMultipleInsertCommand($tableName,$data);
  312. $command->execute();
  313. $rows=$builder->dbConnection->createCommand('SELECT * FROM '.$builder->dbConnection->quoteTableName($tableName))->queryAll();
  314. $this->assertEquals(count($data),count($rows),'Records count miss matches!');
  315. foreach($rows as $rowIndex=>$row)
  316. foreach($row as $columnName=>$value)
  317. {
  318. $columnIndex=array_search($columnName,$data[$rowIndex],true);
  319. if($columnIndex==false)
  320. continue;
  321. $expectedValue=$data[$rowIndex][$columnIndex];
  322. $this->assertTrue($expectedValue==$value,"Value for column '{$columnName}' incorrect!");
  323. }
  324. }
  325. }