PageRenderTime 57ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/tests/include/database/DBManagerTest.php

https://bitbucket.org/cviolette/sugarcrm
PHP | 2105 lines | 1734 code | 130 blank | 241 comment | 25 complexity | d0e42cb0459b6f0dd6341bb0b037321c MD5 | raw file
Possible License(s): LGPL-2.1, MPL-2.0-no-copyleft-exception, BSD-3-Clause
  1. <?php
  2. /*********************************************************************************
  3. * SugarCRM Community Edition is a customer relationship management program developed by
  4. * SugarCRM, Inc. Copyright (C) 2004-2012 SugarCRM Inc.
  5. *
  6. * This program is free software; you can redistribute it and/or modify it under
  7. * the terms of the GNU Affero General Public License version 3 as published by the
  8. * Free Software Foundation with the addition of the following permission added
  9. * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
  10. * IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
  11. * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
  12. *
  13. * This program is distributed in the hope that it will be useful, but WITHOUT
  14. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  15. * FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
  16. * details.
  17. *
  18. * You should have received a copy of the GNU Affero General Public License along with
  19. * this program; if not, see http://www.gnu.org/licenses or write to the Free
  20. * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  21. * 02110-1301 USA.
  22. *
  23. * You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
  24. * SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
  25. *
  26. * The interactive user interfaces in modified source and object code versions
  27. * of this program must display Appropriate Legal Notices, as required under
  28. * Section 5 of the GNU Affero General Public License version 3.
  29. *
  30. * In accordance with Section 7(b) of the GNU Affero General Public License version 3,
  31. * these Appropriate Legal Notices must retain the display of the "Powered by
  32. * SugarCRM" logo. If the display of the logo is not reasonably feasible for
  33. * technical reasons, the Appropriate Legal Notices must display the words
  34. * "Powered by SugarCRM".
  35. ********************************************************************************/
  36. require_once 'include/database/DBManagerFactory.php';
  37. require_once 'modules/Contacts/Contact.php';
  38. require_once 'tests/include/database/TestBean.php';
  39. class DBManagerTest extends Sugar_PHPUnit_Framework_TestCase
  40. {
  41. /**
  42. * @var DBManager
  43. */
  44. private $_db;
  45. protected $created = array();
  46. protected $backupGlobals = FALSE;
  47. static public function setupBeforeClass()
  48. {
  49. $GLOBALS['current_user'] = SugarTestUserUtilities::createAnonymousUser();
  50. $GLOBALS['app_strings'] = return_application_language($GLOBALS['current_language']);
  51. }
  52. static public function tearDownAfterClass()
  53. {
  54. SugarTestUserUtilities::removeAllCreatedAnonymousUsers();
  55. unset($GLOBALS['current_user']);
  56. unset($GLOBALS['app_strings']);
  57. }
  58. public function setUp()
  59. {
  60. if(empty($this->_db)){
  61. $this->_db = DBManagerFactory::getInstance();
  62. }
  63. }
  64. public function tearDown()
  65. {
  66. foreach($this->created as $table => $dummy) {
  67. $this->_db->dropTableName($table);
  68. }
  69. }
  70. protected function createTableParams($tablename, $fieldDefs, $indices)
  71. {
  72. $this->created[$tablename] = true;
  73. return $this->_db->createTableParams($tablename, $fieldDefs, $indices);
  74. }
  75. protected function dropTableName($tablename)
  76. {
  77. unset($this->created[$tablename]);
  78. return $this->_db->dropTableName($tablename);
  79. }
  80. private function _createRecords(
  81. $num
  82. )
  83. {
  84. $beanIds = array();
  85. for ( $i = 0; $i < $num; $i++ ) {
  86. $bean = new Contact();
  87. $bean->id = "$i-test" . mt_rand();
  88. $bean->last_name = "foobar";
  89. $this->_db->insert($bean);
  90. $beanIds[] = $bean->id;
  91. }
  92. return $beanIds;
  93. }
  94. private function _removeRecords(
  95. array $ids
  96. )
  97. {
  98. foreach ($ids as $id)
  99. $this->_db->query("DELETE From contacts where id = '{$id}'");
  100. }
  101. public function testGetDatabase()
  102. {
  103. if ( $this->_db instanceOf MysqliManager )
  104. $this->assertInstanceOf('Mysqli',$this->_db->getDatabase());
  105. else
  106. $this->assertTrue(is_resource($this->_db->getDatabase()));
  107. }
  108. public function testCheckError()
  109. {
  110. $this->assertFalse($this->_db->checkError());
  111. $this->assertFalse($this->_db->lastError());
  112. }
  113. public function testCheckErrorNoConnection()
  114. {
  115. $this->_db->disconnect();
  116. $this->assertTrue($this->_db->checkError());
  117. $this->_db = DBManagerFactory::getInstance();
  118. }
  119. public function testGetQueryTime()
  120. {
  121. $this->_db->version();
  122. $this->assertTrue($this->_db->getQueryTime() > 0);
  123. }
  124. public function testCheckConnection()
  125. {
  126. $this->_db->checkConnection();
  127. if ( $this->_db instanceOf MysqliManager )
  128. $this->assertInstanceOf('Mysqli',$this->_db->getDatabase());
  129. else
  130. $this->assertTrue(is_resource($this->_db->getDatabase()));
  131. }
  132. public function testInsert()
  133. {
  134. $bean = new Contact();
  135. $bean->last_name = 'foobar' . mt_rand();
  136. $bean->id = 'test' . mt_rand();
  137. $this->_db->insert($bean);
  138. $result = $this->_db->query("select id, last_name from contacts where id = '{$bean->id}'");
  139. $row = $this->_db->fetchByAssoc($result);
  140. $this->assertEquals($row['last_name'],$bean->last_name);
  141. $this->assertEquals($row['id'],$bean->id);
  142. $this->_db->query("delete from contacts where id = '{$row['id']}'");
  143. }
  144. public function testUpdate()
  145. {
  146. $bean = new Contact();
  147. $bean->last_name = 'foobar' . mt_rand();
  148. $bean->id = 'test' . mt_rand();
  149. $this->_db->insert($bean);
  150. $id = $bean->id;
  151. $bean = new Contact();
  152. $bean->last_name = 'newfoobar' . mt_rand();
  153. $this->_db->update($bean,array('id'=>$id));
  154. $result = $this->_db->query("select id, last_name from contacts where id = '{$id}'");
  155. $row = $this->_db->fetchByAssoc($result);
  156. $this->assertEquals($row['last_name'],$bean->last_name);
  157. $this->assertEquals($row['id'],$id);
  158. $this->_db->query("delete from contacts where id = '{$row['id']}'");
  159. }
  160. public function testDelete()
  161. {
  162. $bean = new Contact();
  163. $bean->last_name = 'foobar' . mt_rand();
  164. $bean->id = 'test' . mt_rand();
  165. $this->_db->insert($bean);
  166. $id = $bean->id;
  167. $bean = new Contact();
  168. $this->_db->delete($bean,array('id'=>$id));
  169. $result = $this->_db->query("select deleted from contacts where id = '{$id}'");
  170. $row = $this->_db->fetchByAssoc($result);
  171. $this->assertEquals($row['deleted'],'1');
  172. $this->_db->query("delete from contacts where id = '{$id}'");
  173. }
  174. public function testRetrieve()
  175. {
  176. $bean = new Contact();
  177. $bean->last_name = 'foobar' . mt_rand();
  178. $bean->id = 'test' . mt_rand();
  179. $this->_db->insert($bean);
  180. $id = $bean->id;
  181. $bean = new Contact();
  182. $result = $this->_db->retrieve($bean,array('id'=>$id));
  183. $row = $this->_db->fetchByAssoc($result);
  184. $this->assertEquals($row['id'],$id);
  185. $this->_db->query("delete from contacts where id = '{$id}'");
  186. }
  187. public function testRetrieveView()
  188. {
  189. // TODO: Write this test
  190. }
  191. public function testCreateTable()
  192. {
  193. // TODO: Write this test
  194. }
  195. public function testCreateTableParams()
  196. {
  197. $tablename = 'test' . mt_rand();
  198. $this->createTableParams($tablename,
  199. array(
  200. 'foo' => array (
  201. 'name' => 'foo',
  202. 'type' => 'varchar',
  203. 'len' => '255',
  204. ),
  205. ),
  206. array(
  207. array(
  208. 'name' => 'idx_'. $tablename,
  209. 'type' => 'index',
  210. 'fields' => array('foo'),
  211. )
  212. )
  213. );
  214. $this->assertTrue(in_array($tablename,$this->_db->getTablesArray()));
  215. $this->dropTableName($tablename);
  216. }
  217. public function testRepairTable()
  218. {
  219. // TODO: Write this test
  220. }
  221. public function testRepairTableNoChanges()
  222. {
  223. $tableName = 'testRTNC_' . mt_rand();
  224. $params = array(
  225. /* VARDEF - id - ROW[name] => 'id' [vname] => 'LBL_ID' [required] => 'true' [type] => 'char' [reportable] => '' [comment] => 'Unique identifier' [dbType] => 'id' [len] => '36' */
  226. 'id' =>
  227. array (
  228. 'name' => 'id',
  229. 'vname' => 'LBL_ID',
  230. 'required'=>true,
  231. 'type' => 'id',
  232. 'reportable'=>false,
  233. 'comment' => 'Unique identifier'
  234. ),
  235. 'date_entered' =>
  236. array (
  237. 'name' => 'date_entered',
  238. 'vname' => 'LBL_DATE_ENTERED',
  239. 'type' => 'datetime',
  240. 'required'=>true,
  241. 'comment' => 'Date record created'
  242. ),
  243. 'date_modified' =>
  244. array (
  245. 'name' => 'date_modified',
  246. 'vname' => 'LBL_DATE_MODIFIED',
  247. 'type' => 'datetime',
  248. 'required'=>true,
  249. 'comment' => 'Date record last modified'
  250. ),
  251. 'modified_user_id' =>
  252. array (
  253. 'name' => 'modified_user_id',
  254. 'rname' => 'user_name',
  255. 'id_name' => 'modified_user_id',
  256. 'vname' => 'LBL_MODIFIED',
  257. 'type' => 'assigned_user_name',
  258. 'table' => 'modified_user_id_users',
  259. 'isnull' => 'false',
  260. 'dbType' => 'id',
  261. 'required'=> false,
  262. 'len' => 36,
  263. 'reportable'=>true,
  264. 'comment' => 'User who last modified record'
  265. ),
  266. 'created_by' =>
  267. array (
  268. 'name' => 'created_by',
  269. 'rname' => 'user_name',
  270. 'id_name' => 'created_by',
  271. 'vname' => 'LBL_CREATED',
  272. 'type' => 'assigned_user_name',
  273. 'table' => 'created_by_users',
  274. 'isnull' => 'false',
  275. 'dbType' => 'id',
  276. 'len' => 36,
  277. 'comment' => 'User ID who created record'
  278. ),
  279. 'name' =>
  280. array (
  281. 'name' => 'name',
  282. 'type' => 'varchar',
  283. 'vname' => 'LBL_NAME',
  284. 'len' => 150,
  285. 'comment' => 'Name of the allowable action (view, list, delete, edit)'
  286. ),
  287. 'category' =>
  288. array (
  289. 'name' => 'category',
  290. 'vname' => 'LBL_CATEGORY',
  291. 'type' => 'varchar',
  292. 'len' =>100,
  293. 'reportable'=>true,
  294. 'comment' => 'Category of the allowable action (usually the name of a module)'
  295. ),
  296. 'acltype' =>
  297. array (
  298. 'name' => 'acltype',
  299. 'vname' => 'LBL_TYPE',
  300. 'type' => 'varchar',
  301. 'len' =>100,
  302. 'reportable'=>true,
  303. 'comment' => 'Specifier for Category, usually "module"'
  304. ),
  305. 'aclaccess' =>
  306. array (
  307. 'name' => 'aclaccess',
  308. 'vname' => 'LBL_ACCESS',
  309. 'type' => 'int',
  310. 'len'=>3,
  311. 'reportable'=>true,
  312. 'comment' => 'Number specifying access priority; highest access "wins"'
  313. ),
  314. 'deleted' =>
  315. array (
  316. 'name' => 'deleted',
  317. 'vname' => 'LBL_DELETED',
  318. 'type' => 'bool',
  319. 'reportable'=>false,
  320. 'comment' => 'Record deletion indicator'
  321. ),
  322. 'roles' =>
  323. array (
  324. 'name' => 'roles',
  325. 'type' => 'link',
  326. 'relationship' => 'acl_roles_actions',
  327. 'source'=>'non-db',
  328. 'vname'=>'LBL_USERS',
  329. ),
  330. 'reverse' =>
  331. array (
  332. 'name' => 'reverse',
  333. 'vname' => 'LBL_REVERSE',
  334. 'type' => 'bool',
  335. 'default' => 0
  336. ),
  337. 'deleted2' =>
  338. array (
  339. 'name' => 'deleted2',
  340. 'vname' => 'LBL_DELETED2',
  341. 'type' => 'bool',
  342. 'reportable'=>false,
  343. 'default' => '0'
  344. ),
  345. 'primary_address_country' =>
  346. array (
  347. 'name' => 'primary_address_country',
  348. 'vname' => 'LBL_PRIMARY_ADDRESS_COUNTRY',
  349. 'type' => 'varchar',
  350. 'group'=>'primary_address',
  351. 'comment' => 'Country for primary address',
  352. 'merge_filter' => 'enabled',
  353. ),
  354. 'refer_url' => array (
  355. 'name' => 'refer_url',
  356. 'vname' => 'LBL_REFER_URL',
  357. 'type' => 'varchar',
  358. 'len' => '255',
  359. 'default' => 'http://',
  360. 'comment' => 'The URL referenced in the tracker URL; no longer used as of 4.2 (see campaign_trkrs)'
  361. ),
  362. 'budget' => array (
  363. 'name' => 'budget',
  364. 'vname' => 'LBL_CAMPAIGN_BUDGET',
  365. 'type' => 'currency',
  366. 'dbType' => 'double',
  367. 'comment' => 'Budgeted amount for the campaign'
  368. ),
  369. 'time_from' => array (
  370. 'name' => 'time_from',
  371. 'vname' => 'LBL_TIME_FROM',
  372. 'type' => 'time',
  373. 'required' => false,
  374. 'reportable' => false,
  375. ),
  376. 'description' =>
  377. array (
  378. 'name' => 'description',
  379. 'vname' => 'LBL_DESCRIPTION',
  380. 'type' => 'text',
  381. 'comment' => 'Full text of the note',
  382. 'rows' => 6,
  383. 'cols' => 80,
  384. ),
  385. 'cur_plain' => array (
  386. 'name' => 'cur_plain',
  387. 'vname' => 'LBL_curPlain',
  388. 'type' => 'currency',
  389. ),
  390. 'cur_len_prec' => array (
  391. 'name' => 'cur_len_prec',
  392. 'vname' => 'LBL_curLenPrec',
  393. 'dbType' => 'decimal',
  394. 'type' => 'currency',
  395. 'len' => '26,6',
  396. ),
  397. 'cur_len' => array (
  398. 'name' => 'cur_len',
  399. 'vname' => 'LBL_curLen',
  400. 'dbType' => 'decimal',
  401. 'type' => 'currency',
  402. 'len' => '26',
  403. ),
  404. 'cur_len_prec2' => array (
  405. 'name' => 'cur_len_prec2',
  406. 'vname' => 'LBL_curLenPrec',
  407. 'dbType' => 'decimal',
  408. 'type' => 'currency',
  409. 'len' => '26',
  410. 'precision' => '6',
  411. ),
  412. 'token_ts' =>
  413. array (
  414. 'name' => 'token_ts',
  415. 'type' => 'long',
  416. 'required' => true,
  417. 'comment' => 'Token timestamp',
  418. 'function' => array('name' => 'displayDateFromTs', 'returns' => 'html', 'onListView' => true)
  419. ),
  420. 'conskey' => array(
  421. 'name' => 'conskey',
  422. 'type' => 'varchar',
  423. 'len' => 32,
  424. 'required' => true,
  425. 'isnull' => false,
  426. ),
  427. );
  428. if($this->_db->tableExists($tableName)) {
  429. $this->_db->dropTableName($tableName);
  430. }
  431. $this->createTableParams($tableName, $params, array());
  432. $repair = $this->_db->repairTableParams($tableName, $params, array(), false);
  433. $this->assertEmpty($repair, "Unexpected repairs: " . $repair);
  434. $this->dropTableName($tableName);
  435. }
  436. public function testRepairTableParamsAddData()
  437. {
  438. $tableName = 'test1_' . mt_rand();
  439. $params = array(
  440. 'foo' => array (
  441. 'name' => 'foo',
  442. 'type' => 'varchar',
  443. 'len' => '255',
  444. ),
  445. );
  446. if($this->_db->tableExists($tableName)) {
  447. $this->_db->dropTableName($tableName);
  448. }
  449. $this->createTableParams($tableName, $params, array());
  450. $params['bar'] = array (
  451. 'name' => 'bar',
  452. 'type' => 'int',
  453. );
  454. $cols = $this->_db->get_columns($tableName);
  455. $this->assertArrayNotHasKey('bar', $cols);
  456. $repair = $this->_db->repairTableParams($tableName, $params, array(), false);
  457. $this->assertRegExp('#MISSING IN DATABASE.*bar#i', $repair);
  458. $repair = $this->_db->repairTableParams($tableName, $params, array(), true);
  459. $cols = $this->_db->get_columns($tableName);
  460. $this->assertArrayHasKey('bar', $cols);
  461. $this->assertEquals('bar', $cols['bar']['name']);
  462. $this->assertEquals($this->_db->getColumnType('int'), $cols['bar']['type']);
  463. $this->dropTableName($tableName);
  464. }
  465. public function testRepairTableParamsAddIndex()
  466. {
  467. $tableName = 'test1_' . mt_rand();
  468. $params = array(
  469. 'foo' => array (
  470. 'name' => 'foo',
  471. 'type' => 'varchar',
  472. 'len' => '255',
  473. ),
  474. 'bar' => array (
  475. 'name' => 'bar',
  476. 'type' => 'int',
  477. ),
  478. );
  479. $index = array(
  480. 'name' => 'test_index',
  481. 'type' => 'index',
  482. 'fields' => array('foo', 'bar', 'bazz'),
  483. );
  484. if($this->_db->tableExists($tableName)) {
  485. $this->_db->dropTableName($tableName);
  486. }
  487. $this->createTableParams($tableName, $params, array());
  488. $params['bazz'] = array (
  489. 'name' => 'bazz',
  490. 'type' => 'int',
  491. );
  492. $repair = $this->_db->repairTableParams($tableName, $params, array($index), false);
  493. $this->assertRegExp('#MISSING IN DATABASE.*bazz#i', $repair);
  494. $this->assertRegExp('#MISSING INDEX IN DATABASE.*test_index#i', $repair);
  495. $repair = $this->_db->repairTableParams($tableName, $params, array($index), true);
  496. $idx = $this->_db->get_indices($tableName);
  497. $this->assertArrayHasKey('test_index', $idx);
  498. $this->assertContains('foo', $idx['test_index']['fields']);
  499. $this->assertContains('bazz', $idx['test_index']['fields']);
  500. $cols = $this->_db->get_columns($tableName);
  501. $this->assertArrayHasKey('bazz', $cols);
  502. $this->assertEquals('bazz', $cols['bazz']['name']);
  503. $this->assertEquals($this->_db->getColumnType('int'), $cols['bazz']['type']);
  504. $this->dropTableName($tableName);
  505. }
  506. public function testRepairTableParamsAddIndexAndData()
  507. {
  508. $tableName = 'test1_' . mt_rand();
  509. $params = array(
  510. 'foo' => array (
  511. 'name' => 'foo',
  512. 'type' => 'varchar',
  513. 'len' => '255',
  514. ),
  515. 'bar' => array (
  516. 'name' => 'bar',
  517. 'type' => 'int',
  518. ),
  519. );
  520. $index = array(
  521. 'name' => 'test_index',
  522. 'type' => 'index',
  523. 'fields' => array('foo', 'bar'),
  524. );
  525. if($this->_db->tableExists($tableName)) {
  526. $this->_db->dropTableName($tableName);
  527. }
  528. $this->createTableParams($tableName, $params, array());
  529. $repair = $this->_db->repairTableParams($tableName, $params, array($index), false);
  530. $this->assertRegExp('#MISSING INDEX IN DATABASE.*test_index#i', $repair);
  531. $repair = $this->_db->repairTableParams($tableName, $params, array($index), true);
  532. $idx = $this->_db->get_indices($tableName);
  533. $this->assertArrayHasKey('test_index', $idx);
  534. $this->assertContains('foo', $idx['test_index']['fields']);
  535. $this->assertContains('bar', $idx['test_index']['fields']);
  536. $this->dropTableName($tableName);
  537. }
  538. public function testCompareFieldInTables()
  539. {
  540. $tablename1 = 'test1_' . mt_rand();
  541. $this->createTableParams($tablename1,
  542. array(
  543. 'foo' => array (
  544. 'name' => 'foo',
  545. 'type' => 'varchar',
  546. 'len' => '255',
  547. ),
  548. ),
  549. array()
  550. );
  551. $tablename2 = 'test2_' . mt_rand();
  552. $this->createTableParams($tablename2,
  553. array(
  554. 'foo' => array (
  555. 'name' => 'foo',
  556. 'type' => 'varchar',
  557. 'len' => '255',
  558. ),
  559. ),
  560. array()
  561. );
  562. $res = $this->_db->compareFieldInTables(
  563. 'foo', $tablename1, $tablename2);
  564. $this->assertEquals($res['msg'],'match');
  565. $this->dropTableName($tablename1);
  566. $this->dropTableName($tablename2);
  567. }
  568. public function testCompareFieldInTablesNotInTable1()
  569. {
  570. $tablename1 = 'test3_' . mt_rand();
  571. $this->createTableParams($tablename1,
  572. array(
  573. 'foobar' => array (
  574. 'name' => 'foobar',
  575. 'type' => 'varchar',
  576. 'len' => '255',
  577. ),
  578. ),
  579. array()
  580. );
  581. $tablename2 = 'test4_' . mt_rand();
  582. $this->createTableParams($tablename2,
  583. array(
  584. 'foo' => array (
  585. 'name' => 'foo',
  586. 'type' => 'varchar',
  587. 'len' => '255',
  588. ),
  589. ),
  590. array()
  591. );
  592. $res = $this->_db->compareFieldInTables(
  593. 'foo', $tablename1, $tablename2);
  594. $this->assertEquals($res['msg'],'not_exists_table1');
  595. $this->dropTableName($tablename1);
  596. $this->dropTableName($tablename2);
  597. }
  598. public function testCompareFieldInTablesNotInTable2()
  599. {
  600. $tablename1 = 'test5_' . mt_rand();
  601. $this->createTableParams($tablename1,
  602. array(
  603. 'foo' => array (
  604. 'name' => 'foo',
  605. 'type' => 'varchar',
  606. 'len' => '255',
  607. ),
  608. ),
  609. array()
  610. );
  611. $tablename2 = 'test6_' . mt_rand();
  612. $this->createTableParams($tablename2,
  613. array(
  614. 'foobar' => array (
  615. 'name' => 'foobar',
  616. 'type' => 'varchar',
  617. 'len' => '255',
  618. ),
  619. ),
  620. array()
  621. );
  622. $res = $this->_db->compareFieldInTables(
  623. 'foo', $tablename1, $tablename2);
  624. $this->assertEquals($res['msg'],'not_exists_table2');
  625. $this->dropTableName($tablename1);
  626. $this->dropTableName($tablename2);
  627. }
  628. public function testCompareFieldInTablesFieldsDoNotMatch()
  629. {
  630. $tablename1 = 'test7_' . mt_rand();
  631. $this->createTableParams($tablename1,
  632. array(
  633. 'foo' => array (
  634. 'name' => 'foo',
  635. 'type' => 'varchar',
  636. 'len' => '255',
  637. ),
  638. ),
  639. array()
  640. );
  641. $tablename2 = 'test8_' . mt_rand();
  642. $this->createTableParams($tablename2,
  643. array(
  644. 'foo' => array (
  645. 'name' => 'foo',
  646. 'type' => 'int',
  647. ),
  648. ),
  649. array()
  650. );
  651. $res = $this->_db->compareFieldInTables(
  652. 'foo', $tablename1, $tablename2);
  653. $this->assertEquals($res['msg'],'no_match');
  654. $this->dropTableName($tablename1);
  655. $this->dropTableName($tablename2);
  656. }
  657. // public function testCompareIndexInTables()
  658. // {
  659. // $tablename1 = 'test9_' . mt_rand();
  660. // $this->_db->createTableParams($tablename1,
  661. // array(
  662. // 'foo' => array (
  663. // 'name' => 'foo',
  664. // 'type' => 'varchar',
  665. // 'len' => '255',
  666. // ),
  667. // ),
  668. // array(
  669. // array(
  670. // 'name' => 'idx_'. $tablename1,
  671. // 'type' => 'index',
  672. // 'fields' => array('foo'),
  673. // )
  674. // )
  675. // );
  676. // $tablename2 = 'test10_' . mt_rand();
  677. // $this->_db->createTableParams($tablename2,
  678. // array(
  679. // 'foo' => array (
  680. // 'name' => 'foo',
  681. // 'type' => 'varchar',
  682. // 'len' => '255',
  683. // ),
  684. // ),
  685. // array(
  686. // array(
  687. // 'name' => 'idx_'. $tablename2,
  688. // 'type' => 'index',
  689. // 'fields' => array('foo'),
  690. // )
  691. // )
  692. // );
  693. //
  694. // $res = $this->_db->compareIndexInTables(
  695. // 'idx_foo', $tablename1, $tablename2);
  696. //
  697. // $this->assertEquals($res['msg'],'match');
  698. //
  699. // $this->_db->dropTableName($tablename1);
  700. // $this->_db->dropTableName($tablename2);
  701. // }
  702. //
  703. // public function testCompareIndexInTablesNotInTable1()
  704. // {
  705. // $tablename1 = 'test11_' . mt_rand();
  706. // $this->_db->createTableParams($tablename1,
  707. // array(
  708. // 'foo' => array (
  709. // 'name' => 'foo',
  710. // 'type' => 'varchar',
  711. // 'len' => '255',
  712. // ),
  713. // ),
  714. // array(
  715. // array(
  716. // 'name' => 'idx_'. $tablename1,
  717. // 'type' => 'index',
  718. // 'fields' => array('foo'),
  719. // )
  720. // )
  721. // );
  722. // $tablename2 = 'test12_' . mt_rand();
  723. // $this->_db->createTableParams($tablename2,
  724. // array(
  725. // 'foo' => array (
  726. // 'name' => 'foo',
  727. // 'type' => 'varchar',
  728. // 'len' => '255',
  729. // ),
  730. // ),
  731. // array(
  732. // array(
  733. // 'name' => 'idx_'. $tablename2,
  734. // 'type' => 'index',
  735. // 'fields' => array('foo'),
  736. // )
  737. // )
  738. // );
  739. //
  740. // $res = $this->_db->compareIndexInTables(
  741. // 'idx_foo', $tablename1, $tablename2);
  742. //
  743. // $this->assertEquals($res['msg'],'not_exists_table1');
  744. //
  745. // $this->_db->dropTableName($tablename1);
  746. // $this->_db->dropTableName($tablename2);
  747. // }
  748. //
  749. // public function testCompareIndexInTablesNotInTable2()
  750. // {
  751. // $tablename1 = 'test13_' . mt_rand();
  752. // $this->_db->createTableParams($tablename1,
  753. // array(
  754. // 'foo' => array (
  755. // 'name' => 'foo',
  756. // 'type' => 'varchar',
  757. // 'len' => '255',
  758. // ),
  759. // ),
  760. // array(
  761. // array(
  762. // 'name' => 'idx_'. $tablename1,
  763. // 'type' => 'index',
  764. // 'fields' => array('foo'),
  765. // )
  766. // )
  767. // );
  768. // $tablename2 = 'test14_' . mt_rand();
  769. // $this->_db->createTableParams($tablename2,
  770. // array(
  771. // 'foo' => array (
  772. // 'name' => 'foo',
  773. // 'type' => 'varchar',
  774. // 'len' => '255',
  775. // ),
  776. // ),
  777. // array(
  778. // array(
  779. // 'name' => 'idx_'. $tablename2,
  780. // 'type' => 'index',
  781. // 'fields' => array('foo'),
  782. // )
  783. // )
  784. // );
  785. //
  786. // $res = $this->_db->compareIndexInTables(
  787. // 'idx_foo', $tablename1, $tablename2);
  788. //
  789. // $this->assertEquals($res['msg'],'not_exists_table2');
  790. //
  791. // $this->_db->dropTableName($tablename1);
  792. // $this->_db->dropTableName($tablename2);
  793. // }
  794. //
  795. // public function testCompareIndexInTablesIndexesDoNotMatch()
  796. // {
  797. // $tablename1 = 'test15_' . mt_rand();
  798. // $this->_db->createTableParams($tablename1,
  799. // array(
  800. // 'foo' => array (
  801. // 'name' => 'foo',
  802. // 'type' => 'varchar',
  803. // 'len' => '255',
  804. // ),
  805. // ),
  806. // array(
  807. // array(
  808. // 'name' => 'idx_foo',
  809. // 'type' => 'index',
  810. // 'fields' => array('foo'),
  811. // )
  812. // )
  813. // );
  814. // $tablename2 = 'test16_' . mt_rand();
  815. // $this->_db->createTableParams($tablename2,
  816. // array(
  817. // 'foo' => array (
  818. // 'name' => 'foobar',
  819. // 'type' => 'varchar',
  820. // 'len' => '255',
  821. // ),
  822. // ),
  823. // array(
  824. // array(
  825. // 'name' => 'idx_foo',
  826. // 'type' => 'index',
  827. // 'fields' => array('foobar'),
  828. // )
  829. // )
  830. // );
  831. //
  832. // $res = $this->_db->compareIndexInTables(
  833. // 'idx_foo', $tablename1, $tablename2);
  834. //
  835. // $this->assertEquals($res['msg'],'no_match');
  836. //
  837. // $this->_db->dropTableName($tablename1);
  838. // $this->_db->dropTableName($tablename2);
  839. // }
  840. public function testCreateIndex()
  841. {
  842. // TODO: Write this test
  843. }
  844. public function testAddIndexes()
  845. {
  846. //TODO Fix test with normal index inspection
  847. $this->markTestIncomplete(
  848. 'TODO Reimplement test not using compareIndexInTables.'
  849. );
  850. $tablename1 = 'test17_' . mt_rand();
  851. $this->createTableParams($tablename1,
  852. array(
  853. 'foo' => array (
  854. 'name' => 'foo',
  855. 'type' => 'varchar',
  856. 'len' => '255',
  857. ),
  858. ),
  859. array(
  860. array(
  861. 'name' => 'idx_foo',
  862. 'type' => 'index',
  863. 'fields' => array('foo'),
  864. )
  865. )
  866. );
  867. $tablename2 = 'test18_' . mt_rand();
  868. $this->createTableParams($tablename2,
  869. array(
  870. 'foo' => array (
  871. 'name' => 'foo',
  872. 'type' => 'varchar',
  873. 'len' => '255',
  874. ),
  875. ),
  876. array()
  877. );
  878. // first test not executing the statement
  879. $this->_db->addIndexes(
  880. $tablename2,
  881. array(array(
  882. 'name' => 'idx_foo',
  883. 'type' => 'index',
  884. 'fields' => array('foo'),
  885. )),
  886. false);
  887. $res = $this->_db->compareIndexInTables(
  888. 'idx_foo', $tablename1, $tablename2);
  889. $this->assertEquals($res['msg'],'not_exists_table2');
  890. // now, execute the statement
  891. $this->_db->addIndexes(
  892. $tablename2,
  893. array(array(
  894. 'name' => 'idx_foo',
  895. 'type' => 'index',
  896. 'fields' => array('foo'),
  897. ))
  898. );
  899. $res = $this->_db->compareIndexInTables(
  900. 'idx_foo', $tablename1, $tablename2);
  901. $this->assertEquals($res['msg'],'match');
  902. $this->dropTableName($tablename1);
  903. $this->dropTableName($tablename2);
  904. }
  905. public function testDropIndexes()
  906. {
  907. //TODO Fix test with normal index inspection
  908. $this->markTestIncomplete(
  909. 'TODO Reimplement test not using compareIndexInTables.'
  910. );
  911. $tablename1 = 'test19_' . mt_rand();
  912. $this->createTableParams($tablename1,
  913. array(
  914. 'foo' => array (
  915. 'name' => 'foo',
  916. 'type' => 'varchar',
  917. 'len' => '255',
  918. ),
  919. ),
  920. array(
  921. array(
  922. 'name' => 'idx_foo',
  923. 'type' => 'index',
  924. 'fields' => array('foo'),
  925. )
  926. )
  927. );
  928. $tablename2 = 'test20_' . mt_rand();
  929. $this->createTableParams($tablename2,
  930. array(
  931. 'foo' => array (
  932. 'name' => 'foo',
  933. 'type' => 'varchar',
  934. 'len' => '255',
  935. ),
  936. ),
  937. array(
  938. array(
  939. 'name' => 'idx_foo',
  940. 'type' => 'index',
  941. 'fields' => array('foo'),
  942. )
  943. )
  944. );
  945. $res = $this->_db->compareIndexInTables(
  946. 'idx_foo', $tablename1, $tablename2);
  947. $this->assertEquals('match', $res['msg']);
  948. // first test not executing the statement
  949. $this->_db->dropIndexes(
  950. $tablename2,
  951. array(array(
  952. 'name' => 'idx_foo',
  953. 'type' => 'index',
  954. 'fields' => array('foo'),
  955. )),
  956. false);
  957. $res = $this->_db->compareIndexInTables(
  958. 'idx_foo', $tablename1, $tablename2);
  959. $this->assertEquals('match', $res['msg']);
  960. // now, execute the statement
  961. $sql = $this->_db->dropIndexes(
  962. $tablename2,
  963. array(array(
  964. 'name' => 'idx_foo',
  965. 'type' => 'index',
  966. 'fields' => array('foo'),
  967. )),
  968. true
  969. );
  970. $res = $this->_db->compareIndexInTables(
  971. 'idx_foo', $tablename1, $tablename2);
  972. $this->assertEquals('not_exists_table2', $res['msg']);
  973. $this->dropTableName($tablename1);
  974. $this->dropTableName($tablename2);
  975. }
  976. public function testModifyIndexes()
  977. {
  978. //TODO Fix test with normal index inspection
  979. $this->markTestIncomplete(
  980. 'TODO Reimplement test not using compareIndexInTables.'
  981. );
  982. $tablename1 = 'test21_' . mt_rand();
  983. $this->createTableParams($tablename1,
  984. array(
  985. 'foo' => array (
  986. 'name' => 'foo',
  987. 'type' => 'varchar',
  988. 'len' => '255',
  989. ),
  990. 'foobar' => array (
  991. 'name' => 'foobar',
  992. 'type' => 'varchar',
  993. 'len' => '255',
  994. ),
  995. ),
  996. array(
  997. array(
  998. 'name' => 'idx_'. $tablename1,
  999. 'type' => 'index',
  1000. 'fields' => array('foo'),
  1001. )
  1002. )
  1003. );
  1004. $tablename2 = 'test22_' . mt_rand();
  1005. $this->createTableParams($tablename2,
  1006. array(
  1007. 'foo' => array (
  1008. 'name' => 'foo',
  1009. 'type' => 'varchar',
  1010. 'len' => '255',
  1011. ),
  1012. 'foobar' => array (
  1013. 'name' => 'foobar',
  1014. 'type' => 'varchar',
  1015. 'len' => '255',
  1016. ),
  1017. ),
  1018. array(
  1019. array(
  1020. 'name' => 'idx_'. $tablename2,
  1021. 'type' => 'index',
  1022. 'fields' => array('foobar'),
  1023. )
  1024. )
  1025. );
  1026. $res = $this->_db->compareIndexInTables(
  1027. 'idx_foo', $tablename1, $tablename2);
  1028. $this->assertEquals($res['msg'],'no_match');
  1029. $this->_db->modifyIndexes(
  1030. $tablename2,
  1031. array(array(
  1032. 'name' => 'idx_foo',
  1033. 'type' => 'index',
  1034. 'fields' => array('foo'),
  1035. )),
  1036. false);
  1037. $res = $this->_db->compareIndexInTables(
  1038. 'idx_foo', $tablename1, $tablename2);
  1039. $this->assertEquals($res['msg'],'no_match');
  1040. $this->_db->modifyIndexes(
  1041. $tablename2,
  1042. array(array(
  1043. 'name' => 'idx_foo',
  1044. 'type' => 'index',
  1045. 'fields' => array('foo'),
  1046. ))
  1047. );
  1048. $res = $this->_db->compareIndexInTables(
  1049. 'idx_foo', $tablename1, $tablename2);
  1050. $this->assertEquals($res['msg'],'match');
  1051. $this->dropTableName($tablename1);
  1052. $this->dropTableName($tablename2);
  1053. }
  1054. public function testAddColumn()
  1055. {
  1056. $tablename1 = 'test23_' . mt_rand();
  1057. $this->createTableParams($tablename1,
  1058. array(
  1059. 'foo' => array (
  1060. 'name' => 'foo',
  1061. 'type' => 'varchar',
  1062. 'len' => '255',
  1063. ),
  1064. 'foobar' => array (
  1065. 'name' => 'foobar',
  1066. 'type' => 'varchar',
  1067. 'len' => '255',
  1068. ),
  1069. ),
  1070. array()
  1071. );
  1072. $tablename2 = 'test24_' . mt_rand();
  1073. $this->createTableParams($tablename2,
  1074. array(
  1075. 'foo' => array (
  1076. 'name' => 'foo',
  1077. 'type' => 'varchar',
  1078. 'len' => '255',
  1079. ),
  1080. ),
  1081. array()
  1082. );
  1083. $res = $this->_db->compareFieldInTables(
  1084. 'foobar', $tablename1, $tablename2);
  1085. $this->assertEquals($res['msg'],'not_exists_table2');
  1086. $this->_db->addColumn(
  1087. $tablename2,
  1088. array(
  1089. 'foobar' => array (
  1090. 'name' => 'foobar',
  1091. 'type' => 'varchar',
  1092. 'len' => '255',
  1093. )
  1094. )
  1095. );
  1096. $res = $this->_db->compareFieldInTables(
  1097. 'foobar', $tablename1, $tablename2);
  1098. $this->assertEquals($res['msg'],'match');
  1099. $this->dropTableName($tablename1);
  1100. $this->dropTableName($tablename2);
  1101. }
  1102. public function alterColumnDataProvider()
  1103. {
  1104. return array(
  1105. array(
  1106. 1,
  1107. 'target' => array ('name' => 'foobar', 'type' => 'varchar', 'len' => '255', 'required' => true, 'default' => 'sugar'),
  1108. 'temp' => array ('name' => 'foobar', 'type' => 'int') // Check if type conversion works
  1109. ),
  1110. array(
  1111. 2,
  1112. 'target' => array ('name' => 'foobar', 'type' => 'varchar', 'len' => '255', 'default' => 'kilroy'),
  1113. 'temp' => array ('name' => 'foobar', 'type' => 'double', 'default' => '99999') // Check if default gets replaced
  1114. ),
  1115. array(
  1116. 3,
  1117. 'target' => array ('name' => 'foobar', 'type' => 'varchar', 'len' => '255'),
  1118. 'temp' => array ('name' => 'foobar', 'type' => 'double', 'default' => '99999') // Check if default gets dropped
  1119. ),
  1120. array(
  1121. 4,
  1122. 'target' => array ('name' => 'foobar', 'type' => 'varchar', 'len' => '255', 'required' => true, 'default' => 'sweet'),
  1123. 'temp' => array ('name' => 'foobar', 'type' => 'varchar', 'len' => '1500',) // Check varchar shortening
  1124. ),
  1125. array(
  1126. 5,
  1127. 'target' => array ('name' => 'foobar', 'type' => 'longtext', 'required' => true),
  1128. 'temp' => array ('name' => 'foobar', 'type' => 'text', 'default' => 'dextrose') // Check clob(65k) to clob(2M or so) conversion
  1129. ),
  1130. array(
  1131. 6,
  1132. 'target' => array ('name' => 'foobar', 'type' => 'double', 'required' => true),
  1133. 'temp' => array ('name' => 'foobar', 'type' => 'int', 'default' => 0) // Check int to double change
  1134. ),
  1135. );
  1136. }
  1137. /**
  1138. * @dataProvider alterColumnDataProvider
  1139. * @param $i
  1140. * @param $target
  1141. * @param $temp
  1142. * @return void
  1143. */
  1144. public function testAlterColumn($i, $target, $temp)
  1145. {
  1146. if($this->_db->dbType == "oci8" && ($i == 4 || $i == 6)) {
  1147. $this->markTestSkipped("Cannot reliably shrink columns in Oracle");
  1148. }
  1149. $foo_col = array ('name' => 'foo', 'type' => 'varchar', 'len' => '255'); // Common column between tables
  1150. $tablebase = 'testac_'. mt_rand() . '_';
  1151. $t1 = $tablebase . $i .'A';
  1152. $t2 = $tablebase . $i .'B';
  1153. $this->createTableParams( $t1,
  1154. array('foo' => $foo_col, 'foobar' => $target),
  1155. array());
  1156. $this->createTableParams( $t2,
  1157. array('foo' => $foo_col, 'foobar' => $temp),
  1158. array());
  1159. $res = $this->_db->compareFieldInTables('foobar', $t1, $t2);
  1160. $this->assertEquals('no_match', $res['msg'],
  1161. "testAlterColumn table columns match while they shouldn't for table $t1 and $t2: "
  1162. . print_r($res,true) );
  1163. $this->_db->alterColumn($t2, array('foobar' => $target));
  1164. $res = $this->_db->compareFieldInTables('foobar', $t1, $t2);
  1165. $this->assertEquals('match', $res['msg'],
  1166. "testAlterColumn table columns don't match while they should for table $t1 and $t2: "
  1167. . print_r($res,true) );
  1168. $this->dropTableName($t1);
  1169. $this->dropTableName($t2);
  1170. }
  1171. public function testDropTable()
  1172. {
  1173. // TODO: Write this test
  1174. }
  1175. public function testDropTableName()
  1176. {
  1177. $tablename = 'test' . mt_rand();
  1178. $this->createTableParams($tablename,
  1179. array(
  1180. 'foo' => array (
  1181. 'name' => 'foo',
  1182. 'type' => 'varchar',
  1183. 'len' => '255',
  1184. ),
  1185. ),
  1186. array()
  1187. );
  1188. $this->assertTrue(in_array($tablename,$this->_db->getTablesArray()));
  1189. $this->dropTableName($tablename);
  1190. $this->assertFalse(in_array($tablename,$this->_db->getTablesArray()));
  1191. }
  1192. public function testDeleteColumn()
  1193. {
  1194. // TODO: Write this test
  1195. }
  1196. public function testDisconnectAll()
  1197. {
  1198. DBManagerFactory::disconnectAll();
  1199. $this->assertTrue($this->_db->checkError());
  1200. $this->_db = DBManagerFactory::getInstance();
  1201. }
  1202. public function testQuery()
  1203. {
  1204. $beanIds = $this->_createRecords(5);
  1205. $result = $this->_db->query("SELECT id From contacts where last_name = 'foobar'");
  1206. if ( $this->_db instanceOf MysqliManager )
  1207. $this->assertInstanceOf('Mysqli_result',$result);
  1208. else
  1209. $this->assertTrue(is_resource($result));
  1210. while ( $row = $this->_db->fetchByAssoc($result) )
  1211. $this->assertTrue(in_array($row['id'],$beanIds),"Id not found '{$row['id']}'");
  1212. $this->_removeRecords($beanIds);
  1213. }
  1214. public function disabledLimitQuery()
  1215. {
  1216. $beanIds = $this->_createRecords(5);
  1217. $_REQUEST['module'] = 'contacts';
  1218. $result = $this->_db->limitQuery("SELECT id From contacts where last_name = 'foobar'",1,3);
  1219. if ( $this->_db instanceOf MysqliManager )
  1220. $this->assertInstanceOf('Mysqli_result',$result);
  1221. else
  1222. $this->assertTrue(is_resource($result));
  1223. while ( $row = $this->_db->fetchByAssoc($result) ) {
  1224. if ( $row['id'][0] > 3 || $row['id'][0] < 0 )
  1225. $this->assertFalse(in_array($row['id'],$beanIds),"Found {$row['id']} in error");
  1226. else
  1227. $this->assertTrue(in_array($row['id'],$beanIds),"Didn't find {$row['id']}");
  1228. }
  1229. unset($_REQUEST['module']);
  1230. $this->_removeRecords($beanIds);
  1231. }
  1232. public function testGetOne()
  1233. {
  1234. $beanIds = $this->_createRecords(1);
  1235. $id = $this->_db->getOne("SELECT id From contacts where last_name = 'foobar'");
  1236. $this->assertEquals($id,$beanIds[0]);
  1237. // bug 38994
  1238. if ( $this->_db instanceOf MysqlManager ) {
  1239. $id = $this->_db->getOne($this->_db->limitQuerySql("SELECT id From contacts where last_name = 'foobar'", 0, 1));
  1240. $this->assertEquals($id,$beanIds[0]);
  1241. }
  1242. $this->_removeRecords($beanIds);
  1243. }
  1244. public function testGetFieldsArray()
  1245. {
  1246. $beanIds = $this->_createRecords(1);
  1247. $result = $this->_db->query("SELECT id From contacts where id = '{$beanIds[0]}'");
  1248. $fields = $this->_db->getFieldsArray($result,true);
  1249. $this->assertEquals(array("id"),$fields);
  1250. $this->_removeRecords($beanIds);
  1251. }
  1252. public function testGetAffectedRowCount()
  1253. {
  1254. if(!$this->_db->supports("affected_rows")) {
  1255. $this->markTestSkipped('Skipping, backend doesn\'t support affected rows');
  1256. }
  1257. $beanIds = $this->_createRecords(1);
  1258. $result = $this->_db->query("DELETE From contacts where id = '{$beanIds[0]}'");
  1259. $this->assertEquals(1, $this->_db->getAffectedRowCount($result));
  1260. }
  1261. public function testFetchByAssoc()
  1262. {
  1263. $beanIds = $this->_createRecords(1);
  1264. $result = $this->_db->query("SELECT id From contacts where id = '{$beanIds[0]}'");
  1265. $row = $this->_db->fetchByAssoc($result);
  1266. $this->assertTrue(is_array($row));
  1267. $this->assertEquals($row['id'],$beanIds[0]);
  1268. $this->_removeRecords($beanIds);
  1269. }
  1270. public function testConnect()
  1271. {
  1272. // TODO: Write this test
  1273. }
  1274. public function testDisconnect()
  1275. {
  1276. $this->_db->disconnect();
  1277. $this->assertTrue($this->_db->checkError());
  1278. $this->_db = DBManagerFactory::getInstance();
  1279. }
  1280. public function testGetTablesArray()
  1281. {
  1282. $tablename = 'test' . mt_rand();
  1283. $this->createTableParams($tablename,
  1284. array(
  1285. 'foo' => array (
  1286. 'name' => 'foo',
  1287. 'type' => 'varchar',
  1288. 'len' => '255',
  1289. ),
  1290. ),
  1291. array()
  1292. );
  1293. $this->assertTrue($this->_db->tableExists($tablename));
  1294. $this->dropTableName($tablename);
  1295. }
  1296. public function testVersion()
  1297. {
  1298. $ver = $this->_db->version();
  1299. $this->assertTrue(is_string($ver));
  1300. }
  1301. public function testTableExists()
  1302. {
  1303. $tablename = 'test' . mt_rand();
  1304. $this->createTableParams($tablename,
  1305. array(
  1306. 'foo' => array (
  1307. 'name' => 'foo',
  1308. 'type' => 'varchar',
  1309. 'len' => '255',
  1310. ),
  1311. ),
  1312. array()
  1313. );
  1314. $this->assertTrue(in_array($tablename,$this->_db->getTablesArray()));
  1315. $this->dropTableName($tablename);
  1316. }
  1317. public function providerCompareVardefs()
  1318. {
  1319. $returnArray = array(
  1320. array(
  1321. array(
  1322. 'name' => 'foo',
  1323. 'type' => 'varchar',
  1324. 'len' => '255',
  1325. ),
  1326. array(
  1327. 'name' => 'foo',
  1328. 'type' => 'varchar',
  1329. 'len' => '255',
  1330. ),
  1331. true),
  1332. array(
  1333. array(
  1334. 'name' => 'foo',
  1335. 'type' => 'char',
  1336. 'len' => '255',
  1337. ),
  1338. array(
  1339. 'name' => 'foo',
  1340. 'type' => 'varchar',
  1341. 'len' => '255',
  1342. ),
  1343. false),
  1344. array(
  1345. array(
  1346. 'name' => 'foo',
  1347. 'type' => 'char',
  1348. 'len' => '255',
  1349. ),
  1350. array(
  1351. 'name' => 'foo',
  1352. 'len' => '255',
  1353. ),
  1354. false),
  1355. array(
  1356. array(
  1357. 'name' => 'foo',
  1358. 'len' => '255',
  1359. ),
  1360. array(
  1361. 'name' => 'foo',
  1362. 'type' => 'varchar',
  1363. 'len' => '255',
  1364. ),
  1365. true),
  1366. array(
  1367. array(
  1368. 'name' => 'foo',
  1369. 'type' => 'varchar',
  1370. 'len' => '255',
  1371. ),
  1372. array(
  1373. 'name' => 'FOO',
  1374. 'type' => 'varchar',
  1375. 'len' => '255',
  1376. ),
  1377. true),
  1378. );
  1379. return $returnArray;
  1380. }
  1381. /**
  1382. * @dataProvider providerCompareVarDefs
  1383. */
  1384. public function testCompareVarDefs($fieldDef1,$fieldDef2,$expectedResult)
  1385. {
  1386. if ( $expectedResult ) {
  1387. $this->assertTrue($this->_db->compareVarDefs($fieldDef1,$fieldDef2));
  1388. }
  1389. else {
  1390. $this->assertFalse($this->_db->compareVarDefs($fieldDef1,$fieldDef2));
  1391. }
  1392. }
  1393. /**
  1394. * @ticket 34892
  1395. */
  1396. public function test_Bug34892_MssqlNotClearingErrorResults()
  1397. {
  1398. // execute a bad query
  1399. $this->_db->query("select dsdsdsdsdsdsdsdsdsd", false, "test_Bug34892_MssqlNotClearingErrorResults", true);
  1400. // assert it found an error
  1401. $this->assertNotEmpty($this->_db->lastError(), "lastError should return true as a result of the previous illegal query");
  1402. // now, execute a good query
  1403. $this->_db->query("select * from config");
  1404. // and make no error messages are asserted
  1405. $this->assertEmpty($this->_db->lastError(), "lastError should have cleared the previous error and return false of the last legal query");
  1406. }
  1407. public function vardefProvider()
  1408. {
  1409. $GLOBALS['log']->info('DBManagerTest.vardefProvider: _db = ' . print_r($this->_db));
  1410. $this->setUp(); // Just in case the DB driver is not created yet.
  1411. $emptydate = $this->_db->emptyValue("date");
  1412. $emptytime = $this->_db->emptyValue("time");
  1413. $emptydatetime = $this->_db->emptyValue("datetime");
  1414. return array(
  1415. array("testid", array (
  1416. 'id' =>
  1417. array (
  1418. 'name' => 'id',
  1419. 'type' => 'varchar',
  1420. 'required'=>true,
  1421. ),
  1422. ),
  1423. array("id" => "test123"),
  1424. array("id" => "'test123'")
  1425. ),
  1426. array("testtext", array (
  1427. 'text1' =>
  1428. array (
  1429. 'name' => 'text1',
  1430. 'type' => 'varchar',
  1431. 'required'=>true,
  1432. ),
  1433. 'text2' =>
  1434. array (
  1435. 'name' => 'text2',
  1436. 'type' => 'varchar',
  1437. ),
  1438. ),
  1439. array(),
  1440. array("text1" => "''"),
  1441. array()
  1442. ),
  1443. array("testtext2", array (
  1444. 'text1' =>
  1445. array (
  1446. 'name' => 'text1',
  1447. 'type' => 'varchar',
  1448. 'required'=>true,
  1449. ),
  1450. 'text2' =>
  1451. array (
  1452. 'name' => 'text2',
  1453. 'type' => 'varchar',
  1454. ),
  1455. ),
  1456. array('text1' => 'foo', 'text2' => 'bar'),
  1457. array("text1" => "'foo'", 'text2' => "'bar'"),
  1458. ),
  1459. array("testreq", array (
  1460. 'id' =>
  1461. array (
  1462. 'name' => 'id',
  1463. 'type' => 'varchar',
  1464. 'required'=>true,
  1465. ),
  1466. 'intval' =>
  1467. array (
  1468. 'name' => 'intval',
  1469. 'type' => 'int',
  1470. 'required'=>true,
  1471. ),
  1472. 'floatval' =>
  1473. array (
  1474. 'name' => 'floatval',
  1475. 'type' => 'decimal',
  1476. 'required'=>true,
  1477. ),
  1478. 'money' =>
  1479. array (
  1480. 'name' => 'money',
  1481. 'type' => 'currency',
  1482. 'required'=>true,
  1483. ),
  1484. 'test_dtm' =>
  1485. array (
  1486. 'name' => 'test_dtm',
  1487. 'type' => 'datetime',
  1488. 'required'=>true,
  1489. ),
  1490. 'test_dtm2' =>
  1491. array (
  1492. 'name' => 'test_dtm2',
  1493. 'type' => 'datetimecombo',
  1494. 'required'=>true,
  1495. ),
  1496. 'test_dt' =>
  1497. array (
  1498. 'name' => 'test_dt',
  1499. 'type' => 'date',
  1500. 'required'=>true,
  1501. ),
  1502. 'test_tm' =>
  1503. array (
  1504. 'name' => 'test_tm',
  1505. 'type' => 'time',
  1506. 'required'=>true,
  1507. ),
  1508. ),
  1509. array("id" => "test123", 'intval' => 42, 'floatval' => 42.24,
  1510. 'money' => 56.78, 'test_dtm' => '2002-01-02 12:34:56', 'test_dtm2' => '2011-10-08 01:02:03',
  1511. 'test_dt' => '1998-10-04', 'test_tm' => '03:04:05'
  1512. ),
  1513. array("id" => "'test123'", 'intval' => 42, 'floatval' => 42.24,
  1514. 'money' => 56.78, 'test_dtm' => $this->_db->convert('\'2002-01-02 12:34:56\'', "datetime"), 'test_dtm2' => $this->_db->convert('\'2011-10-08 01:02:03\'', 'datetime'),
  1515. 'test_dt' => $this->_db->convert('\'1998-10-04\'', 'date'), 'test_tm' => $this->_db->convert('\'03:04:05\'', 'time')
  1516. ),
  1517. ),
  1518. array("testreqnull", array (
  1519. 'id' =>
  1520. array (
  1521. 'name' => 'id',
  1522. 'type' => 'varchar',
  1523. 'required'=>true,
  1524. ),
  1525. 'intval' =>
  1526. array (
  1527. 'name' => 'intval',
  1528. 'type' => 'int',
  1529. 'required'=>true,
  1530. ),
  1531. 'floatval' =>
  1532. array (
  1533. 'name' => 'floatval',
  1534. 'type' => 'decimal',
  1535. 'required'=>true,
  1536. ),
  1537. 'money' =>
  1538. array (
  1539. 'name' => 'money',
  1540. 'type' => 'currency',
  1541. 'required'=>true,
  1542. ),
  1543. 'test_dtm' =>
  1544. array (
  1545. 'name' => 'test_dtm',
  1546. 'type' => 'datetime',
  1547. 'required'=>true,
  1548. ),
  1549. 'test_dtm2' =>
  1550. array (
  1551. 'name' => 'test_dtm2',
  1552. 'type' => 'datetimecombo',
  1553. 'required'=>true,
  1554. ),
  1555. 'test_dt' =>
  1556. array (
  1557. 'name' => 'test_dt',
  1558. 'type' => 'date',
  1559. 'required'=>true,
  1560. ),
  1561. 'test_tm' =>
  1562. array (
  1563. 'name' => 'test_tm',
  1564. 'type' => 'time',
  1565. 'required'=>true,
  1566. ),
  1567. ),
  1568. array(),
  1569. array("id" => "''", 'intval' => 0, 'floatval' => 0,
  1570. 'money' => 0, 'test_dtm' => "$emptydatetime", 'test_dtm2' => "$emptydatetime",
  1571. 'test_dt' => "$emptydate", 'test_tm' => "$emptytime"
  1572. ),
  1573. array(),
  1574. ),
  1575. array("testnull", array (
  1576. 'id' =>
  1577. array (
  1578. 'name' => 'id',
  1579. 'type' => 'varchar',
  1580. ),
  1581. 'intval' =>
  1582. array (
  1583. 'name' => 'intval',
  1584. 'type' => 'int',
  1585. ),
  1586. 'floatval' =>
  1587. array (
  1588. 'name' => 'floatval',
  1589. 'type' => 'decimal',
  1590. ),
  1591. 'money' =>
  1592. array (
  1593. 'name' => 'money',
  1594. 'type' => 'currency',
  1595. ),
  1596. 'test_dtm' =>
  1597. array (
  1598. 'name' => 'test_dtm',
  1599. 'type' => 'datetime',
  1600. ),
  1601. 'test_dtm2' =>
  1602. array (
  1603. 'name' => 'test_dtm2',
  1604. 'type' => 'datetimecombo',
  1605. ),
  1606. 'test_dt' =>
  1607. array (
  1608. 'name' => 'test_dt',
  1609. 'type' => 'date',
  1610. ),
  1611. 'test_tm' =>
  1612. array (
  1613. 'name' => 'test_tm',
  1614. 'type' => 'time',
  1615. ),
  1616. ),
  1617. array("id" => 123),
  1618. array("id" => "'123'"),
  1619. array(),
  1620. ),
  1621. array("testempty", array (
  1622. 'id' =>
  1623. array (
  1624. 'name' => 'id',
  1625. 'type' => 'varchar',
  1626. ),
  1627. 'intval' =>
  1628. array (
  1629. 'name' => 'intval',
  1630. 'type' => 'int',
  1631. ),
  1632. 'floatval' =>
  1633. array (
  1634. 'name' => 'floatval',
  1635. 'type' => 'decimal',
  1636. ),
  1637. 'money' =>
  1638. array (
  1639. 'name' => 'money',
  1640. 'type' => 'currency',
  1641. ),
  1642. 'test_dtm' =>
  1643. array (
  1644. 'name' => 'test_dtm',
  1645. 'type' => 'datetime',
  1646. ),
  1647. 'test_dtm2' =>
  1648. array (
  1649. 'name' => 'test_dtm2',
  1650. 'type' => 'datetimecombo',
  1651. ),
  1652. 'test_dt' =>
  1653. array (
  1654. 'name' => 'test_dt',
  1655. 'type' => 'date',
  1656. ),
  1657. 'test_tm' =>
  1658. array (
  1659. 'name' => 'test_tm',
  1660. 'type' => 'time',
  1661. ),
  1662. 'text_txt' =>
  1663. array (
  1664. 'name' => 'test_txt',
  1665. 'type' => 'varchar',
  1666. ),
  1667. ),
  1668. array("id" => "", 'intval' => '', 'floatval' => '',
  1669. 'money' => '', 'test_dtm' => '', 'test_dtm2' => '',
  1670. 'test_dt' => '', 'test_tm' => '', 'text_txt' => null
  1671. ),
  1672. array("id" => "''", 'intval' => 0, 'floatval' => 0,
  1673. 'money' => 0, 'test_dtm' => "NULL", 'test_dtm2' => "NULL",
  1674. 'test_dt' => "NULL", 'test_tm' => 'NULL'
  1675. ),
  1676. array('intval' => 'NULL', 'floatval' => 'NULL',
  1677. 'money' => 'NULL', 'test_dtm' => 'NULL', 'test_dtm2' => 'NULL',
  1678. 'test_dt' => 'NULL', 'test_tm' => 'NULL'
  1679. ),
  1680. ),
  1681. );
  1682. }
  1683. /**
  1684. * Test InserSQL functions
  1685. * @dataProvider vardefProvider
  1686. * @param string $name
  1687. * @param array $defs
  1688. * @param array $data
  1689. * @param array $result
  1690. */
  1691. public function testInsertSQL($name, $defs, $data, $result)
  1692. {
  1693. $vardefs = array(
  1694. 'table' => $name,
  1695. 'fields' => $defs,
  1696. );
  1697. $obj = new TestSugarBean($name, $vardefs);
  1698. // regular fields
  1699. foreach($data as $k => $v) {
  1700. $obj->$k = $v;
  1701. }
  1702. $sql = $this->_db->insertSQL($obj);
  1703. $names = join('\s*,\s*',array_map('preg_quote', array_keys($result)));
  1704. $values = join('\s*,\s*',array_map('preg_quote', array_values($result)));
  1705. $this->assertRegExp("/INSERT INTO $name\s+\(\s*$names\s*\)\s+VALUES\s+\(\s*$values\s*\)/is", $sql, "Bad sql: $sql");
  1706. }
  1707. /**
  1708. * Test UpdateSQL functions
  1709. * @dataProvider vardefProvider
  1710. * @param string $name
  1711. * @param array $defs
  1712. * @param array $data
  1713. * @param array $_
  1714. * @param array $result
  1715. */
  1716. public function testUpdateSQL($name, $defs, $data, $_, $result = null)
  1717. {
  1718. $name = "update$name";
  1719. $vardefs = array(
  1720. 'table' => $name,
  1721. 'fields' => $defs,
  1722. );
  1723. // ensure it has an ID
  1724. $vardefs['fields']['id'] = array (
  1725. 'name' => 'id',
  1726. 'type' => 'id',
  1727. 'required'=>true,
  1728. );
  1729. $vardefs['fields']['deleted'] = array (
  1730. 'name' => 'deleted',
  1731. 'type' => 'bool',
  1732. );
  1733. $obj = new TestSugarBean($name, $vardefs);
  1734. // regular fields
  1735. foreach($defs as $k => $v) {
  1736. if(isset($data[$k])) {
  1737. $obj->$k = $data[$k];
  1738. } else {
  1739. $obj->$k = null;
  1740. }
  1741. }
  1742. // set fixed ID
  1743. $obj->id = 'test_ID';
  1744. $sql = $this->_db->updateSQL($obj);
  1745. if(is_null($result)) {
  1746. $result = $_;
  1747. }
  1748. $names_i = array();
  1749. foreach($result as $k => $v) {
  1750. if($k == "id" || $k == 'deleted') continue;
  1751. $names_i[] = preg_quote("$k=$v");
  1752. }
  1753. if(empty($names_i)) {
  1754. $this->assertEquals("", $sql, "Bad sql: $sql");
  1755. return;
  1756. }
  1757. $names = join('\s*,\s*',$names_i);
  1758. $this->assertRegExp("/UPDATE $name\s+SET\s+$names\s+WHERE\s+$name.id\s*=\s*'test_ID' AND deleted=0/is", $sql, "Bad sql: $sql");
  1759. }
  1760. /**
  1761. * Test UpdateSQL functions
  1762. * @dataProvider vardefProvider
  1763. * @param string $name
  1764. * @param array $defs
  1765. * @param array $data
  1766. * @param array $_
  1767. * @param array $result
  1768. */
  1769. public function testUpdateSQLNoDeleted($name, $defs, $data, $_, $result = null)
  1770. {
  1771. $name = "updatenodel$name";
  1772. $vardefs = array(
  1773. 'table' => $name,
  1774. 'fields' => $defs,
  1775. );
  1776. // ensure it has an ID
  1777. $vardefs['fields']['id'] = array (
  1778. 'name' => 'id',
  1779. 'type' => 'id',
  1780. 'required'=>true,
  1781. );
  1782. unset($vardefs['fields']['deleted']);
  1783. $obj = new TestSugarBean($name, $vardefs);
  1784. // regular fields
  1785. foreach($defs as $k => $v) {
  1786. if(isset($data[$k])) {
  1787. $obj->$k = $data[$k];
  1788. } else {
  1789. $obj->$k = null;
  1790. }
  1791. }
  1792. // set fixed ID
  1793. $obj->id = 'test_ID';
  1794. $sql = $this->_db->updateSQL($obj);
  1795. if(is_null($result)) {
  1796. $result = $_;
  1797. }
  1798. $names_i = array();
  1799. foreach($result as $k => $v) {
  1800. if($k == "id" || $k == 'deleted') continue;
  1801. $names_i[] = preg_quote("$k=$v");
  1802. }
  1803. if(empty($names_i)) {
  1804. $this->assertEquals("", $sql, "Bad sql: $sql");
  1805. return;
  1806. }
  1807. $names = join('\s*,\s*',$names_i);
  1808. $this->assertRegExp("/UPDATE $name\s+SET\s+$names\s+WHERE\s+$name.id\s*=\s*'test_ID'/is", $sql, "Bad sql: $sql");
  1809. $this->assertNotContains(" AND deleted=0", $sql, "Bad sql: $sql");
  1810. }
  1811. /**
  1812. * Test the canInstall
  1813. * @return void
  1814. */
  1815. public function testCanInstall() {
  1816. $DBManagerClass = get_class($this->_db);
  1817. if(!method_exists($this->_db, 'version') || !method_exists($this->_db, 'canInstall'))
  1818. $this->markTestSkipped(
  1819. "Class {$DBManagerClass} doesn't implement canInstall or version methods");
  1820. $method = new ReflectionMethod($DBManagerClass, 'canInstall');
  1821. if($method->class == 'DBManager')
  1822. $this->markTestSkipped(
  1823. "Class {$DBManagerClass} or one of it's ancestors doesn't override DBManager's canInstall");
  1824. // First assuming that we are only running unit tests against a supported database :)
  1825. $this->assertTrue($this->_db->canInstall(), "Apparently we are not running this unit test against a supported database!!!");
  1826. $DBstub = $this->getMock($DBManagerClass, array('version'));
  1827. $DBstub->expects($this->any())
  1828. ->method('version')
  1829. ->will($this->returnValue('0.0.0')); // Expect that any supported version is higher than 0.0.0
  1830. $this->assertTrue(is_array($DBstub->canInstall()), "Apparently we do support version 0.0.0 in " . $DBManagerClass);
  1831. }
  1832. public function providerValidateQuery()
  1833. {
  1834. return array(
  1835. array(true, 'SELECT * FROM accounts'),
  1836. array(false, 'SELECT * FROM blablabla123'),
  1837. );
  1838. }
  1839. /**
  1840. * Test query validation
  1841. * @dataProvider providerValidateQuery
  1842. * @param $good
  1843. * @param $sql
  1844. * @return void
  1845. */
  1846. public function testValidateQuery($good, $sql)
  1847. {
  1848. $check = $this->_db->validateQuery($sql);
  1849. $this->assertEquals($good, $check);
  1850. }
  1851. public function testTextSizeHandling()
  1852. {
  1853. $tablename = 'testTextSize';// . mt_rand();
  1854. $fielddefs = array(
  1855. 'id' =>
  1856. array (
  1857. 'name' => 'id',
  1858. 'required'=>true,
  1859. 'type' => 'id',
  1860. ),
  1861. 'test' => array (
  1862. 'name' => 'test',
  1863. 'type' => 'longtext',
  1864. //'len' => '255',
  1865. ),
  1866. 'dummy' => array (
  1867. 'name' => 'dummy',
  1868. 'type' => 'longtext',
  1869. //'len' => '255',
  1870. ),
  1871. );
  1872. $this->createTableParams($tablename, $fielddefs, array());
  1873. $basestr = '0123456789abcdefghijklmnopqrstuvwxyz';
  1874. $str = $basestr;
  1875. while(strlen($str) < 159900)
  1876. {
  1877. $str .= $basestr;
  1878. }
  1879. for($i = 0; $i < 50; $i++)
  1880. {
  1881. $str .= $basestr;
  1882. $size = strlen($str);
  1883. //echo "$size\n";
  1884. $this->_db->insertParams($tablename, $fielddefs, array('id' => $size, 'test' => $str, 'dummy' => $str));
  1885. $select = "SELECT test FROM $tablename WHERE id = '{$size}'";
  1886. $strresult = $this->_db->getOne($select);
  1887. $this->assertEquals(0, mb_strpos($str, $strresult));
  1888. }
  1889. }
  1890. public function testGetIndicesContainsPrimary()
  1891. {
  1892. $indices = $this->_db->get_indices('accounts');
  1893. // find if any are primary
  1894. $found = false;
  1895. foreach($indices as $index)
  1896. {
  1897. if($index['type'] == "primary") {
  1898. $found = true;
  1899. break;
  1900. }
  1901. }
  1902. $this->assertTrue($found, 'Primary Key Not Found On Module');
  1903. }
  1904. /*
  1905. * testDBGuidGeneration
  1906. * Tests that the first 1000 DB generated GUIDs are unique
  1907. */
  1908. public function testDBGuidGeneration()
  1909. {
  1910. $guids = array();
  1911. $sql = "SELECT {$this->_db->getGuidSQL()} {$this->_db->getFromDummyTable()}";
  1912. for($i = 0; $i < 1000; $i++)
  1913. {
  1914. $newguid = $this->_db->getOne($sql);
  1915. $this->assertFalse(in_array($newguid, $guids), "'$newguid' already existed in the array of GUIDs!");
  1916. $guids []= $newguid;
  1917. }
  1918. }
  1919. }