Subversion-Projekte lars-tiefland.php_share

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
1 lars 1
<?php
2
// +----------------------------------------------------------------------+
3
// | PHP versions 4 and 5                                                 |
4
// +----------------------------------------------------------------------+
5
// | Copyright (c) 1998-2007 Lukas Smith, Lorenzo Alberton                |
6
// | All rights reserved.                                                 |
7
// +----------------------------------------------------------------------+
8
// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB  |
9
// | API as well as database abstraction for PHP applications.            |
10
// | This LICENSE is in the BSD license style.                            |
11
// |                                                                      |
12
// | Redistribution and use in source and binary forms, with or without   |
13
// | modification, are permitted provided that the following conditions   |
14
// | are met:                                                             |
15
// |                                                                      |
16
// | Redistributions of source code must retain the above copyright       |
17
// | notice, this list of conditions and the following disclaimer.        |
18
// |                                                                      |
19
// | Redistributions in binary form must reproduce the above copyright    |
20
// | notice, this list of conditions and the following disclaimer in the  |
21
// | documentation and/or other materials provided with the distribution. |
22
// |                                                                      |
23
// | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken,    |
24
// | Lukas Smith nor the names of his contributors may be used to endorse |
25
// | or promote products derived from this software without specific prior|
26
// | written permission.                                                  |
27
// |                                                                      |
28
// | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS  |
29
// | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT    |
30
// | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS    |
31
// | FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE      |
32
// | REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,          |
33
// | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
34
// | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS|
35
// |  OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED  |
36
// | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT          |
37
// | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY|
38
// | WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE          |
39
// | POSSIBILITY OF SUCH DAMAGE.                                          |
40
// +----------------------------------------------------------------------+
41
// | Author: Lorenzo Alberton <l dot alberton at quipo dot it>            |
42
// +----------------------------------------------------------------------+
43
//
44
// $Id: MDB2_reverse_testcase.php,v 1.46 2007/03/29 18:18:06 quipo Exp $
45
 
46
require_once 'MDB2_testcase.php';
47
 
48
class MDB2_Reverse_TestCase extends MDB2_TestCase
49
{
50
    //test table name (it is dynamically created/dropped)
51
    var $table       = 'testtable';
52
    var $fields      = array();
53
    var $indices     = array();
54
    var $constraints = array();
55
 
56
    function setUp() {
57
        parent::setUp();
58
        $this->db->loadModule('Reverse', null, true);
59
        $this->db->loadModule('Manager', null, true);
60
 
61
        //Table structure
62
        $this->fields = array(
63
            'id' => array(  //PK
64
                'type'     => 'integer',
65
                'unsigned' => 1,
66
                'notnull'  => 1,
67
                'default'  => 0,
68
                'length'  => 4,
69
            ),
70
            'id2' => array( //UNIQUE_MULTIFIELD(1/2)
71
                'type'     => 'integer',
72
                'unsigned' => 1,
73
                'notnull'  => 1,
74
                'default'  => 0,
75
            ),
76
            'id3' => array( //UNIQUE_MULTIFIELD(2/2)
77
                'type'     => 'integer',
78
                'unsigned' => 1,
79
                'notnull'  => 1,
80
                'default'  => 0,
81
            ),
82
            'id4' => array( //UNIQUE
83
                'type'     => 'integer',
84
                'unsigned' => 1,
85
                'notnull'  => 1,
86
                'default'  => 0,
87
            ),
88
            'somename' => array( //NORMAL INDEX
89
                'type'   => 'text',
90
                'length' => 12,
91
            ),
92
            'somedescription' => array( //INDEX_MULTIFIELD(1/2)
93
                'type'   => 'text',
94
                'length' => 12,
95
            ),
96
            'sex' => array( //INDEX_MULTIFIELD(2/2)
97
                'type' => 'text',
98
                'length' => 1,
99
                'default' => 'M',
100
            ),
101
        );
102
 
103
        if (!$this->tableExists($this->table)) {
104
            $this->db->manager->createTable($this->table, $this->fields);
105
        }
106
    }
107
 
108
    function tearDown() {
109
        if ($this->tableExists($this->table)) {
110
            $this->db->manager->dropTable($this->table);
111
        }
112
        $this->db->popExpect();
113
        unset($this->dsn);
114
        if (!PEAR::isError($this->db->manager)) {
115
            $this->db->disconnect();
116
        }
117
        unset($this->db);
118
    }
119
 
120
    function setUpIndices()
121
    {
122
        //Indices definition
123
        $this->indices = array(
124
            'sometestindex' => array(
125
                'fields' => array(
126
                    'somename' => array(
127
                        'sorting' => 'ascending',
128
                    ),
129
                ),
130
                'unique' => false,
131
            ),
132
            'multipletestindex' => array(
133
                'fields' => array(
134
                    'somedescription' => array(
135
                        'sorting' => 'ascending',
136
                    ),
137
                    'sex' => array(
138
                        'sorting' => 'ascending',
139
                    ),
140
                ),
141
            ),
142
        );
143
        foreach ($this->indices as $index_name => $index) {
144
            $result = $this->db->manager->createIndex($this->table, $index_name, $index);
145
            $this->assertFalse(PEAR::isError($result), 'Error creating index: '.$index_name);
146
            if (PEAR::isError($result)) {
147
                break;
148
            }
149
        }
150
        return PEAR::isError($result);
151
    }
152
 
153
    function setUpConstraints()
154
    {
155
        //Constraints definition
156
        $this->constraints = array(
157
            'pkfield' => array(
158
                'fields' => array(
159
                    'id' => array(
160
                        'sorting' => 'ascending',
161
                    ),
162
                ),
163
                'primary' => true,
164
            ),
165
            'multipleunique' => array(
166
                'fields' => array(
167
                    'id2' => array(
168
                        'sorting' => 'ascending',
169
                    ),
170
                    'id3' => array(
171
                        'sorting' => 'ascending',
172
                    ),
173
                ),
174
                'unique' => true,
175
            ),
176
            'singleunique' => array(
177
                'fields' => array(
178
                    'id4' => array(
179
                        'sorting' => 'ascending',
180
                    ),
181
                ),
182
                'unique' => true,
183
            ),
184
        );
185
        foreach ($this->constraints as $constraint_name => $constraint) {
186
            $result = $this->db->manager->createConstraint($this->table, $constraint_name, $constraint);
187
            $this->assertFalse(PEAR::isError($result), 'Error creating constraint: '.$constraint_name);
188
            if (PEAR::isError($result)) {
189
                break;
190
            }
191
        }
192
        return PEAR::isError($result);
193
    }
194
 
195
    /**
196
     * Test tableInfo('table_name')
197
     */
198
    function testTableInfo()
199
    {
200
        if (!$this->methodExists($this->db->reverse, 'tableInfo')) {
201
            return;
202
        }
203
 
204
        $table_info = $this->db->reverse->tableInfo($this->table);
205
        if (PEAR::isError($table_info)) {
206
            $this->assertTrue(false, 'Error in tableInfo(): '.$table_info->getMessage());
207
        } else {
208
            $this->assertEquals(count($this->fields), count($table_info), 'The number of fields retrieved is different from the expected one');
209
            foreach ($table_info as $field_info) {
210
                $this->assertEquals($this->table, $field_info['table'], "the table name is not correct");
211
                if (!array_key_exists(strtolower($field_info['name']), $this->fields)) {
212
                    $this->assertTrue(false, 'Field names do not match ('.$field_info['name'].' is unknown)');
213
                }
214
                //expand test, for instance adding a check on types...
215
            }
216
        }
217
 
218
        if (!$this->supported('result_introspection')) {
219
            return;
220
        }
221
 
222
        $result = $this->db->query('SELECT * FROM '.$this->table);
223
        $table_info = $this->db->reverse->tableInfo($result);
224
        if (PEAR::isError($table_info)) {
225
            $this->assertTrue(false, 'Error in tableInfo(): '.$table_info->getMessage());
226
        } else {
227
            $this->assertEquals(count($this->fields), count($table_info), 'The number of fields retrieved is different from the expected one');
228
            foreach ($table_info as $field_info) {
229
                //not all the drivers are capable of returning the table name,
230
                //and may return an empty value
231
                if (!empty($field_info['table'])) {
232
                    $this->assertEquals($this->table, $field_info['table'], "the table name is not correct");
233
                }
234
                if (!array_key_exists(strtolower($field_info['name']), $this->fields)) {
235
                    $this->assertTrue(false, 'Field names do not match ('.$field_info['name'].' is unknown)');
236
                }
237
                //expand test, for instance adding a check on types...
238
            }
239
        }
240
        $result->free();
241
    }
242
 
243
    /**
244
     * Test getTableFieldDefinition($table, $field_name)
245
     */
246
    function testGetTableFieldDefinition()
247
    {
248
        if (!$this->methodExists($this->db->reverse, 'getTableFieldDefinition')) {
249
            return;
250
        }
251
 
252
        //test integer not null
253
        $field_info = $this->db->reverse->getTableFieldDefinition($this->table, 'id');
254
        if (PEAR::isError($field_info)) {
255
            $this->assertTrue(false, 'Error in getTableFieldDefinition(): '.$field_info->getMessage());
256
        } else {
257
            $field_info = array_shift($field_info);
258
            $this->assertEquals('integer', $field_info['type'], 'The field type is different from the expected one');
259
            $expected_length = ($this->db->phptype == 'oci8') ? 10 : 4;
260
            $this->assertEquals($expected_length, $field_info['length'], 'The field length is different from the expected one');
261
            $this->assertTrue($field_info['notnull'], 'The field can be null unlike it was expected');
262
            $this->assertEquals('0', $field_info['default'], 'The field default value is different from the expected one');
263
        }
264
 
265
        //test blob
266
        $field_info = $this->db->reverse->getTableFieldDefinition('files', 'picture');
267
        if (PEAR::isError($field_info)) {
268
            $this->assertTrue(false, 'Error in getTableFieldDefinition(): '.$field_info->getMessage());
269
        } else {
270
            $field_info = array_shift($field_info);
271
            $this->assertEquals($field_info['type'], 'blob', 'The field type is different from the expected one');
272
            $this->assertFalse($field_info['notnull'], 'The field cannot be null unlike it was expected');
273
        }
274
 
275
        //test varchar(100) not null
276
        $field_info = $this->db->reverse->getTableFieldDefinition('users', 'user_name');
277
        if (PEAR::isError($field_info)) {
278
            $this->assertTrue(false, 'Error in getTableFieldDefinition(): '.$field_info->getMessage());
279
        } else {
280
            $field_info = array_shift($field_info);
281
            $this->assertEquals('text', $field_info['type'], 'The field type is different from the expected one');
282
            $this->assertEquals(12, $field_info['length'], 'The field length is different from the expected one');
283
            $this->assertFalse($field_info['notnull'], 'The field can be null unlike it was expected');
284
            $this->assertNull($field_info['default'], 'The field default value is different from the expected one');
285
            $this->assertFalse($field_info['fixed'], 'The field fixed value is different from the expected one');
286
        }
287
 
288
        //test decimal
289
        $field_info = $this->db->reverse->getTableFieldDefinition('users', 'quota');
290
        if (PEAR::isError($field_info)) {
291
            $this->assertTrue(false, 'Error in getTableFieldDefinition(): '.$field_info->getMessage());
292
        } else {
293
            $field_info = array_shift($field_info);
294
            $this->assertEquals('decimal', $field_info['type'], 'The field type is different from the expected one');
295
            $expected_length = ($this->db->phptype == 'oci8') ? '22,2' : '18,2';
296
            $this->assertEquals($expected_length, $field_info['length'], 'The field length is different from the expected one');
297
        }
298
    }
299
 
300
    /**
301
     * Test getTableIndexDefinition($table, $index_name)
302
     */
303
    function testGetTableIndexDefinition()
304
    {
305
        if (!$this->methodExists($this->db->reverse, 'getTableIndexDefinition')) {
306
            return;
307
        }
308
 
309
        $this->setUpIndices();
310
 
311
        //test index names
312
        foreach ($this->indices as $index_name => $index) {
313
            $index_info = $this->db->reverse->getTableIndexDefinition($this->table, $index_name);
314
            if (PEAR::isError($index_info)) {
315
                $this->assertFalse(true, 'Error getting table index definition');
316
            } else {
317
                $field_names = array_keys($index['fields']);
318
                $this->assertEquals($field_names, array_keys($index_info['fields']), 'Error listing index fields');
319
            }
320
        }
321
 
322
        //test INDEX
323
        $index_name = 'sometestindex';
324
        $index_info = $this->db->reverse->getTableIndexDefinition($this->table, $index_name);
325
        if (PEAR::isError($index_info)) {
326
            $this->assertTrue(false, 'Error in getTableIndexDefinition(): '.$index_info->getMessage());
327
        } else {
328
            $this->assertEquals(1, count($index_info['fields']), 'The INDEX is not on one field unlike it was expected');
329
            $expected_fields = array_keys($this->indices[$index_name]['fields']);
330
            $actual_fields = array_keys($index_info['fields']);
331
            $this->assertEquals($expected_fields, $actual_fields, 'The INDEX field names don\'t match');
332
            $this->assertEquals(1, $index_info['fields'][$expected_fields[0]]['position'], 'The field position in the INDEX is not correct');
333
        }
334
 
335
        //test INDEX on MULTIPLE FIELDS
336
        $index_name = 'multipletestindex';
337
        $index_info = $this->db->reverse->getTableIndexDefinition($this->table, $index_name);
338
        if (PEAR::isError($index_info)) {
339
            $this->assertTrue(false, 'Error in getTableIndexDefinition(): '.$index_info->getMessage());
340
        } else {
341
            $this->assertEquals(2, count($index_info['fields']), 'The INDEX is not on two fields unlike it was expected');
342
            $expected_fields = array_keys($this->indices[$index_name]['fields']);
343
            $actual_fields = array_keys($index_info['fields']);
344
            $this->assertEquals($expected_fields, $actual_fields, 'The INDEX field names don\'t match');
345
            $this->assertEquals(1, $index_info['fields'][$expected_fields[0]]['position'], 'The field position in the INDEX is not correct');
346
            $this->assertEquals(2, $index_info['fields'][$expected_fields[1]]['position'], 'The field position in the INDEX is not correct');
347
        }
348
 
349
        if (!$this->setUpConstraints()) {
350
            return;
351
        }
352
        //constraints should NOT be listed
353
        foreach (array_keys($this->constraints) as $constraint_name) {
354
            $this->db->expectError(MDB2_ERROR_NOT_FOUND);
355
            $result = $this->db->reverse->getTableIndexDefinition($this->table, $constraint_name);
356
            $this->assertTrue(PEAR::isError($result), 'Error listing index definition, this is a CONSTRAINT');
357
        }
358
 
359
        //test index created WITHOUT using MDB2 (i.e. without the "_idx" suffix)
360
        //NB: MDB2 > v.2.3.0 provides a fallback mechanism
361
    }
362
 
363
    /**
364
     * Test testGetTableConstraintDefinition($table, $constraint_name)
365
     */
366
    function testGetTableConstraintDefinition()
367
    {
368
        if (!$this->methodExists($this->db->reverse, 'getTableConstraintDefinition')) {
369
            return;
370
        }
371
 
372
        if (!$this->setUpConstraints()) {
373
            return;
374
        }
375
 
376
        //test constraint names
377
        foreach ($this->constraints as $constraint_name => $constraint) {
378
            $this->db->expectError(MDB2_ERROR_NOT_FOUND);
379
            $result = $this->db->reverse->getTableConstraintDefinition($this->table, $constraint_name);
380
            $this->db->popExpect();
381
            if (PEAR::isError($result) && isset($constraint['primary']) && $constraint['primary']) {
382
                echo 'Error reading primary constraint, trying with name "primary" instead .. ';
383
                $constraint_name = 'primary';
384
                $result = $this->db->reverse->getTableConstraintDefinition($this->table, $constraint_name);
385
            }
386
            if (PEAR::isError($result)) {
387
                $this->assertFalse(true, 'Error getting table constraint definition ('.$constraint_name.')');
388
            } else {
389
                $constraint_names = array_keys($constraint['fields']);
390
                $this->assertEquals($constraint_names, array_keys($result['fields']), 'Error listing constraint fields');
391
            }
392
        }
393
 
394
        $this->setUpIndices();
395
        //indices should NOT be listed
396
        foreach (array_keys($this->indices) as $index_name) {
397
            $this->db->expectError(MDB2_ERROR_NOT_FOUND);
398
            $result = $this->db->reverse->getTableConstraintDefinition($this->table, $index_name);
399
            $this->db->popExpect();
400
            $this->assertTrue(PEAR::isError($result), 'Error listing constraint definition, this is a normal INDEX');
401
        }
402
 
403
        //test PK
404
        $this->db->expectError(MDB2_ERROR_NOT_FOUND);
405
        $constraint_info = $this->db->reverse->getTableConstraintDefinition($this->table, 'pkfield');
406
        $this->db->popExpect();
407
        if (PEAR::isError($constraint_info)) {
408
            echo 'Error reading primary constraint, trying with name "primary" instead .. ';
409
            $constraint_info = $this->db->reverse->getTableConstraintDefinition($this->table, 'primary');
410
        }
411
        if (PEAR::isError($constraint_info)) {
412
            $this->assertTrue(false, 'Error in getTableConstraintDefinition(): '.$constraint_info->getMessage());
413
        } else {
414
            $this->assertTrue($constraint_info['primary'], 'The field is not a PK unlike it was expected');
415
        }
416
 
417
        //test UNIQUE
418
        $constraint_name = 'singleunique';
419
        $constraint_info = $this->db->reverse->getTableConstraintDefinition($this->table, $constraint_name);
420
        if (PEAR::isError($constraint_info)) {
421
            $this->assertTrue(false, 'Error in getTableConstraintDefinition(): '.$constraint_info->getMessage());
422
        } else {
423
            $this->assertTrue($constraint_info['unique'], 'The field is not a PK unlike it was expected');
424
            $this->assertTrue(empty($constraint_info['primary']), 'The field is a PK unlike it was expected');
425
            $this->assertEquals(1, count($constraint_info['fields']), 'The UNIQUE INDEX is not on one field unlike it was expected');
426
            $expected_fields = array_keys($this->constraints[$constraint_name]['fields']);
427
            $actual_fields = array_keys($constraint_info['fields']);
428
            $this->assertEquals($expected_fields, $actual_fields, 'The UNIQUE INDEX field names don\'t match');
429
            $this->assertEquals(1, $constraint_info['fields'][$expected_fields[0]]['position'], 'The field position in the INDEX is not correct');
430
        }
431
 
432
        //test UNIQUE on MULTIPLE FIELDS
433
        $constraint_name = 'multipleunique';
434
        $constraint_info = $this->db->reverse->getTableConstraintDefinition($this->table, $constraint_name);
435
        if (PEAR::isError($constraint_info)) {
436
            $this->assertTrue(false, 'Error in getTableConstraintDefinition(): '.$constraint_info->getMessage());
437
        } else {
438
            $this->assertTrue($constraint_info['unique'], 'The field is not a PK unlike it was expected');
439
            $this->assertTrue(empty($constraint_info['primary']), 'The field is a PK unlike it was expected');
440
            $this->assertEquals(2, count($constraint_info['fields']), 'The UNIQUE INDEX is not on two fields unlike it was expected');
441
            $expected_fields = array_keys($this->constraints[$constraint_name]['fields']);
442
            $actual_fields = array_keys($constraint_info['fields']);
443
            $this->assertEquals($expected_fields, $actual_fields, 'The UNIQUE INDEX field names don\'t match');
444
            $this->assertEquals(1, $constraint_info['fields'][$expected_fields[0]]['position'], 'The field position in the INDEX is not correct');
445
            $this->assertEquals(2, $constraint_info['fields'][$expected_fields[1]]['position'], 'The field position in the INDEX is not correct');
446
        }
447
    }
448
 
449
    /**
450
     * Test getSequenceDefinition($sequence)
451
     */
452
    function testGetSequenceDefinition() {
453
        //setup
454
        $this->db->loadModule('Manager', null, true);
455
        $sequence = 'test_sequence';
456
        $sequences = $this->db->manager->listSequences();
457
        if (!in_array($sequence, $sequences)) {
458
            $result = $this->db->manager->createSequence($sequence);
459
            $this->assertFalse(PEAR::isError($result), 'Error creating a sequence');
460
        }
461
 
462
        //test
463
        $start = $this->db->nextId($sequence);
464
        $def = $this->db->reverse->getSequenceDefinition($sequence);
465
        $this->assertEquals($start+1, (isset($def['start']) ? $def['start'] : 1), 'Error getting sequence definition');
466
 
467
        //cleanup
468
        $result = $this->db->manager->dropSequence($sequence);
469
        $this->assertFalse(PEAR::isError($result), 'Error dropping a sequence');
470
    }
471
 
472
    /**
473
     * Test getTriggerDefinition($trigger)
474
     */
475
    function testGetTriggerDefinition() {
476
        //setup
477
        $trigger_name = 'test_trigger';
478
 
479
        include_once 'MDB2_nonstandard.php';
480
        $nonstd =& MDB2_nonstandard::factory($this->db, $this);
481
        if (PEAR::isError($nonstd)) {
482
            $this->assertTrue(false, 'Cannot create trigger: '.$nonstd->getMessage());
483
            return;
484
        }
485
 
486
        $result = $nonstd->createTrigger($trigger_name, $this->table);
487
        if (PEAR::isError($result)) {
488
            $this->assertTrue(false, 'Cannot create trigger: '.$result->getMessage());
489
            return;
490
        }
491
 
492
        //test
493
        $def = $this->db->reverse->getTriggerDefinition($trigger_name);
494
        if (PEAR::isError($def)) {
495
            $this->assertTrue(false, 'getTriggerDefinition: '.$def->getMessage());
496
        } else {
497
            $nonstd->checkTrigger($trigger_name, $this->table, $def);
498
        }
499
 
500
        //cleanup
501
        $result = $nonstd->dropTrigger($trigger_name, $this->table);
502
        if (PEAR::isError($result)) {
503
            $this->assertTrue(false, 'Error dropping the trigger: '.$result->getMessage());
504
            return;
505
        }
506
    }
507
}
508
?>