Subversion-Projekte lars-tiefland.niewerth

Revision

Revision 7 | Details | Vergleich mit vorheriger | 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-2006 Manuel Lemos, Tomas V.V.Cox,                 |
6
// | Stig. S. Bakken, Lukas Smith                                         |
7
// | All rights reserved.                                                 |
8
// +----------------------------------------------------------------------+
9
// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB  |
10
// | API as well as database abstraction for PHP applications.            |
11
// | This LICENSE is in the BSD license style.                            |
12
// |                                                                      |
13
// | Redistribution and use in source and binary forms, with or without   |
14
// | modification, are permitted provided that the following conditions   |
15
// | are met:                                                             |
16
// |                                                                      |
17
// | Redistributions of source code must retain the above copyright       |
18
// | notice, this list of conditions and the following disclaimer.        |
19
// |                                                                      |
20
// | Redistributions in binary form must reproduce the above copyright    |
21
// | notice, this list of conditions and the following disclaimer in the  |
22
// | documentation and/or other materials provided with the distribution. |
23
// |                                                                      |
24
// | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken,    |
25
// | Lukas Smith nor the names of his contributors may be used to endorse |
26
// | or promote products derived from this software without specific prior|
27
// | written permission.                                                  |
28
// |                                                                      |
29
// | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS  |
30
// | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT    |
31
// | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS    |
32
// | FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE      |
33
// | REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,          |
34
// | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
35
// | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS|
36
// |  OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED  |
37
// | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT          |
38
// | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY|
39
// | WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE          |
40
// | POSSIBILITY OF SUCH DAMAGE.                                          |
41
// +----------------------------------------------------------------------+
42
// | Author: Lukas Smith <smith@pooteeweet.org>                           |
43
// +----------------------------------------------------------------------+
44
//
45
// $Id: mysql.php,v 1.60 2006/09/25 23:39:35 lsmith Exp $
46
//
47
 
48
require_once 'MDB2/Driver/Reverse/Common.php';
49
 
50
/**
51
 * MDB2 MySQL driver for the schema reverse engineering module
52
 *
53
 * @package MDB2
54
 * @category Database
55
 * @author  Lukas Smith <smith@pooteeweet.org>
56
 */
57
class MDB2_Driver_Reverse_mysql extends MDB2_Driver_Reverse_Common
58
{
59
    // {{{ getTableFieldDefinition()
60
 
61
    /**
62
     * Get the stucture of a field into an array
63
     *
64
     * @param string    $table         name of table that should be used in method
65
     * @param string    $field_name     name of field that should be used in method
66
     * @return mixed data array on success, a MDB2 error on failure
67
     * @access public
68
     */
69
    function getTableFieldDefinition($table, $field_name)
70
    {
71
        $db =& $this->getDBInstance();
72
        if (PEAR::isError($db)) {
73
            return $db;
74
        }
75
 
76
        $result = $db->loadModule('Datatype', null, true);
77
        if (PEAR::isError($result)) {
78
            return $result;
79
        }
80
        $table = $db->quoteIdentifier($table, true);
81
        $query = "SHOW COLUMNS FROM $table LIKE ".$db->quote($field_name);
82
        $columns = $db->queryAll($query, null, MDB2_FETCHMODE_ASSOC);
83
        if (PEAR::isError($columns)) {
84
            return $columns;
85
        }
86
        foreach ($columns as $column) {
87
            $column = array_change_key_case($column, CASE_LOWER);
88
            $column['name'] = $column['field'];
89
            unset($column['field']);
90
            if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
91
                if ($db->options['field_case'] == CASE_LOWER) {
92
                    $column['name'] = strtolower($column['name']);
93
                } else {
94
                    $column['name'] = strtoupper($column['name']);
95
                }
96
            } else {
97
                $column = array_change_key_case($column, $db->options['field_case']);
98
            }
99
            if ($field_name == $column['name']) {
100
                list($types, $length, $unsigned, $fixed) = $db->datatype->mapNativeDatatype($column);
101
                $notnull = false;
102
                if (empty($column['null']) || $column['null'] !== 'YES') {
103
                    $notnull = true;
104
                }
105
                $default = false;
106
                if (array_key_exists('default', $column)) {
107
                    $default = $column['default'];
108
                    if (is_null($default) && $notnull) {
109
                        $default = '';
110
                    }
111
                }
112
                $autoincrement = false;
113
                if (!empty($column['extra']) && $column['extra'] == 'auto_increment') {
114
                    $autoincrement = true;
115
                }
116
 
117
                $definition[0] = array(
118
                    'notnull' => $notnull,
119
                    'nativetype' => preg_replace('/^([a-z]+)[^a-z].*/i', '\\1', $column['type'])
120
                );
121
                if ($length > 0) {
122
                    $definition[0]['length'] = $length;
123
                }
124
                if (!is_null($unsigned)) {
125
                    $definition[0]['unsigned'] = $unsigned;
126
                }
127
                if (!is_null($fixed)) {
128
                    $definition[0]['fixed'] = $fixed;
129
                }
130
                if ($default !== false) {
131
                    $definition[0]['default'] = $default;
132
                }
133
                if ($autoincrement !== false) {
134
                    $definition[0]['autoincrement'] = $autoincrement;
135
                }
136
                foreach ($types as $key => $type) {
137
                    $definition[$key] = $definition[0];
138
                    if ($type == 'clob' || $type == 'blob') {
139
                        unset($definition[$key]['default']);
140
                    }
141
                    $definition[$key]['type'] = $type;
142
                    $definition[$key]['mdb2type'] = $type;
143
                }
144
                return $definition;
145
            }
146
        }
147
 
148
        return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
149
            'it was not specified an existing table column', __FUNCTION__);
150
    }
151
 
152
    // }}}
153
    // {{{ getTableIndexDefinition()
154
 
155
    /**
156
     * Get the stucture of an index into an array
157
     *
158
     * @param string    $table      name of table that should be used in method
159
     * @param string    $index_name name of index that should be used in method
160
     * @return mixed data array on success, a MDB2 error on failure
161
     * @access public
162
     */
163
    function getTableIndexDefinition($table, $index_name)
164
    {
165
        $db =& $this->getDBInstance();
166
        if (PEAR::isError($db)) {
167
            return $db;
168
        }
169
 
170
        $index_name = $db->getIndexName($index_name);
171
        $table = $db->quoteIdentifier($table, true);
172
        $query = "SHOW INDEX FROM $table /*!50002 WHERE Key_name = ".$db->quote($index_name)." */";
173
        $result = $db->query($query);
174
        if (PEAR::isError($result)) {
175
            return $result;
176
        }
177
        $definition = array();
178
        while (is_array($row = $result->fetchRow(MDB2_FETCHMODE_ASSOC))) {
179
            $row = array_change_key_case($row, CASE_LOWER);
180
            $key_name = $row['key_name'];
181
            if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
182
                if ($db->options['field_case'] == CASE_LOWER) {
183
                    $key_name = strtolower($key_name);
184
                } else {
185
                    $key_name = strtoupper($key_name);
186
                }
187
            }
188
            if ($index_name == $key_name) {
189
                if (!$row['non_unique']) {
190
                    return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
191
                        'it was not specified an existing table index', __FUNCTION__);
192
                }
193
                $column_name = $row['column_name'];
194
                if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
195
                    if ($db->options['field_case'] == CASE_LOWER) {
196
                        $column_name = strtolower($column_name);
197
                    } else {
198
                        $column_name = strtoupper($column_name);
199
                    }
200
                }
201
                $definition['fields'][$column_name] = array();
202
                if (!empty($row['collation'])) {
203
                    $definition['fields'][$column_name]['sorting'] = ($row['collation'] == 'A'
204
                        ? 'ascending' : 'descending');
205
                }
206
            }
207
        }
208
        $result->free();
209
        if (empty($definition['fields'])) {
210
            return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
211
                'it was not specified an existing table index', __FUNCTION__);
212
        }
213
        return $definition;
214
    }
215
 
216
    // }}}
217
    // {{{ getTableConstraintDefinition()
218
 
219
    /**
220
     * Get the stucture of a constraint into an array
221
     *
222
     * @param string    $table      name of table that should be used in method
223
     * @param string    $index_name name of index that should be used in method
224
     * @return mixed data array on success, a MDB2 error on failure
225
     * @access public
226
     */
227
    function getTableConstraintDefinition($table, $index_name)
228
    {
229
        $db =& $this->getDBInstance();
230
        if (PEAR::isError($db)) {
231
            return $db;
232
        }
233
 
234
        if (strtolower($index_name) != 'primary') {
235
            $index_name = $db->getIndexName($index_name);
236
        }
237
        $table = $db->quoteIdentifier($table, true);
238
        $query = "SHOW INDEX FROM $table /*!50002 WHERE Key_name = ".$db->quote($index_name)." */";
239
        $result = $db->query($query);
240
        if (PEAR::isError($result)) {
241
            return $result;
242
        }
243
        $definition = array();
244
        while (is_array($row = $result->fetchRow(MDB2_FETCHMODE_ASSOC))) {
245
            $row = array_change_key_case($row, CASE_LOWER);
246
            $key_name = $row['key_name'];
247
            if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
248
                if ($db->options['field_case'] == CASE_LOWER) {
249
                    $key_name = strtolower($key_name);
250
                } else {
251
                    $key_name = strtoupper($key_name);
252
                }
253
            }
254
            if ($index_name == $key_name) {
255
                if ($row['non_unique']) {
256
                    return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
257
                        'it was not specified an existing table constraint', __FUNCTION__);
258
                }
259
                if ($row['key_name'] == 'PRIMARY') {
260
                    $definition['primary'] = true;
261
                } else {
262
                    $definition['unique'] = true;
263
                }
264
                $column_name = $row['column_name'];
265
                if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
266
                    if ($db->options['field_case'] == CASE_LOWER) {
267
                        $column_name = strtolower($column_name);
268
                    } else {
269
                        $column_name = strtoupper($column_name);
270
                    }
271
                }
272
                $definition['fields'][$column_name] = array();
273
                if (!empty($row['collation'])) {
274
                    $definition['fields'][$column_name]['sorting'] = ($row['collation'] == 'A'
275
                        ? 'ascending' : 'descending');
276
                }
277
            }
278
        }
279
        $result->free();
280
        if (empty($definition['fields'])) {
281
            return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
282
                'it was not specified an existing table constraint', __FUNCTION__);
283
        }
284
        return $definition;
285
    }
286
 
287
    // }}}
288
    // {{{ tableInfo()
289
 
290
    /**
291
     * Returns information about a table or a result set
292
     *
293
     * @param object|string  $result  MDB2_result object from a query or a
294
     *                                 string containing the name of a table.
295
     *                                 While this also accepts a query result
296
     *                                 resource identifier, this behavior is
297
     *                                 deprecated.
298
     * @param int            $mode    a valid tableInfo mode
299
     *
300
     * @return array  an associative array with the information requested.
301
     *                 A MDB2_Error object on failure.
302
     *
303
     * @see MDB2_Driver_Common::setOption()
304
     */
305
    function tableInfo($result, $mode = null)
306
    {
307
        if (is_string($result)) {
308
           return parent::tableInfo($result, $mode);
309
        }
310
 
311
        $db =& $this->getDBInstance();
312
        if (PEAR::isError($db)) {
313
            return $db;
314
        }
315
 
316
        $resource = MDB2::isResultCommon($result) ? $result->getResource() : $result;
317
        if (!is_resource($resource)) {
318
            return $db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null,
319
                'Could not generate result resource', __FUNCTION__);
320
        }
321
 
322
        if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
323
            if ($db->options['field_case'] == CASE_LOWER) {
324
                $case_func = 'strtolower';
325
            } else {
326
                $case_func = 'strtoupper';
327
            }
328
        } else {
329
            $case_func = 'strval';
330
        }
331
 
332
        $count = @mysql_num_fields($resource);
333
        $res   = array();
334
 
335
        if ($mode) {
336
            $res['num_fields'] = $count;
337
        }
338
 
339
        $db->loadModule('Datatype', null, true);
340
        for ($i = 0; $i < $count; $i++) {
341
            $res[$i] = array(
342
                'table' => $case_func(@mysql_field_table($resource, $i)),
343
                'name'  => $case_func(@mysql_field_name($resource, $i)),
344
                'type'  => @mysql_field_type($resource, $i),
345
                'length'   => @mysql_field_len($resource, $i),
346
                'flags' => @mysql_field_flags($resource, $i),
347
            );
348
            if ($res[$i]['type'] == 'string') {
349
                $res[$i]['type'] = 'char';
350
            } elseif ($res[$i]['type'] == 'unknown') {
351
                $res[$i]['type'] = 'decimal';
352
            }
353
            $mdb2type_info = $db->datatype->mapNativeDatatype($res[$i]);
354
            if (PEAR::isError($mdb2type_info)) {
355
               return $mdb2type_info;
356
            }
357
            $res[$i]['mdb2type'] = $mdb2type_info[0][0];
358
            if ($mode & MDB2_TABLEINFO_ORDER) {
359
                $res['order'][$res[$i]['name']] = $i;
360
            }
361
            if ($mode & MDB2_TABLEINFO_ORDERTABLE) {
362
                $res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i;
363
            }
364
        }
365
 
366
        return $res;
367
    }
368
}
369
?>