~ubuntu-branches/ubuntu/lucid/phpmyadmin/lucid

« back to all changes in this revision

Viewing changes to libraries/Index.class.php

  • Committer: Bazaar Package Importer
  • Author(s): Michal Čihař
  • Date: 2009-06-30 14:05:13 UTC
  • mfrom: (1.2.1 upstream) (36.1.2 karmic)
  • Revision ID: james.westby@ubuntu.com-20090630140513-hz71do3sij2jhm4s
* New upstream version fixing XSS (PMASA-2009-5).
* Document no empty password in README.Debian and the shipped sample
  configuration file (LP: #388703).
* Install service file for avahi (if web service enabled and if avahi is
  installed) (LP: #369244).
* Mention protecting of setup if not using provided configuration snippets
  for webservers.
* Call ucf with --debconf-ok in postrm (Closes: #534894).

Show diffs side-by-side

added added

removed removed

Lines of Context:
3
3
/**
4
4
 * holds the datasbe index class
5
5
 *
6
 
 * @version $Id: Index.class.php 11647 2008-10-12 13:03:57Z lem9 $
 
6
 * @version $Id: Index.class.php 11986 2008-11-24 11:05:40Z nijel $
 
7
 * @package phpMyAdmin
7
8
 */
8
9
 
9
10
/**
10
11
 * @since phpMyAdmin 3.0.0
11
 
 * 
 
12
 *
 
13
 * @package phpMyAdmin
12
14
 */
13
15
class PMA_Index
14
16
{
18
20
     * @var array
19
21
     */
20
22
    protected static $_registry = array();
21
 
    
 
23
 
22
24
    /**
23
25
     * @var string The name of the schema
24
26
     */
25
27
    protected $_schema = '';
26
 
    
 
28
 
27
29
    /**
28
30
     * @var string The name of the table
29
31
     */
30
32
    protected $_table = '';
31
 
    
 
33
 
32
34
    /**
33
35
     * @var string The name of the index
34
36
     */
35
37
    protected $_name = '';
36
 
    
 
38
 
37
39
    /**
38
40
     * Columns in index
39
41
     *
40
42
     * @var array
41
43
     */
42
44
    protected $_columns = array();
43
 
    
 
45
 
44
46
    /**
45
47
     * The index method used (BTREE, FULLTEXT, HASH, RTREE).
46
48
     *
54
56
     * @var string
55
57
     */
56
58
    protected $_choice = '';
57
 
    
 
59
 
58
60
    /**
59
61
     * Various remarks.
60
62
     *
61
63
     * @var string
62
64
     */
63
65
    protected $_remarks = '';
64
 
    
 
66
 
65
67
    /**
66
 
     * Any comment provided for the index with a COMMENT attribute when the 
 
68
     * Any comment provided for the index with a COMMENT attribute when the
67
69
     * index was created.
68
70
     *
69
71
     * @var string
70
72
     */
71
73
    protected $_comment = '';
72
 
    
 
74
 
73
75
    /**
74
 
     * @var integer 0 if the index cannot contain duplicates, 1 if it can. 
 
76
     * @var integer 0 if the index cannot contain duplicates, 1 if it can.
75
77
     */
76
78
    protected $_non_unique = 0;
77
 
    
 
79
 
78
80
    /**
79
81
     * Indicates how the key is packed. NULL if it is not.
80
82
     *
81
83
     * @var string
82
84
     */
83
85
    protected $_packed = null;
84
 
    
 
86
 
85
87
    /**
86
88
     * Constructor
87
89
     *
92
94
    {
93
95
        $this->set($params);
94
96
    }
95
 
    
 
97
 
96
98
    static public function singleton($schema, $table, $index_name = '')
97
99
    {
98
100
        PMA_Index::_loadIndexes($table, $schema);
107
109
            return PMA_Index::$_registry[$schema][$table][$index_name];
108
110
        }
109
111
    }
110
 
    
 
112
 
111
113
    /**
112
114
     * returns an array with all indexes from the given table
113
115
     *
120
122
    static public function getFromTable($table, $schema)
121
123
    {
122
124
        PMA_Index::_loadIndexes($table, $schema);
123
 
        
 
125
 
124
126
        if (isset(PMA_Index::$_registry[$schema][$table])) {
125
127
            return PMA_Index::$_registry[$schema][$table];
126
128
        } else {
127
129
            return array();
128
130
        }
129
131
    }
130
 
    
 
132
 
131
133
    /**
132
134
     * return primary if set, false otherwise
133
135
     *
140
142
    static public function getPrimary($table, $schema)
141
143
    {
142
144
        PMA_Index::_loadIndexes($table, $schema);
143
 
        
 
145
 
144
146
        if (isset(PMA_Index::$_registry[$schema][$table]['PRIMARY'])) {
145
147
            return PMA_Index::$_registry[$schema][$table]['PRIMARY'];
146
148
        } else {
147
149
            return false;
148
150
        }
149
151
    }
150
 
    
 
152
 
151
153
    /**
152
154
     * Load index data for table
153
155
     *
165
167
        if (isset(PMA_Index::$_registry[$schema][$table])) {
166
168
            return true;
167
169
        }
168
 
        
 
170
 
169
171
        $_raw_indexes = PMA_DBI_fetch_result('SHOW INDEX FROM ' . PMA_backquote($schema) . '.' . PMA_backquote($table));
170
172
        foreach ($_raw_indexes as $_each_index) {
171
173
            $_each_index['Schema'] = $schema;
175
177
            } else {
176
178
                $key = PMA_Index::$_registry[$schema][$table][$_each_index['Key_name']];
177
179
            }
178
 
            
 
180
 
179
181
            $key->addColumn($_each_index);
180
182
        }
181
 
        
 
183
 
182
184
        return true;
183
185
    }
184
 
    
 
186
 
185
187
    /**
186
188
     * Add column to index
187
189
     *
195
197
            $this->_columns[$params['Column_name']] = new PMA_Index_Column($params);
196
198
        }
197
199
    }
198
 
    
 
200
 
199
201
    public function addColumns($columns)
200
202
    {
201
203
        $_columns = array();
202
 
        
 
204
 
203
205
        if (isset($columns['names'])) {
204
206
            // coming from form
205
207
            // $columns[names][]
217
219
            // ...
218
220
            $_columns = $columns;
219
221
        }
220
 
        
 
222
 
221
223
        foreach ($_columns as $column) {
222
224
            $this->addColumn($column);
223
225
        }
224
226
    }
225
 
    
 
227
 
226
228
    /**
227
229
     * Returns true if $column indexed in this index
228
230
     *
234
236
    {
235
237
        return isset($this->_columns[$column]);
236
238
    }
237
 
    
 
239
 
238
240
    public function set($params)
239
241
    {
240
242
        if (isset($params['columns'])) {
274
276
            $this->_choice = 'INDEX';
275
277
        }
276
278
    }
277
 
    
 
279
 
278
280
    public function getColumnCount()
279
281
    {
280
282
        return count($this->_columns);
281
283
    }
282
 
    
 
284
 
283
285
    public function getComment()
284
286
    {
285
287
        return $this->_comment;
286
288
    }
287
 
    
 
289
 
288
290
    public function getRemarks()
289
291
    {
290
292
        return $this->_remarks;
291
293
    }
292
 
    
 
294
 
293
295
    public function getComments()
294
296
    {
295
297
        $comments = $this->getRemarks();
297
299
            $comments .= "\n";
298
300
        }
299
301
        $comments .= $this->getComment();
300
 
        
 
302
 
301
303
        return $comments;
302
304
    }
303
 
    
 
305
 
304
306
    public function getType()
305
307
    {
306
308
        return $this->_type;
307
309
    }
308
 
    
 
310
 
309
311
    /**
310
 
     * Return a list of all index choices 
 
312
     * Return a list of all index choices
311
313
     *
312
 
     * @return  array index choices 
 
314
     * @return  array index choices
313
315
     */
314
316
    static public function getIndexChoices()
315
317
    {
318
320
            'INDEX',
319
321
            'UNIQUE',
320
322
            'FULLTEXT',
321
 
        );        
 
323
        );
322
324
    }
323
325
 
324
326
    public function generateIndexSelector()
325
327
    {
326
328
        $html_options = '';
327
 
        
 
329
 
328
330
        foreach (PMA_Index::getIndexChoices() as $each_index_choice) {
329
331
            if ($each_index_choice === 'PRIMARY'
330
332
             && $this->_choice !== 'PRIMARY'
336
338
                 . (($this->_choice == $each_index_choice) ? ' selected="selected"' : '')
337
339
                 . '>'. $each_index_choice . '</option>' . "\n";
338
340
        }
339
 
        
 
341
 
340
342
        return $html_options;
341
343
    }
342
 
    
 
344
 
343
345
    public function getPacked()
344
346
    {
345
347
        return $this->_packed;
346
348
    }
347
 
    
 
349
 
348
350
    public function isPacked($as_text = false)
349
351
    {
350
352
        if ($as_text) {
358
360
                '1' => true,
359
361
            );
360
362
        }
361
 
        
 
363
 
362
364
        if (null === $this->_packed) {
363
365
            return $r[0];
364
366
        }
365
 
        
 
367
 
366
368
        return $this->_packed;
367
369
    }
368
 
    
 
370
 
369
371
    public function getNonUnique()
370
372
    {
371
373
        return $this->_non_unique;
372
374
    }
373
 
    
 
375
 
374
376
    public function isUnique($as_text = false)
375
377
    {
376
378
        if ($as_text) {
384
386
                '1' => false,
385
387
            );
386
388
        }
387
 
        
 
389
 
388
390
        return $r[$this->_non_unique];
389
391
    }
390
 
    
 
392
 
391
393
    public function getName()
392
394
    {
393
395
        return $this->_name;
394
396
    }
395
 
    
 
397
 
396
398
    public function setName($name)
397
399
    {
398
400
        $this->_name = (string) $name;
399
401
    }
400
 
    
 
402
 
401
403
    public function getColumns()
402
404
    {
403
405
        return $this->_columns;
404
406
    }
405
 
    
 
407
 
406
408
    /**
407
409
     * Show index data
408
410
     *
421
423
        if (count($indexes) < 1) {
422
424
            return PMA_Message::warning('strNoIndex')->getDisplay();
423
425
        }
424
 
        
 
426
 
425
427
        $r = '';
426
 
        
427
 
        $r .= '<h2>' . $GLOBALS['strIndexes'] . ': '; 
 
428
 
 
429
        $r .= '<h2>' . $GLOBALS['strIndexes'] . ': ';
428
430
        $r .= PMA_showMySQLDocu('optimization', 'optimizing-database-structure');
429
431
        $r .= '</h2>';
430
432
        $r .= '<table>';
445
447
        $r .= '</tr>';
446
448
        $r .= '</thead>';
447
449
        $r .= '<tbody>';
448
 
        
 
450
 
449
451
        $odd_row = true;
450
452
        foreach ($indexes as $index) {
451
453
            $row_span = ' rowspan="' . $index->getColumnCount() . '" ';
452
 
    
 
454
 
453
455
            $r .= '<tr class="' . ($odd_row ? 'odd' : 'even') . '">';
454
 
            
 
456
 
455
457
            if (! $print_mode) {
456
458
                $this_params = $GLOBALS['url_params'];
457
459
                $this_params['index'] = $index->getName();
459
461
                   . '    <a href="tbl_indexes.php' . PMA_generate_common_url($this_params)
460
462
                   . '">' . PMA_getIcon('b_edit.png', $GLOBALS['strEdit']) . '</a>'
461
463
                   . '</td>' . "\n";
462
 
    
 
464
 
463
465
                $this_params = $GLOBALS['url_params'];
464
466
                if ($index->getName() == 'PRIMARY') {
465
467
                    $this_params['sql_query'] = 'ALTER TABLE ' . PMA_backquote($table) . ' DROP PRIMARY KEY';
470
472
                    $this_params['zero_rows'] = sprintf($GLOBALS['strIndexHasBeenDropped'], $index->getName());
471
473
                    $js_msg      = PMA_jsFormat('ALTER TABLE ' . $table . ' DROP INDEX ' . $index->getName());
472
474
                }
473
 
    
 
475
 
474
476
                $r .= '<td ' . $row_span . '>'
475
477
                   . '    <a href="sql.php' . PMA_generate_common_url($this_params)
476
 
                   . '" onclick="return confirmLink(this, \'' . $js_msg . '\')">' 
 
478
                   . '" onclick="return confirmLink(this, \'' . $js_msg . '\')">'
477
479
                   . PMA_getIcon('b_drop.png', $GLOBALS['strDrop'])  . '</a>'
478
480
                   . '</td>' . "\n";
479
481
            }
480
 
    
 
482
 
481
483
            $r .= '<th ' . $row_span . '>' . htmlspecialchars($index->getName()) . '</th>';
482
484
            $r .= '<td ' . $row_span . '>' . htmlspecialchars($index->getType()) . '</td>';
483
485
            $r .= '<td ' . $row_span . '>' . $index->isUnique(true) . '</td>';
484
486
            $r .= '<td ' . $row_span . '>' . $index->isPacked(true) . '</td>';
485
 
               
 
487
 
486
488
            foreach ($index->getColumns() as $column) {
487
489
                if ($column->getSeqInIndex() > 1) {
488
490
                    $r .= '<tr class="' . ($odd_row ? 'odd' : 'even') . '">';
497
499
                $r .= '<td>' . htmlspecialchars($column->getNull()) . '</td>';
498
500
 
499
501
                if ($column->getSeqInIndex() == 1) {
500
 
                    $r .= '<td ' . $row_span . '>' 
 
502
                    $r .= '<td ' . $row_span . '>'
501
503
                        . htmlspecialchars($index->getComments()) . '</td>';
502
504
                }
503
505
                $r .= '</tr>';
504
506
            } // end foreach $index['Sequences']
505
 
            
 
507
 
506
508
            $odd_row = ! $odd_row;
507
509
        } // end while
508
510
        $r .= '</tbody>';
509
511
        $r .= '</table>';
510
 
        
 
512
 
511
513
        if (! $print_mode) {
512
514
            $r .= PMA_Index::findDuplicates($table, $schema);
513
515
        }
514
 
        
 
516
 
515
517
        return $r;
516
518
    }
517
 
    
 
519
 
518
520
    public function getCompareData()
519
521
    {
520
522
        $data = array(
522
524
            'Packed'        => $this->_packed,
523
525
            'Index_type'    => $this->_type,
524
526
        );
525
 
        
 
527
 
526
528
        foreach ($this->_columns as $column) {
527
529
            $data['columns'][] = $column->getCompareData();
528
530
        }
529
 
        
 
531
 
530
532
        return $data;
531
533
    }
532
 
    
 
534
 
533
535
    /**
534
536
     * Function to check over array of indexes and look for common problems
535
537
     *
547
549
    static public function findDuplicates($table, $schema)
548
550
    {
549
551
        $indexes = PMA_Index::getFromTable($table, $schema);
550
 
    
 
552
 
551
553
        $output  = '';
552
 
        
 
554
 
553
555
        // count($indexes) < 2:
554
556
        //   there is no need to check if there less than two indexes
555
557
        if (count($indexes) < 2) {
556
558
            return $output;
557
559
        }
558
 
    
 
560
 
559
561
        // remove last index from stack and ...
560
562
        while ($while_index = array_pop($indexes)) {
561
563
            // ... compare with every remaining index in stack
563
565
                if ($each_index->getCompareData() !== $while_index->getCompareData()) {
564
566
                    continue;
565
567
                }
566
 
                
 
568
 
567
569
                // did not find any difference
568
570
                // so it makes no sense to have this two equal indexes
569
 
    
 
571
 
570
572
                $message = PMA_Message::warning('strIndexesSeemEqual');
571
573
                $message->addParam($each_index->getName());
572
574
                $message->addParam($while_index->getName());
573
575
                $output .= $message->getDisplay();
574
 
    
 
576
 
575
577
                // there is no need to check any further indexes if we have already
576
578
                // found that this one has a duplicate
577
579
                continue 2;
581
583
    }
582
584
}
583
585
 
 
586
/**
 
587
 * @package phpMyAdmin
 
588
 */
584
589
class PMA_Index_Column
585
590
{
586
591
    /**
587
592
     * @var string The column name
588
593
     */
589
594
    protected $_name = '';
590
 
    
 
595
 
591
596
    /**
592
 
     * @var integer The column sequence number in the index, starting with 1. 
 
597
     * @var integer The column sequence number in the index, starting with 1.
593
598
     */
594
599
    protected $_seq_in_index = 1;
595
 
    
 
600
 
596
601
    /**
597
 
     * @var string How the column is sorted in the index. “A” (Ascending) or NULL (Not sorted) 
 
602
     * @var string How the column is sorted in the index. “A” (Ascending) or NULL (Not sorted)
598
603
     */
599
604
    protected $_collation = null;
600
 
    
 
605
 
601
606
    /**
602
 
     * The number of indexed characters if the column is only partly indexed, 
603
 
     * NULL if the entire column is indexed. 
 
607
     * The number of indexed characters if the column is only partly indexed,
 
608
     * NULL if the entire column is indexed.
604
609
     *
605
610
     * @var integer
606
611
     */
607
612
    protected $_sub_part = null;
608
 
    
 
613
 
609
614
    /**
610
 
     * Contains YES if the column may contain NULL. 
611
 
     * If not, the column contains NO. 
 
615
     * Contains YES if the column may contain NULL.
 
616
     * If not, the column contains NO.
612
617
     *
613
618
     * @var string
614
619
     */
615
620
    protected $_null = '';
616
 
    
 
621
 
617
622
    /**
618
 
     * An estimate of the number of unique values in the index. This is updated 
619
 
     * by running ANALYZE TABLE or myisamchk -a. Cardinality is counted based on 
620
 
     * statistics stored as integers, so the value is not necessarily exact even 
621
 
     * for small tables. The higher the cardinality, the greater the chance that 
622
 
     * MySQL uses the index when doing joins. 
 
623
     * An estimate of the number of unique values in the index. This is updated
 
624
     * by running ANALYZE TABLE or myisamchk -a. Cardinality is counted based on
 
625
     * statistics stored as integers, so the value is not necessarily exact even
 
626
     * for small tables. The higher the cardinality, the greater the chance that
 
627
     * MySQL uses the index when doing joins.
623
628
     *
624
629
     * @var integer
625
630
     */
626
631
    protected $_cardinality = 0;
627
 
    
 
632
 
628
633
    public function __construct($params = array())
629
634
    {
630
635
        $this->set($params);
631
636
    }
632
 
    
 
637
 
633
638
    public function set($params)
634
639
    {
635
640
        if (isset($params['Column_name'])) {
651
656
            $this->_null = $params['Null'];
652
657
        }
653
658
    }
654
 
    
 
659
 
655
660
    public function getName()
656
661
    {
657
662
        return $this->_name;
658
663
    }
659
 
    
 
664
 
660
665
    public function getCollation()
661
666
    {
662
667
        return $this->_collation;
663
668
    }
664
 
    
 
669
 
665
670
    public function getCardinality()
666
671
    {
667
672
        return $this->_cardinality;
668
673
    }
669
 
    
 
674
 
670
675
    public function getNull()
671
676
    {
672
677
        return $this->_null;
673
678
    }
674
 
    
 
679
 
675
680
    public function getSeqInIndex()
676
681
    {
677
682
        return $this->_seq_in_index;
678
683
    }
679
 
    
 
684
 
680
685
    public function getSubPart()
681
686
    {
682
687
        return $this->_sub_part;