ILIAS  eassessment Revision 61809
 All Data Structures Namespaces Files Functions Variables Groups Pages
class.ilDBOracle.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (c) 1998-2009 ILIAS open source, Extended GPL, see docs/LICENSE */
3 
4 
5 include_once ("./Services/Database/classes/class.ilDB.php");
6 
18 class ilDBOracle extends ilDB
19 {
20  const CLOB_BUFFER_SIZE = 2000;
22 
23 
27  function getDSN()
28  {
29  // TODO: check if there is another solution.
30  // This works with 11g
31  if(!isset($GLOBALS['_MDB2_dsninfo_default']['charset']) or
32  $GLOBALS['_MDB2_dsninfo_default']['charset'] != 'utf8')
33  {
34  $GLOBALS['_MDB2_dsninfo_default']['charset'] = 'utf8';
35  }
36 
37  return array('phptype' => 'oci8',
38  'hostspec' => $this->getDBHost(),
39  'username' => $this->getDBUser(),
40  'password' => $this->getDBPassword(),
41  'port' => $this->getDBPort(),
42  'service' => $this->getDBName()
43  );
44 
45  //return "oci8://".$this->getDBUser().":".$this->getDBPassword()."@".
46  // $this->getDBHost()."/?service=".$this->getDBName();
47  }
48 
52  function getDBType()
53  {
54  return "oracle";
55  }
56 
57  public function getDBVersion()
58  {
59  $query = 'SELECT * FROM v$version';
60  $res = $this->db->query($query);
61 
62  if(MDB2::isError($res))
63  {
64  return parent::getDBVersion();
65  }
66  $row = $res->fetchRow(DB_FETCHMODE_ASSOC);
67  return isset($row['banner']) ? $row['banner'] : parent::getDBVersion();
68  }
69 
73  static function getReservedWords()
74  {
75  // version: 10g
76  // url: http://download-west.oracle.com/docs/cd/B14117_01/server.101/b10759/ap_keywd.htm#g691972
77  return array(
78  "ACCESS", "ADD", "ALL", "ALTER", "AND", "ANY", "AS", "ASC",
79  "AUDIT", "BETWEEN", "BY", "CHAR", "CHECK", "CLUSTER", "COLUMN",
80  "COMMENT", "COMPRESS", "CONNECT", "CREATE", "CURRENT", "DATE",
81  "DECIMAL", "DEFAULT", "DELETE", "DESC", "DISTINCT", "DROP", "ELSE",
82  "EXCLUSIVE", "EXISTS", "FILE", "FLOAT", "FOR", "FROM", "GRANT", "GROUP",
83  "HAVING", "IDENTIFIED", "IMMEDIATE", "IN", "INCREMENT", "INDEX", "INITIAL",
84  "INSERT", "INTEGER", "INTERSECT", "INTO", "IS", "LEVEL", "LIKE", "LOCK", "LONG",
85  "MAXEXTENTS", "MINUS", "MLSLABEL", "MODE", "MODIFY", "NOAUDIT", "NOCOMPRESS", "NOT",
86  "NOWAIT", "NULL", "NUMBER", "OF", "OFFLINE", "ON", "ONLINE","OPTION",
87  "OR", "ORDER", "PCTFREE", "PRIOR", "PRIVILEGES", "PUBLIC", "RAW", "RENAME",
88  "RESOURCE", "REVOKE", "ROW", "ROWID", "ROWNUM", "ROWS", "SELECT", "SESSION", "SET",
89  "SHARE", "SIZE", "SMALLINT", "START", "SUCCESSFUL", "SYNONYM", "SYSDATE","TABLE",
90  "THEN", "TO", "TRIGGER", "UID", "UNION", "UNIQUE", "UPDATE", "USER","VALIDATE",
91  "VALUES", "VARCHAR", "VARCHAR2", "VIEW", "WHENEVER", "WHERE", "WITH"
92  );
93  }
94 
98  function doConnect()
99  {
100  $this->db = MDB2::connect($this->getDSN(),
101  array("use_transactions" => true));
102  }
103 
107  function initConnection()
108  {
109  $GLOBALS['_MDB2_dsninfo_default']['charset'] = 'utf8';
110  $this->query("ALTER SESSION SET nls_length_semantics='CHAR'");
111  $this->query("ALTER SESSION SET NLS_SORT = binary_ci");
112  }
113 
114 /* function manipulate($sql)
115  {
116 //echo "1";
117 //echo "3";
118  }*/
119 
124  function now()
125  {
126  return "LOCALTIMESTAMP";
127  }
128 
132  function fromUnixtime($a_expr, $a_to_text = true)
133  {
134  if (!$a_to_text)
135  {
136  return "TO_DATE('19700101000000','YYYYMMDDHH24MISS') ".
137  "+ NUMTODSINTERVAL(".$a_expr.", 'SECOND')";
138  }
139  else
140  {
141  return "to_char(TO_DATE('19700101000000','YYYYMMDDHH24MISS') ".
142  "+ NUMTODSINTERVAL(".$a_expr.", 'SECOND'), 'yyyy-mm-dd hh24:mi:ss')";
143  }
144  }
145 
149  function unixTimestamp()
150  {
151  // sysdate should respect database time zone
152  // current_date would respect session time zone
153  return "ROUND((sysdate - to_date('01-JAN-1970','DD-MON-YYYY')) * (86400))";
154  }
155 
159  function constraintName($a_table, $a_constraint)
160  {
161  return $a_table."_".$a_constraint;
162  }
163 
168  {
169  return "pk";
170  }
171 
175  function supportsFulltext()
176  {
177  return false;
178  }
179 
187  function replace($a_table, $a_pk_columns, $a_other_columns)
188  {
189  $a_columns = array_merge($a_pk_columns, $a_other_columns);
190  $fields = array();
191  $field_values = array();
192  $placeholders = array();
193  $types = array();
194  $values = array();
195  $lobs = false;
196  $lob = array();
197  $val_field = array();
198  $a = array();
199  $b = array();
200  foreach ($a_columns as $k => $col)
201  {
202  if($col[0] == 'clob' or $col[0] == 'blob')
203  {
204  $val_field[] = $this->quote($col[1], 'text')." ".$k;
205  }
206  else
207  {
208  $val_field[] = $this->quote($col[1], $col[0])." ".$k;
209  }
210  $fields[] = $k;
211  $placeholders[] = "%s";
212  $placeholders2[] = ":$k";
213  $types[] = $col[0];
214  $values[] = $col[1];
215  $field_values[$k] = $col[1];
216  if ($col[0] == "blob" || $col[0] == "clob")
217  {
218  $lobs = true;
219  $lob[$k] = $k;
220  }
221  $a[] = "a.".$k;
222  $b[] = "b.".$k;
223  }
224  $abpk = array();
225  $aboc = array();
226  $delwhere = array();
227  foreach ($a_pk_columns as $k => $col)
228  {
229  $abpk[] = "a.".$k." = b.".$k;
230  $delwhere[] = $k." = ".$this->quote($col[1], $col[0]);
231  }
232  foreach ($a_other_columns as $k => $col)
233  {
234  $aboc[] = "a.".$k." = b.".$k;
235  }
236  if ($lobs) // lobs -> use prepare execute (autoexecute broken in PEAR 2.4.1)
237  {
238  $this->manipulate("DELETE FROM ".$a_table." WHERE ".
239  implode ($delwhere, " AND ")
240  );
241  $this->insert($a_table, $a_columns);
242 
243  //$r = $this->db->extended->autoExecute($a_table, $field_values, MDB2_AUTOQUERY_INSERT, null, $types);
244  $this->handleError($r, "replace, delete/insert(".$a_table.")");
245  }
246  else // if no lobs are used, use manipulate
247  {
248  $q = "MERGE INTO ".$a_table." a ".
249  "USING (SELECT ".implode($val_field, ", ")." ".
250  "FROM DUAL) b ON (".implode($abpk, " AND ").") ".
251  "WHEN MATCHED THEN UPDATE SET ".implode($aboc, ", ")." ".
252  "WHEN NOT MATCHED THEN INSERT (".implode($a, ",").") VALUES (".implode($b, ",").")";
253  $r = $this->manipulate($q);
254  }
255  return $r;
256  }
257 
265  public function locate($a_needle,$a_string,$a_start_pos = 1)
266  {
267  $locate = ' INSTR( ';
268  $locate .= ('SUBSTR('.$a_string.',0,'.self::CLOB_BUFFER_SIZE.')');
269  $locate .= ',';
270  $locate .= $a_needle;
271  $locate .= ',';
272  $locate .= $a_start_pos;
273  $locate .= ') ';
274  return $locate;
275  }
276 
288  public function like($a_col, $a_type, $a_value = "?", $case_insensitive = true)
289  {
290  if($a_type == 'text')
291  {
292  return parent::like($a_col,$a_type,$a_value,$case_insensitive);
293  }
294 
295  if (!in_array($a_type, array("text", "clob", "blob")))
296  {
297  $this->raisePearError("Like: Invalid column type '".$a_type."'.", $this->error_class->FATAL);
298  }
299  if ($a_value == "?")
300  {
301  if ($case_insensitive)
302  {
303  return "UPPER(SUBSTR(".$a_col.",0,".self::CLOB_BUFFER_SIZE.")) LIKE(UPPER(?))";
304  }
305  else
306  {
307  return "SUBSTR(".$a_col .",0,".self::CLOB_BUFFER_SIZE.") LIKE(?)";
308  }
309  }
310  else
311  {
312  if ($case_insensitive)
313  {
314  return " UPPER(SUBSTR(".$a_col.",0,".self::CLOB_BUFFER_SIZE.")) LIKE(UPPER(".$this->quote($a_value, 'text')."))";
315  }
316  else
317  {
318  return " SUBSTR(".$a_col.",0,".self::CLOB_BUFFER_SIZE.") LIKE(".$this->quote($a_value, 'text').")";
319  }
320  }
321  }
322 
329  public function concat($a_values, $a_allow_null = true)
330  {
331  if(count($a_values) <= 2)
332  {
333  return parent::concat($a_values,false);
334  }
335 
336  $first = true;
337  foreach($a_values as $field_info)
338  {
339  if(!$first)
340  {
341  $concat_value = parent::concat(
342  array(
343  array($concat_value,$concat_type),
344  array($field_info[0],$field_info[1])),
345  false
346  );
347  }
348  else
349  {
350  $first = false;
351  $concat_value = $field_info[0];
352  $concat_type = $field_info[1];
353  }
354  }
355  return $concat_value;
356  }
357 
372  function in($a_field, $a_values, $negate = false, $a_type = "")
373  {
374  if(count($a_values) <= self::LIMIT_EXPRESSIONS_IN_LIST)
375  {
376  return parent::in($a_field,$a_values,$negate,$a_type);
377  }
378 
379  $first = true;
380  $concat = $negate ? ' AND ' : ' OR ';
381  $in = '(';
382  do
383  {
384  if(!$first)
385  {
386  $in .= $concat;
387 
388  }
389  $first = false;
390 
391  $spliced = array_splice($a_values, 0, self::LIMIT_EXPRESSIONS_IN_LIST);
392  $in .= parent::in($a_field, $spliced, $negate, $a_type);
393 
394  }
395  while($a_values);
396 
397  return $in." ) ";
398  }
399 
400 
410  public function lockTables($a_tables)
411  {
412  global $ilLog;
413 
414  $locks = array();
415 
416  $counter = 0;
417  foreach($a_tables as $table)
418  {
419  $lock = 'LOCK TABLE ';
420 
421  $lock .= ($table['name'].' ');
422 
423  switch($table['type'])
424  {
425  case ilDB::LOCK_READ:
426  $lock .= ' IN SHARE MODE ';
427  break;
428 
429  case ilDB::LOCK_WRITE:
430  $lock .= ' IN EXCLUSIVE MODE ';
431  break;
432  }
433 
434  $locks[] = $lock;
435  }
436 
437  // @TODO use and store a unique identifier to allow nested lock/unlocks
438  $this->db->beginTransaction();
439  foreach($locks as $lock)
440  {
441  $this->db->query($lock);
442  $ilLog->write(__METHOD__.': '.$lock);
443  }
444  return true;
445  }
446 
451  public function unlockTables()
452  {
453  $this->db->commit();
454  }
455 }
456 ?>