ILIAS  Release_3_10_x_branch Revision 61812
 All Data Structures Namespaces Files Functions Variables Groups Pages
class.ilDBx.php
Go to the documentation of this file.
1 <?php
2 /*
3  +-----------------------------------------------------------------------------+
4  | ILIAS open source |
5  +-----------------------------------------------------------------------------+
6  | Copyright (c) 1998-2001 ILIAS open source, University of Cologne |
7  | |
8  | This program is free software; you can redistribute it and/or |
9  | modify it under the terms of the GNU General Public License |
10  | as published by the Free Software Foundation; either version 2 |
11  | of the License, or (at your option) any later version. |
12  | |
13  | This program is distributed in the hope that it will be useful, |
14  | but WITHOUT ANY WARRANTY; without even the implied warranty of |
15  | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16  | GNU General Public License for more details. |
17  | |
18  | You should have received a copy of the GNU General Public License |
19  | along with this program; if not, write to the Free Software |
20  | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
21  +-----------------------------------------------------------------------------+
22 */
23 
24 
25 //pear DB abstraction layer
26 //require_once ("DB.php");
27 include_once ("MDB2.php");
28 
29 define("DB_FETCHMODE_ASSOC", MDB2_FETCHMODE_ASSOC);
30 define("DB_FETCHMODE_OBJECT", MDB2_FETCHMODE_OBJECT);
31 
32 //echo "-".DB_FETCHMODE_ASSOC."-";
33 //echo "+".DB_FETCHMODE_OBJECT."+";
34 
35 
48 class ilDBx extends PEAR
49 {
56 
61  var $db;
62 
67  var $result;
68 
74 
75 
83  function ilDBx($dsn)
84  {
85  //call parent constructor
86  $parent = get_parent_class($this);
87  $this->$parent();
88 
89  //set up error handling
90  $this->error_class = new ilErrorHandling();
91  $this->setErrorHandling(PEAR_ERROR_CALLBACK, array($this->error_class,'errorHandler'));
92 
93  //check dsn
94  if ($dsn=="")
95  $this->raiseError("no DSN given", $this->error_class->FATAL);
96 
97  $this->dsn = $dsn;
98 
99  //connect to database
100  //$this->db = DB::connect($this->dsn, true);
101  $this->db = MDB2::connect($this->dsn, array("use_transactions" => true));
102 
103  $this->loadMDB2Extensions();
104 
105  // set empty value portability to PEAR::DB behaviour
106  if (!$this->isDbError($this->db))
107  {
108  $cur = ($this->db->getOption("portability") & MDB2_PORTABILITY_EMPTY_TO_NULL);
109  $this->db->setOption("portability", $this->db->getOption("portability") - $cur);
110 
111  $cur = ($this->db->getOption("portability") & MDB2_PORTABILITY_FIX_CASE);
112  $this->db->setOption("portability", $this->db->getOption("portability") - $cur);
113  }
114 
115  //check error
116  if (MDB2::isError($this->db)) {
117  $this->raiseError($this->db->getMessage(), $this->error_class->FATAL);
118  }
119 
120  // SET 'max_allowed_packet' (only possible for mysql version 4)
121  $this->setMaxAllowedPacket();
122 
123  // NOTE: Three sourcecodes use this or a similar handling:
124  // - classes/class.ilDBx.php
125  // - calendar/classes/class.ilCalInterface.php->setNames
126  // - setup/classes/class.ilClient.php
127  if ($this->isMysql4_1OrHigher())
128  {
129  $this->query("SET NAMES utf8");
130  $this->query("SET SESSION SQL_MODE = ''");
131  }
132 
133  return true;
134  } //end constructor
135 
139  function _ilDBx(){
140  //$this->db->disconnect();
141  } //end destructor
142 
146  function disconnect()
147  {
148 // $this->db->disconnect();
149  }
150 
154  function createTable($a_name, $a_definition_array, $a_options = "")
155  {
156  if ($a_options == "")
157  {
158  $a_options = array();
159  }
160 
161  $manager = $this->db->loadModule('Manager');
162  $r = $manager->createTable($a_name, $a_definition_array, $a_options);
163 
164  if (MDB2::isError($r))
165  {
166  //$err = "<br>Details: ".mysql_error();
167  $this->raiseError($r->getMessage()."<br><font size=-1>SQL: ".$sql.$err."</font>", $this->error_class->FATAL);
168  }
169  else
170  {
171  return $r;
172  }
173  }
174 
188  function query($sql)
189  {
190  $r = $this->db->query($sql);
191 
192 /*$pos1 = strpos(strtolower($sql), "from ");
193 $table = "";
194 if ($pos1 > 0)
195 {
196  $tablef = substr($sql, $pos1+5);
197  $pos2 = strpos(strtolower($tablef), " ");
198  if ($pos2 > 0)
199  {
200  $table =substr($tablef, 0, $pos2);
201  }
202  else
203  {
204  $table = $tablef;
205  }
206 }
207 if (trim($table) != "")
208 {
209  if (!is_array($this->ttt) || !in_array($table, $this->ttt))
210  {
211  echo "<br>".$table;
212  $this->ttt[] = $table;
213  }
214 }
215 else
216 {
217  echo "<br><b>".$sql."</b>";
218 }*/
219 //error_log('ilDBx '.$sql.' #rows:'.$r->numRows());
220  if (MDB2::isError($r))
221  {
222  $err = "<br>Details: ".mysql_error();
223  $this->raiseError($r->getMessage()."<br><font size=-1>SQL: ".$sql.$err."</font>", $this->error_class->FATAL);
224  }
225  else
226  {
227  return $r;
228  }
229  }
230 
244  function manipulate($sql)
245  {
246  $r = $this->db->exec($sql);
247 
248  if (MDB2::isError($r))
249  {
250  $err = "<br>Details: ".mysql_error();
251  $this->raiseError($r->getMessage()."<br><font size=-1>SQL: ".$sql.$err."</font>", $this->error_class->FATAL);
252  }
253  else
254  {
255  return $r;
256  }
257  }
258 
267  function prepare($a_query, $a_types = null, $a_result_types = null)
268  {
269  $res = $this->db->prepare($a_query, $a_types, $a_result_types);
270  if (MDB2::isError($res))
271  {
272  $this->raiseError($res->getMessage()."<br><font size=-1>SQL: ".$a_query."</font>", $this->error_class->FATAL);
273  }
274  else
275  {
276  return $res;
277  }
278  }
279 
288  function prepareManip($a_query, $a_types = null)
289  {
290  $res = $this->db->prepare($a_query, $a_types, MDB2_PREPARE_MANIP);
291  if (MDB2::isError($res))
292  {
293  $this->raiseError($res->getMessage()."<br><font size=-1>SQL: ".$a_query."</font>", $this->error_class->FATAL);
294  }
295  else
296  {
297  return $res;
298  }
299  }
300 
309  function execute($a_stmt, $a_data = null)
310  {
311  $res = $a_stmt->execute($a_data);
312 
313  if (MDB2::isError($res))
314  {
315  $this->raiseError($res->getMessage()."<br><font size=-1>SQL: ".$a_stmt->query . " with data " . print_r($a_data, true) ."</font>", $this->error_class->FATAL);
316  }
317  else
318  {
319  return $res;
320  }
321  }
322 
332  function executeMultiple($a_stmt, $a_data)
333  {
334  $res = $this->db->extended->executeMultiple($a_stmt,$a_data);
335 
336  if (MDB2::isError($res))
337  {
338  $this->raiseError($res->getMessage()."<br><font size=-1>SQL: ".$data."</font>", $this->error_class->FATAL);
339  }
340  else
341  {
342  return $res;
343  }
344  }
345 
351  function fetchAssoc($a_set)
352  {
353  return $a_set->fetchRow(DB_FETCHMODE_ASSOC);
354  }
355 
361  function fetchObject($a_set)
362  {
363  return $a_set->fetchObject(DB_FETCHMODE_OBJECT);
364  }
365 
370  function getInClause($a_field, $a_values)
371  {
372  if (count($a_values) == 0)
373  {
374  return " 1=2 "; // return a false statement on empty array
375  }
376  $str = $a_field." IN (?".str_repeat(",?", count($a_values) - 1).")";
377 
378  return $str;
379  }
380 
384  function addTypesToArray($a_arr, $a_type, $a_cnt)
385  {
386  if ($a_cnt > 0)
387  {
388  $type_arr = array_fill(0, $a_cnt, $a_type);
389  }
390  else
391  {
392  $type_arr = array();
393  }
394  return array_merge($a_arr, $type_arr);
395  }
396 
400  static function isDbError($a_res)
401  {
402  return MDB2::isError($a_res);
403  }
404 
405 
411  function beginTransaction()
412  {
413  if (!$this->db->supports('transactions'))
414  {
415  $this->raiseError("ilDB::beginTransaction: Transactions are not supported.", $this->error_class->FATAL);
416  }
417  $res = $this->db->beginTransaction();
418  if(MDB2::isError($res))
419  {
420  $this->raiseError($res->getMessage()."<br><font size=-1>SQL: ".$query."</font>", $this->error_class->FATAL);
421  }
422 
423  return $res;
424  }
425 
429  function commit()
430  {
431  $res = $this->db->commit();
432  if(MDB2::isError($res))
433  {
434  $this->raiseError($res->getMessage()."<br><font size=-1>SQL: ".$query."</font>", $this->error_class->FATAL);
435  }
436 
437  return $res;
438  }
439 
443  function rollback()
444  {
445  $res = $this->db->rollback();
446  if(MDB2::isError($res))
447  {
448  $this->raiseError($res->getMessage()."<br><font size=-1>SQL: ".$query."</font>", $this->error_class->FATAL);
449  }
450 
451  return $res;
452  }
453 
457  function getLastInsertId()
458  {
459  $res = $this->db->lastInsertId();
460  if(MDB2::isError($res))
461  {
462  return false;
463  }
464  return $res;
465  }
466 
472  function _lockTables($a_table_params)
473  {
474  global $ilDB;
475 
476  $lock_str = 'LOCK TABLES ';
477  $counter = 0;
478  foreach($a_table_params as $table_name => $type)
479  {
480  $lock_str .= $counter++ ? ',' : '';
481  $lock_str .= $table_name.' '.$type;
482  }
483 
484  $ilDB->query($lock_str);
485 
486  return true;
487  }
488  function _unlockTables()
489  {
490  global $ilDB;
491 
492  $ilDB->query('UNLOCK TABLES');
493 
494  return true;
495  }
496 
500  function getMySQLVersion()
501  {
502  return mysql_get_server_info();
503  }
504 
505 
510  {
511  $version = explode(".", $this->getMysqlVersion());
512  if((int) $version[0] >= 4)
513  {
514  return true;
515  }
516  return false;
517  }
518 
522  function isMysql4_1()
523  {
524  $version = explode(".", $this->getMysqlVersion());
525  if ($version[0] == "4" && $version[1] == "1")
526  {
527  return true;
528  }
529 
530  return false;
531  }
532 
542  {
543  $version = explode(".", $this->getMysqlVersion());
544  if ((int)$version[0] >= 5 ||
545  ((int)$version[0] == 4 && (int)$version[1] >= 1))
546  {
547  return true;
548  }
549 
550  return false;
551  }
552 
558  protected function loadMDB2Extensions()
559  {
560  if (!$this->isDbError($this->db))
561  {
562  $this->db->loadModule('Extended');
563  define('DB_AUTOQUERY_SELECT',MDB2_AUTOQUERY_SELECT);
564  define('DB_AUTOQUERY_INSERT',MDB2_AUTOQUERY_INSERT);
565  define('DB_AUTOQUERY_UPDATE',MDB2_AUTOQUERY_UPDATE);
566  define('DB_AUTOQUERY_DELETE',MDB2_AUTOQUERY_DELETE);
567  }
568  }
569 
573  function checkQuerySize($a_query)
574  {
575  global $lang;
576 
577  if(strlen($a_query) >= $this->max_allowed_packet_size)
578  {
579  return false;
580  }
581  else
582  {
583  return true;
584  }
585  }
586 
587 //
588 //
589 // Older functions. Must be checked.
590 //
591 //
592 
601  function autoExecute($a_tablename,$a_fields,$a_mode = MDB2_AUTOQUERY_INSERT,$a_where = false)
602  {
603  $res = $this->db->autoExecute($a_tablename,$a_fields,$a_mode,$a_where);
604 
605  if (MDB2::isError($res))
606  {
607  $this->raiseError($res->getMessage()."<br><font size=-1>SQL: ".$data."</font>", $this->error_class->FATAL);
608  }
609  else
610  {
611  return $res;
612  }
613  }
614 
618  private function setMaxAllowedPacket()
619  {
620 
621  // GET MYSQL VERSION
622  $query = "SHOW VARIABLES LIKE 'version'";
623  $res = $this->db->query($query);
624  if(MDB2::isError($res))
625  {
626  $this->raiseError($res->getMessage()."<br><font size=-1>SQL: ".$query."</font>", $this->error_class->FATAL);
627  }
628  while($row = $res->fetchRow(DB_FETCHMODE_OBJECT))
629  {
630  $version = $row->Value;
631  }
632 
633  // CHANG VALUE IF MYSQL VERSION > 4.0
634  if(substr($version,0,1) == "4")
635  {
636  ini_get("post_max_size");
637  $query = "SET GLOBAL max_allowed_packet = ".(int) ini_get("post_max_size") * 1024 * 1024;
638  $this->db->query($query);
639  if(MDB2::isError($res))
640  {
641  $this->raiseError($res->getMessage()."<br><font size=-1>SQL: ".$query."</font>", $this->error_class->FATAL);
642  }
643  }
644  // STORE NEW max_size in member variable
645  $query = "SHOW VARIABLES LIKE 'max_allowed_packet'";
646  if(MDB2::isError($res))
647  {
648  $this->raiseError($res->getMessage()."<br><font size=-1>SQL: ".$query."</font>", $this->error_class->FATAL);
649  }
650  $res = $this->db->query($query);
651 
652  while($row = $res->fetchRow(DB_FETCHMODE_OBJECT))
653  {
654  $this->max_allowed_packet_size = $row->Value;
655  //$this->max_allowed_packet_size = $row->value;
656  }
657  #var_dump("<pre>",$this->max_allowed_packet_size,"<pre>");
658  return true;
659  }
660 
661 
669  function tableColumnExists($a_table, $a_column_name)
670  {
671 
672  $column_visibility = false;
673  $manager = $this->db->loadModule('Manager');
674  $r = $manager->listTableFields($a_table);
675 
676  if (!MDB2::isError($r))
677  {
678  foreach($r as $field)
679  {
680  if ($field == $a_column_name)
681  {
682  $column_visibility = true;
683  }
684  }
685  }
686 
687  return $column_visibility;
688 
689  /*$query = "SHOW COLUMNS FROM `$a_table`";
690  $res = $this->db->query($query);
691  while ($data = $res->fetchRow(DB_FETCHMODE_ASSOC))
692  {
693  if ((strcmp($data["Field"], $a_column_name) == 0) || (strcmp($data["field"], $a_column_name) == 0))
694  {
695  $column_visibility = TRUE;
696  }
697  }
698  return $column_visibility;*/
699  }
700 
708  function listTables()
709  {
710  $manager = $this->db->loadModule('Manager');
711  $r = $manager->listTables();
712 
713  if (!MDB2::isError($r))
714  {
715  return $r;
716  }
717 
718  return false;
719  }
720 
721 //
722 //
723 // Deprecated functions.
724 //
725 //
726 
730  function quote($a_query, $null_as_empty_string = true)
731  {
732  if ($null_as_empty_string)
733  {
734  // second test against 0 is crucial for MDB2
735  //if ($a_query == "" && $a_query !== 0)
736  if ($a_query == "")
737  {
738  $a_query = "";
739  }
740  }
741 
742  if (method_exists($this->db, "quoteSmart"))
743  {
744  return $this->db->quoteSmart($a_query);
745  }
746  else
747  {
748  return $this->db->quote($a_query);
749  }
750  }
751 
761  function getOne($sql)
762  {
763  //$r = $this->db->getOne($sql);
764  $set = $this->db->query($sql);
765 
766  if (MDB2::isError($set))
767  {
768  $this->raiseError($set->getMessage()."<br><font size=-1>SQL: ".$sql."</font>", $this->error_class->FATAL);
769  return;
770  }
771 
772  $r = $set->fetchRow(DB_FETCHMODE_ASSOC);
773 
774  return $r[0];
775 
776  } //end function
777 
787  function getRow($sql,$mode = DB_FETCHMODE_OBJECT)
788  {
789  $set = $this->query($sql);
790  $r = $set->fetchRow($mode);
791  //$r = $this->db->getrow($sql,$mode);
792 
793  if (MDB2::isError($r))
794  {
795  $this->raiseError($r->getMessage()."<br><font size=-1>SQL: ".$sql."</font>", $this->error_class->FATAL);
796  }
797  else
798  {
799  return $r;
800  }
801  } //end function
802 
803 
812 /* function affectedRows()
813  {
814  return $this->db->affectedRows();
815  }
816 */
817 
818 } //end Class
819 ?>