ILIAS  Release_4_4_x_branch Revision 61816
 All Data Structures Namespaces Files Functions Variables Groups Pages
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 
48 require_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 ?>