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