ILIAS  release_5-1 Revision 5.0.0-5477-g43f3e3fab5f
mysqli.php
Go to the documentation of this file.
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: mysqli.php,v 1.59 2007/03/29 18:18:06 quipo Exp $
46//
47
48require_once 'MDB2/Driver/Reverse/Common.php';
49
59{
65 var $flags = array(
66 MYSQLI_NOT_NULL_FLAG => 'not_null',
67 MYSQLI_PRI_KEY_FLAG => 'primary_key',
68 MYSQLI_UNIQUE_KEY_FLAG => 'unique_key',
69 MYSQLI_MULTIPLE_KEY_FLAG => 'multiple_key',
70 MYSQLI_BLOB_FLAG => 'blob',
71 MYSQLI_UNSIGNED_FLAG => 'unsigned',
72 MYSQLI_ZEROFILL_FLAG => 'zerofill',
73 MYSQLI_AUTO_INCREMENT_FLAG => 'auto_increment',
74 MYSQLI_TIMESTAMP_FLAG => 'timestamp',
75 MYSQLI_SET_FLAG => 'set',
76 // MYSQLI_NUM_FLAG => 'numeric', // unnecessary
77 // MYSQLI_PART_KEY_FLAG => 'multiple_key', // duplicatvie
78 MYSQLI_GROUP_FLAG => 'group_by'
79 );
80
86 var $types = array(
87 MYSQLI_TYPE_DECIMAL => 'decimal',
88 246 => 'decimal',
89 MYSQLI_TYPE_TINY => 'tinyint',
90 MYSQLI_TYPE_SHORT => 'int',
91 MYSQLI_TYPE_LONG => 'int',
92 MYSQLI_TYPE_FLOAT => 'float',
93 MYSQLI_TYPE_DOUBLE => 'double',
94 // MYSQLI_TYPE_NULL => 'DEFAULT NULL', // let flags handle it
95 MYSQLI_TYPE_TIMESTAMP => 'timestamp',
96 MYSQLI_TYPE_LONGLONG => 'bigint',
97 MYSQLI_TYPE_INT24 => 'mediumint',
98 MYSQLI_TYPE_DATE => 'date',
99 MYSQLI_TYPE_TIME => 'time',
100 MYSQLI_TYPE_DATETIME => 'datetime',
101 MYSQLI_TYPE_YEAR => 'year',
102 MYSQLI_TYPE_NEWDATE => 'date',
103 MYSQLI_TYPE_ENUM => 'enum',
104 MYSQLI_TYPE_SET => 'set',
105 MYSQLI_TYPE_TINY_BLOB => 'tinyblob',
106 MYSQLI_TYPE_MEDIUM_BLOB => 'mediumblob',
107 MYSQLI_TYPE_LONG_BLOB => 'longblob',
108 MYSQLI_TYPE_BLOB => 'blob',
109 MYSQLI_TYPE_VAR_STRING => 'varchar',
110 MYSQLI_TYPE_STRING => 'char',
111 MYSQLI_TYPE_GEOMETRY => 'geometry',
112 );
113
114 // {{{ getTableFieldDefinition()
115
124 function getTableFieldDefinition($table, $field_name)
125 {
126 $db =& $this->getDBInstance();
127 if (PEAR::isError($db)) {
128 return $db;
129 }
130
131 $result = $db->loadModule('Datatype', null, true);
132 if (PEAR::isError($result)) {
133 return $result;
134 }
135 $table = $db->quoteIdentifier($table, true);
136 $query = "SHOW COLUMNS FROM $table LIKE ".$db->quote($field_name);
137 $columns = $db->queryAll($query, null, MDB2_FETCHMODE_ASSOC);
138 if (PEAR::isError($columns)) {
139 return $columns;
140 }
141 foreach ($columns as $column) {
142 $column = array_change_key_case($column, CASE_LOWER);
143 $column['name'] = $column['field'];
144 unset($column['field']);
145 if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
146 if ($db->options['field_case'] == CASE_LOWER) {
147 $column['name'] = strtolower($column['name']);
148 } else {
149 $column['name'] = strtoupper($column['name']);
150 }
151 } else {
152 $column = array_change_key_case($column, $db->options['field_case']);
153 }
154 if ($field_name == $column['name']) {
155 $mapped_datatype = $db->datatype->mapNativeDatatype($column);
156 if (PEAR::IsError($mapped_datatype)) {
157 return $mapped_datatype;
158 }
159 list($types, $length, $unsigned, $fixed) = $mapped_datatype;
160 $notnull = false;
161 if (empty($column['null']) || $column['null'] !== 'YES') {
162 $notnull = true;
163 }
164 $default = false;
165 if (array_key_exists('default', $column)) {
166 $default = $column['default'];
167 if (is_null($default) && $notnull) {
168 $default = '';
169 }
170 }
171 $autoincrement = false;
172 if (!empty($column['extra']) && $column['extra'] == 'auto_increment') {
173 $autoincrement = true;
174 }
175
176 $definition[0] = array(
177 'notnull' => $notnull,
178 'nativetype' => preg_replace('/^([a-z]+)[^a-z].*/i', '\\1', $column['type'])
179 );
180 if (!is_null($length)) {
181 $definition[0]['length'] = $length;
182 }
183 if (!is_null($unsigned)) {
184 $definition[0]['unsigned'] = $unsigned;
185 }
186 if (!is_null($fixed)) {
187 $definition[0]['fixed'] = $fixed;
188 }
189 if ($default !== false) {
190 $definition[0]['default'] = $default;
191 }
192 if ($autoincrement !== false) {
193 $definition[0]['autoincrement'] = $autoincrement;
194 }
195 foreach ($types as $key => $type) {
196 $definition[$key] = $definition[0];
197 if ($type == 'clob' || $type == 'blob') {
198 unset($definition[$key]['default']);
199 }
200 $definition[$key]['type'] = $type;
201 $definition[$key]['mdb2type'] = $type;
202 }
203 return $definition;
204 }
205 }
206
207 return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
208 'it was not specified an existing table column', __FUNCTION__);
209 }
210
211 // }}}
212 // {{{ getTableIndexDefinition()
213
222 function getTableIndexDefinition($table, $index_name)
223 {
224 $db =& $this->getDBInstance();
225 if (PEAR::isError($db)) {
226 return $db;
227 }
228
229 $table = $db->quoteIdentifier($table, true);
230 $query = "SHOW INDEX FROM $table /*!50002 WHERE Key_name = %s */";
231 $index_name_mdb2 = $db->getIndexName($index_name);
232 $result = $db->queryRow(sprintf($query, $db->quote($index_name_mdb2)));
233 if (!PEAR::isError($result) && !is_null($result)) {
234 // apply 'idxname_format' only if the query succeeded, otherwise
235 // fallback to the given $index_name, without transformation
236 $index_name = $index_name_mdb2;
237 }
238 $result = $db->query(sprintf($query, $db->quote($index_name)));
239 if (PEAR::isError($result)) {
240 return $result;
241 }
242 $colpos = 1;
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 index', __FUNCTION__);
258 }
259 $column_name = $row['column_name'];
260 if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
261 if ($db->options['field_case'] == CASE_LOWER) {
262 $column_name = strtolower($column_name);
263 } else {
264 $column_name = strtoupper($column_name);
265 }
266 }
267 $definition['fields'][$column_name] = array(
268 'position' => $colpos++
269 );
270 if (!empty($row['collation'])) {
271 $definition['fields'][$column_name]['sorting'] = ($row['collation'] == 'A'
272 ? 'ascending' : 'descending');
273 }
274 }
275 }
276 $result->free();
277 if (empty($definition['fields'])) {
278 return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
279 'it was not specified an existing table index', __FUNCTION__);
280 }
281 return $definition;
282 }
283
284 // }}}
285 // {{{ getTableConstraintDefinition()
286
295 function getTableConstraintDefinition($table, $constraint_name)
296 {
297 $db =& $this->getDBInstance();
298 if (PEAR::isError($db)) {
299 return $db;
300 }
301
302 $table = $db->quoteIdentifier($table, true);
303 $query = "SHOW INDEX FROM $table /*!50002 WHERE Key_name = %s */";
304 if (strtolower($constraint_name) != 'primary') {
305 $constraint_name_mdb2 = $db->getIndexName($constraint_name);
306 $result = $db->queryRow(sprintf($query, $db->quote($constraint_name_mdb2)));
307 if (!PEAR::isError($result) && !is_null($result)) {
308 // apply 'idxname_format' only if the query succeeded, otherwise
309 // fallback to the given $index_name, without transformation
310 $constraint_name = $constraint_name_mdb2;
311 }
312 }
313 $result = $db->query(sprintf($query, $db->quote($constraint_name)));
314 if (PEAR::isError($result)) {
315 return $result;
316 }
317 $colpos = 1;
318 $definition = array();
319 while (is_array($row = $result->fetchRow(MDB2_FETCHMODE_ASSOC))) {
320 $row = array_change_key_case($row, CASE_LOWER);
321 $key_name = $row['key_name'];
322 if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
323 if ($db->options['field_case'] == CASE_LOWER) {
324 $key_name = strtolower($key_name);
325 } else {
326 $key_name = strtoupper($key_name);
327 }
328 }
329 if ($constraint_name == $key_name) {
330 if ($row['non_unique']) {
331 return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
332 $constraint_name . ' is not an existing table constraint', __FUNCTION__);
333 }
334 if ($row['key_name'] == 'PRIMARY') {
335 $definition['primary'] = true;
336 } else {
337 $definition['unique'] = true;
338 }
339 $column_name = $row['column_name'];
340 if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
341 if ($db->options['field_case'] == CASE_LOWER) {
342 $column_name = strtolower($column_name);
343 } else {
344 $column_name = strtoupper($column_name);
345 }
346 }
347 $definition['fields'][$column_name] = array(
348 'position' => $colpos++
349 );
350 if (!empty($row['collation'])) {
351 $definition['fields'][$column_name]['sorting'] = ($row['collation'] == 'A'
352 ? 'ascending' : 'descending');
353 }
354 }
355 }
356 $result->free();
357 if (empty($definition['fields'])) {
358 return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
359 $constraint_name . ' is not an existing table constraint', __FUNCTION__);
360 }
361 return $definition;
362 }
363
364 // }}}
365 // {{{ getTriggerDefinition()
366
379 function getTriggerDefinition($trigger)
380 {
381 $db =& $this->getDBInstance();
382 if (PEAR::isError($db)) {
383 return $db;
384 }
385
386 $query = 'SELECT trigger_name,
387 event_object_table AS table_name,
388 action_statement AS trigger_body,
389 action_timing AS trigger_type,
390 event_manipulation AS trigger_event
391 FROM information_schema.triggers
392 WHERE trigger_name = '. $db->quote($trigger, 'text');
393 $types = array(
394 'trigger_name' => 'text',
395 'table_name' => 'text',
396 'trigger_body' => 'text',
397 'trigger_type' => 'text',
398 'trigger_event' => 'text',
399 );
400 $def = $db->queryRow($query, $types, MDB2_FETCHMODE_ASSOC);
401 if (PEAR::isError($def)) {
402 return $def;
403 }
404 $def['trigger_comment'] = '';
405 $def['trigger_enabled'] = true;
406 return $def;
407 }
408
409 // }}}
410 // {{{ tableInfo()
411
427 function tableInfo($result, $mode = null)
428 {
429 if (is_string($result)) {
430 return parent::tableInfo($result, $mode);
431 }
432
433 $db =& $this->getDBInstance();
434 if (PEAR::isError($db)) {
435 return $db;
436 }
437
438 $resource = MDB2::isResultCommon($result) ? $result->getResource() : $result;
439 if (!is_object($resource)) {
440 return $db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null,
441 'Could not generate result resource', __FUNCTION__);
442 }
443
444 if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
445 if ($db->options['field_case'] == CASE_LOWER) {
446 $case_func = 'strtolower';
447 } else {
448 $case_func = 'strtoupper';
449 }
450 } else {
451 $case_func = 'strval';
452 }
453
454 $count = @mysqli_num_fields($resource);
455 $res = array();
456 if ($mode) {
457 $res['num_fields'] = $count;
458 }
459
460 $db->loadModule('Datatype', null, true);
461 for ($i = 0; $i < $count; $i++) {
462 $tmp = @mysqli_fetch_field($resource);
463
464 $flags = '';
465 foreach ($this->flags as $const => $means) {
466 if ($tmp->flags & $const) {
467 $flags.= $means . ' ';
468 }
469 }
470 if ($tmp->def) {
471 $flags.= 'default_' . rawurlencode($tmp->def);
472 }
473 $flags = trim($flags);
474
475 $res[$i] = array(
476 'table' => $case_func($tmp->table),
477 'name' => $case_func($tmp->name),
478 'type' => isset($this->types[$tmp->type])
479 ? $this->types[$tmp->type] : 'unknown',
480 // http://bugs.php.net/?id=36579
481 'length' => $tmp->length,
482 'flags' => $flags,
483 );
484 $mdb2type_info = $db->datatype->mapNativeDatatype($res[$i]);
485 if (PEAR::isError($mdb2type_info)) {
486 return $mdb2type_info;
487 }
488 $res[$i]['mdb2type'] = $mdb2type_info[0][0];
489 if ($mode & MDB2_TABLEINFO_ORDER) {
490 $res['order'][$res[$i]['name']] = $i;
491 }
492 if ($mode & MDB2_TABLEINFO_ORDERTABLE) {
493 $res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i;
494 }
495 }
496
497 return $res;
498 }
499}
500?>
$result
const MDB2_PORTABILITY_FIX_CASE
Portability: convert names of tables and fields to case defined in the "field_case" option when using...
Definition: MDB2.php:158
const MDB2_ERROR_NOT_FOUND
Definition: MDB2.php:71
const MDB2_ERROR_NEED_MORE_DATA
Definition: MDB2.php:87
const MDB2_FETCHMODE_ASSOC
Column data indexed by column names.
Definition: MDB2.php:129
const MDB2_TABLEINFO_ORDERTABLE
Definition: Common.php:60
const MDB2_TABLEINFO_ORDER
These are constants for the tableInfo-function they are bitwised or'ed.
Definition: Common.php:59
if(! $in) $columns
Definition: Utf8Test.php:46
getTableConstraintDefinition($table, $constraint_name)
Get the structure of a constraint into an array.
Definition: mysqli.php:295
getTableIndexDefinition($table, $index_name)
Get the structure of an index into an array.
Definition: mysqli.php:222
getTableFieldDefinition($table, $field_name)
Get the structure of a field into an array.
Definition: mysqli.php:124
tableInfo($result, $mode=null)
Returns information about a table or a result set.
Definition: mysqli.php:427
getTriggerDefinition($trigger)
Get the structure of a trigger into an array.
Definition: mysqli.php:379
& getDBInstance()
Get the instance of MDB2 associated with the module instance.
Definition: MDB2.php:4206
isResultCommon($value)
Tell whether a value is a MDB2 result implementing the common interface.
Definition: MDB2.php:655
isError($data, $code=null)
Tell whether a value is a PEAR error.
Definition: PEAR.php:279