ILIAS  release_5-2 Revision v5.2.25-18-g3f80b828510
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/MDB2/class.ilDB.php");
6 
18 class ilDBOracle extends ilDB
19 {
20  const CLOB_BUFFER_SIZE = 2000;
22 
23 
24  public function loadModule($module) {
25  // TODO: Implement loadModule() method.
26  }
27 
28 
32  function getDSN()
33  {
34  // TODO: check if there is another solution.
35  // This works with 11g
36  if(!isset($GLOBALS['_MDB2_dsninfo_default']['charset']) or
37  $GLOBALS['_MDB2_dsninfo_default']['charset'] != 'utf8')
38  {
39  $GLOBALS['_MDB2_dsninfo_default']['charset'] = 'utf8';
40  }
41 
42  return array('phptype' => 'oci8',
43  'hostspec' => $this->getDBHost(),
44  'username' => $this->getDBUser(),
45  'password' => $this->getDBPassword(),
46  'port' => $this->getDBPort(),
47  'service' => $this->getDBName()
48  );
49 
50  //return "oci8://".$this->getDBUser().":".$this->getDBPassword()."@".
51  // $this->getDBHost()."/?service=".$this->getDBName();
52  }
53 
57  function getDBType()
58  {
59  return "oracle";
60  }
61 
62  public function getDBVersion()
63  {
64  $query = 'SELECT * FROM v$version';
65  $res = $this->db->query($query);
66 
67  if(MDB2::isError($res))
68  {
69  return parent::getDBVersion();
70  }
72  return isset($row['banner']) ? $row['banner'] : parent::getDBVersion();
73  }
74 
78  static function getReservedWords()
79  {
80  // version: 10g
81  // url: http://download-west.oracle.com/docs/cd/B14117_01/server.101/b10759/ap_keywd.htm#g691972
82  return array(
83  "ACCESS", "ADD", "ALL", "ALTER", "AND", "ANY", "AS", "ASC",
84  "AUDIT", "BETWEEN", "BY", "CHAR", "CHECK", "CLUSTER", "COLUMN",
85  "COMMENT", "COMPRESS", "CONNECT", "CREATE", "CURRENT", "DATE",
86  "DECIMAL", "DEFAULT", "DELETE", "DESC", "DISTINCT", "DROP", "ELSE",
87  "EXCLUSIVE", "EXISTS", "FILE", "FLOAT", "FOR", "FROM", "GRANT", "GROUP",
88  "HAVING", "IDENTIFIED", "IMMEDIATE", "IN", "INCREMENT", "INDEX", "INITIAL",
89  "INSERT", "INTEGER", "INTERSECT", "INTO", "IS", "LEVEL", "LIKE", "LOCK", "LONG",
90  "MAXEXTENTS", "MINUS", "MLSLABEL", "MODE", "MODIFY", "NOAUDIT", "NOCOMPRESS", "NOT",
91  "NOWAIT", "NULL", "NUMBER", "OF", "OFFLINE", "ON", "ONLINE","OPTION",
92  "OR", "ORDER", "PCTFREE", "PRIOR", "PRIVILEGES", "PUBLIC", "RAW", "RENAME",
93  "RESOURCE", "REVOKE", "ROW", "ROWID", "ROWNUM", "ROWS", "SELECT", "SESSION", "SET",
94  "SHARE", "SIZE", "SMALLINT", "START", "SUCCESSFUL", "SYNONYM", "SYSDATE","TABLE",
95  "THEN", "TO", "TRIGGER", "UID", "UNION", "UNIQUE", "UPDATE", "USER","VALIDATE",
96  "VALUES", "VARCHAR", "VARCHAR2", "VIEW", "WHENEVER", "WHERE", "WITH"
97  );
98  }
99 
103  function doConnect()
104  {
105  $this->db = MDB2::connect($this->getDSN(),
106  array("use_transactions" => true));
107  }
108 
112  function initConnection()
113  {
114  $GLOBALS['_MDB2_dsninfo_default']['charset'] = 'utf8';
115  $this->query("ALTER SESSION SET nls_length_semantics='CHAR'");
116  $this->query("ALTER SESSION SET NLS_SORT = binary_ci");
117  }
118 
119 /* function manipulate($sql)
120  {
121 //echo "1";
122 //if (!is_int(strpos($sql, "frm_thread_access")))
123 //{
124 //echo "2";
125  return parent::manipulate($sql);
126 //}
127 //echo "3";
128  }*/
129 
134  function now()
135  {
136  return "LOCALTIMESTAMP";
137  }
138 
142  function fromUnixtime($a_expr, $a_to_text = true)
143  {
144  if (!$a_to_text)
145  {
146  return "TO_DATE('19700101000000','YYYYMMDDHH24MISS') ".
147  "+ NUMTODSINTERVAL(".$a_expr.", 'SECOND')";
148  }
149  else
150  {
151  return "to_char(TO_DATE('19700101000000','YYYYMMDDHH24MISS') ".
152  "+ NUMTODSINTERVAL(".$a_expr.", 'SECOND'), 'yyyy-mm-dd hh24:mi:ss')";
153  }
154  }
155 
159  function unixTimestamp()
160  {
161  // sysdate should respect database time zone
162  // current_date would respect session time zone
163  return "ROUND((sysdate - to_date('01-JAN-1970','DD-MON-YYYY')) * (86400))";
164  }
165 
169  function constraintName($a_table, $a_constraint)
170  {
171  return $a_table."_".$a_constraint;
172  }
173 
178  {
179  return "pk";
180  }
181 
185  function supportsFulltext()
186  {
187  return false;
188  }
189 
197  function replace($a_table, $a_pk_columns, $a_other_columns)
198  {
199  $a_columns = array_merge($a_pk_columns, $a_other_columns);
200  $fields = array();
201  $field_values = array();
202  $placeholders = array();
203  $types = array();
204  $values = array();
205  $lobs = false;
206  $lob = array();
207  $val_field = array();
208  $a = array();
209  $b = array();
210  foreach ($a_columns as $k => $col)
211  {
212  if($col[0] == 'clob' or $col[0] == 'blob')
213  {
214  $val_field[] = $this->quote($col[1], 'text')." ".$k;
215  }
216  else
217  {
218  $val_field[] = $this->quote($col[1], $col[0])." ".$k;
219  }
220  $fields[] = $k;
221  $placeholders[] = "%s";
222  $placeholders2[] = ":$k";
223  $types[] = $col[0];
224 
225  // integer auto-typecast (this casts bool values to integer)
226  if ($col[0] == 'integer' && !is_null($col[1]))
227  {
228  $col[1] = (int) $col[1];
229  }
230 
231  $values[] = $col[1];
232  $field_values[$k] = $col[1];
233  if ($col[0] == "blob" || $col[0] == "clob")
234  {
235  $lobs = true;
236  $lob[$k] = $k;
237  }
238  $a[] = "a.".$k;
239  $b[] = "b.".$k;
240  }
241  $abpk = array();
242  $aboc = array();
243  $delwhere = array();
244  foreach ($a_pk_columns as $k => $col)
245  {
246  $abpk[] = "a.".$k." = b.".$k;
247  $delwhere[] = $k." = ".$this->quote($col[1], $col[0]);
248  }
249  foreach ($a_other_columns as $k => $col)
250  {
251  $aboc[] = "a.".$k." = b.".$k;
252  }
253  if ($lobs) // delete/insert
254  {
255  $this->manipulate("DELETE FROM ".$a_table." WHERE ".
256  implode ($delwhere, " AND ")
257  );
258  $this->insert($a_table, $a_columns);
259 
260  //$r = $this->db->extended->autoExecute($a_table, $field_values, MDB2_AUTOQUERY_INSERT, null, $types);
261  $this->handleError($r, "replace, delete/insert(".$a_table.")");
262  }
263  else // if no lobs are used, use manipulate
264  {
265  $q = "MERGE INTO ".$a_table." a ".
266  "USING (SELECT ".implode($val_field, ", ")." ".
267  "FROM DUAL) b ON (".implode($abpk, " AND ").") ".
268  "WHEN MATCHED THEN UPDATE SET ".implode($aboc, ", ")." ".
269  "WHEN NOT MATCHED THEN INSERT (".implode($a, ",").") VALUES (".implode($b, ",").")";
270  $r = $this->manipulate($q);
271  }
272  return $r;
273  }
274 
282  public function locate($a_needle,$a_string,$a_start_pos = 1)
283  {
284  $locate = ' INSTR( ';
285  $locate .= ('SUBSTR('.$a_string.',0,'.self::CLOB_BUFFER_SIZE.')');
286  $locate .= ',';
287  $locate .= $a_needle;
288  $locate .= ',';
289  $locate .= $a_start_pos;
290  $locate .= ') ';
291  return $locate;
292  }
293 
305  public function like($a_col, $a_type, $a_value = "?", $case_insensitive = true)
306  {
307  if($a_type == 'text')
308  {
309  return parent::like($a_col,$a_type,$a_value,$case_insensitive);
310  }
311 
312  if (!in_array($a_type, array("text", "clob", "blob")))
313  {
314  $this->raisePearError("Like: Invalid column type '".$a_type."'.", $this->error_class->FATAL);
315  }
316  if ($a_value == "?")
317  {
318  if ($case_insensitive)
319  {
320  return "UPPER(SUBSTR(".$a_col.",0,".self::CLOB_BUFFER_SIZE.")) LIKE(UPPER(?))";
321  }
322  else
323  {
324  return "SUBSTR(".$a_col .",0,".self::CLOB_BUFFER_SIZE.") LIKE(?)";
325  }
326  }
327  else
328  {
329  if ($case_insensitive)
330  {
331  return " UPPER(SUBSTR(".$a_col.",0,".self::CLOB_BUFFER_SIZE.")) LIKE(UPPER(".$this->quote($a_value, 'text')."))";
332  }
333  else
334  {
335  return " SUBSTR(".$a_col.",0,".self::CLOB_BUFFER_SIZE.") LIKE(".$this->quote($a_value, 'text').")";
336  }
337  }
338  }
339 
346  public function concat(array $a_values, $a_allow_null = true)
347  {
348  if(count($a_values) <= 2)
349  {
350  return parent::concat($a_values,false);
351  }
352 
353  $first = true;
354  foreach($a_values as $field_info)
355  {
356  if(!$first)
357  {
358  $concat_value = parent::concat(
359  array(
360  array($concat_value,$concat_type),
361  array($field_info[0],$field_info[1])),
362  false
363  );
364  }
365  else
366  {
367  $first = false;
368  $concat_value = $field_info[0];
369  $concat_type = $field_info[1];
370  }
371  }
372  return $concat_value;
373  }
374 
389  function in($a_field, $a_values, $negate = false, $a_type = "")
390  {
391  if(count($a_values) <= self::LIMIT_EXPRESSIONS_IN_LIST)
392  {
393  return parent::in($a_field,$a_values,$negate,$a_type);
394  }
395 
396  $first = true;
397  $concat = $negate ? ' AND ' : ' OR ';
398  $in = '(';
399  do
400  {
401  if(!$first)
402  {
403  $in .= $concat;
404 
405  }
406  $first = false;
407 
408  $spliced = array_splice($a_values, 0, self::LIMIT_EXPRESSIONS_IN_LIST);
409  $in .= parent::in($a_field, $spliced, $negate, $a_type);
410 
411  }
412  while($a_values);
413 
414  return $in." ) ";
415  }
416 
417 
428  public function lockTables($a_tables)
429  {
430  global $ilLog;
431 
432  $locks = array();
433 
434  $counter = 0;
435  foreach($a_tables as $table)
436  {
437  $lock = 'LOCK TABLE ';
438 
439  $lock .= ($table['name'].' ');
440 
441  switch($table['type'])
442  {
444  $lock .= ' IN SHARE MODE ';
445  break;
446 
448  $lock .= ' IN EXCLUSIVE MODE ';
449  break;
450  }
451 
452  $locks[] = $lock;
453  }
454 
455  // @TODO use and store a unique identifier to allow nested lock/unlocks
456  $this->db->beginTransaction();
457  foreach($locks as $lock)
458  {
459  $this->db->query($lock);
460  $ilLog->write(__METHOD__.': '.$lock);
461  }
462  return true;
463  }
464 
470  public function unlockTables()
471  {
472  $this->db->commit();
473  }
474 
480  function dropPrimaryKey($a_table)
481  {
482  // oracle 10: dropping constraint may not drop attached index
483  // http://www.orafaq.com/forum/t/59807/0/
484 
485  $query = "ALTER TABLE ".$a_table." DROP PRIMARY KEY DROP INDEX";
486  $res = $this->db->query($query);
487 
488  return $this->handleError($res, "dropPrimaryKey(".$a_table.")");
489  }
490 
491 
492  public function setStorageEngine($storage_engine) {
493  unset($storage_engine);
494  }
495 
496 
497  public function getStorageEngine() {
498  return null;
499  }
500 
501 
502  public function dropFulltextIndex($a_table, $a_name) {
503  return false;
504  }
505 }
raisePearError($a_message, $a_level="")
Raise an error.
Definition: class.ilDB.php:459
getPrimaryKeyIdentifier()
Primary key identifier.
isError($data, $code=null)
Tell whether a value is a MDB2 error.
Definition: MDB2.php:599
query($sql, $a_handle_error=true)
Query.
doConnect()
Standard way to connect to db.
unlockTables()
Unlock tables.
$GLOBALS['loaded']
Global hash that tracks already loaded includes.
dropPrimaryKey($a_table)
Drop a primary key from a table.
getDBPort()
Get database port.
Definition: class.ilDB.php:103
setStorageEngine($storage_engine)
unixTimestamp()
Unix timestamp.
constraintName($a_table, $a_constraint)
Constraint names must be "globally" unique in oracle.
getDBName()
Get database name.
Definition: class.ilDB.php:163
$counter
$a_type
Definition: workflow.php:93
quote($a_query, $a_type=null)
Wrapper for quote method.
lockTables($a_tables)
Lock table.
$r
Definition: example_031.php:79
getDBHost()
Get database host.
Definition: class.ilDB.php:123
getDBType()
Get DB Type.
loadModule($module)
getDBUser()
Get database user.
Definition: class.ilDB.php:83
& connect($dsn, $options=false)
Create a new MDB2 connection object and connect to the specified database.
Definition: MDB2.php:436
like($a_col, $a_type, $a_value="?", $case_insensitive=true)
Provisional LIKE support for oracle CLOB&#39;s Uses SUBSTR to reduce the length.
const LIMIT_EXPRESSIONS_IN_LIST
handleError($a_res, $a_info="", $a_level="")
Handle MDB2 Errors.
Definition: class.ilDB.php:423
const CLOB_BUFFER_SIZE
insert($a_table, $a_columns)
Convenient method for standard insert statements, example field array:
initConnection()
Initialize the database connection.
Create styles array
The data for the language used.
if(php_sapi_name() !='cli') $in
Definition: Utf8Test.php:37
getDSN()
Get DSN.
manipulate($sql)
Data manipulation.
Database Wrapper.
Definition: class.ilDB.php:29
dropFulltextIndex($a_table, $a_name)
replace($a_table, $a_pk_columns, $a_other_columns)
Replace into method.
supportsFulltext()
Is fulltext index supported?
concat(array $a_values, $a_allow_null=true)
CONCAT for oracle allows only the concatenation of two values.
fromUnixtime($a_expr, $a_to_text=true)
fromUnixtime (makes timestamp out of unix timestamp)
getDBPassword()
Get database password.
Definition: class.ilDB.php:143
static getReservedWords()
Get reserved words.
in($a_field, $a_values, $negate=false, $a_type="")
Overwritten implementation of $ilDB->in to avoid ORA-01795 (maximum number of expressions in a list i...
Oracle Database Wrapper.
locate($a_needle, $a_string, $a_start_pos=1)
Create locate string.