6 * @copyright (c) 2005 phpBB Group
7 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
14 if (!defined('IN_PHPBB'))
19 include_once($phpbb_root_path . 'includes/db/dbal.' . $phpEx);
22 * Oracle Database Abstraction Layer
25 class dbal_oracle
extends dbal
27 var $last_query_text = '';
32 function sql_connect($sqlserver, $sqluser, $sqlpassword, $database, $port = false, $persistency = false)
34 $this->persistency
= $persistency;
35 $this->user
= $sqluser;
36 $this->server
= $sqlserver . (($port) ?
':' . $port : '');
37 $this->dbname
= $database;
39 $this->db_connect_id
= ($this->persistency
) ? @ociplogon
($this->user
, $sqlpassword, $this->server
, 'UTF8') : @ocinlogon
($this->user
, $sqlpassword, $this->server
, 'UTF8');
41 return ($this->db_connect_id
) ?
$this->db_connect_id
: $this->sql_error('');
45 * Version information about used database
47 function sql_server_info()
49 return @ociserverversion
($this->db_connect_id
);
56 function _sql_transaction($status = 'begin')
65 return @ocicommit
($this->db_connect_id
);
69 return @ocirollback
($this->db_connect_id
);
79 * @param string $query Contains the SQL query which shall be executed
80 * @param int $cache_ttl Either 0 to avoid caching or the time in seconds which the result shall be kept in cache
81 * @return mixed When casted to bool the returned value returns true on success and false on failure
85 function sql_query($query = '', $cache_ttl = 0)
91 // EXPLAIN only in extra debug mode
92 if (defined('DEBUG_EXTRA'))
94 $this->sql_report('start', $query);
97 $this->last_query_text
= $query;
98 $this->query_result
= ($cache_ttl && method_exists($cache, 'sql_load')) ?
$cache->sql_load($query) : false;
99 $this->sql_add_num_queries($this->query_result
);
101 if ($this->query_result
=== false)
103 $in_transaction = false;
104 if (!$this->transaction
)
106 $this->sql_transaction('begin');
110 $in_transaction = true;
115 // We overcome Oracle's 4000 char limit by binding vars
116 if (preg_match('/^(INSERT INTO[^(]+)\\(([^()]+)\\) VALUES[^(]+\\(([^()]+)\\)$/', $query, $regs))
118 if (strlen($regs[3]) > 4000)
120 $cols = explode(', ', $regs[2]);
121 $vals = explode(', ', $regs[3]);
122 foreach ($vals as $key => $value)
124 if (strlen($value) > 4002) // check to see if this thing is greater than the max + 'x2
126 $vals[$key] = ':' . strtoupper($cols[$key]);
127 $array[$vals[$key]] = substr($value, 1, -1);
130 $query = $regs[1] . '(' . implode(', ', $cols) . ') VALUES (' . implode(', ', $vals) . ')';
133 else if (preg_match('/^(UPDATE.*?)SET (.*)(\\sWHERE.*)$/s', $query, $regs))
135 if (strlen($regs[2]) > 4000)
137 $args = explode(', ', $regs[2]);
139 foreach ($args as $value)
141 $temp_array = explode('=', $value);
142 $cols[$temp_array[0]] = $temp_array[1];
145 foreach ($cols as $col => $val)
147 if (strlen($val) > 4003) // check to see if this thing is greater than the max + 'x2 + a space
149 $cols[$col] = ' :' . strtoupper(rtrim($col));
150 $array[ltrim($cols[$col])] = substr(trim($val), 2, -1);
155 foreach ($cols as $col => $val)
157 $art[] = $col . '=' . $val;
159 $query = $regs[1] . 'SET ' . implode(', ', $art) . $regs[3];
163 $this->query_result
= @ociparse
($this->db_connect_id
, $query);
165 foreach ($array as $key => $value)
167 @ocibindbyname
($this->query_result
, $key, $array[$key], -1);
170 $success = @ociexecute
($this->query_result
, OCI_DEFAULT
);
174 $this->sql_error($query);
175 $this->query_result
= false;
179 if (!$in_transaction)
181 $this->sql_transaction('commit');
185 if (defined('DEBUG_EXTRA'))
187 $this->sql_report('stop', $query);
190 if ($cache_ttl && method_exists($cache, 'sql_save'))
192 $this->open_queries
[(int) $this->query_result
] = $this->query_result
;
193 $cache->sql_save($query, $this->query_result
, $cache_ttl);
195 else if (strpos($query, 'SELECT') === 0 && $this->query_result
)
197 $this->open_queries
[(int) $this->query_result
] = $this->query_result
;
200 else if (defined('DEBUG_EXTRA'))
202 $this->sql_report('fromcache', $query);
210 return ($this->query_result
) ?
$this->query_result
: false;
216 function _sql_query_limit($query, $total, $offset = 0, $cache_ttl = 0)
218 $this->query_result
= false;
220 $query = 'SELECT * FROM (SELECT /*+ FIRST_ROWS */ rownum AS xrownum, a.* FROM (' . $query . ') a WHERE rownum <= ' . ($offset +
$total) . ') WHERE xrownum >= ' . $offset;
222 return $this->sql_query($query, $cache_ttl);
226 * Return number of affected rows
228 function sql_affectedrows()
230 return ($this->query_result
) ? @ocirowcount
($this->query_result
) : false;
236 function sql_fetchrow($query_id = false)
240 if ($query_id === false)
242 $query_id = $this->query_result
;
245 if (isset($cache->sql_rowset
[$query_id]))
247 return $cache->sql_fetchrow($query_id);
250 if ($query_id !== false)
253 $result = @ocifetchinto
($query_id, $row, OCI_ASSOC + OCI_RETURN_NULLS
);
255 if (!$result ||
!$row)
260 $result_row = array();
261 foreach ($row as $key => $value)
264 if (is_object($value))
266 $value = $value->load();
269 $result_row[strtolower($key)] = $value;
279 * Seek to given row number
280 * rownum is zero-based
282 function sql_rowseek($rownum, $query_id = false)
286 if ($query_id === false)
288 $query_id = $this->query_result
;
291 if (isset($cache->sql_rowset
[$query_id]))
293 return $cache->sql_rowseek($rownum, $query_id);
296 if ($query_id === false)
301 // Reset internal pointer
302 @ociexecute
($query_id, OCI_DEFAULT
);
304 // We do not fetch the row for rownum == 0 because then the next resultset would be the second row
305 for ($i = 0; $i < $rownum; $i++
)
307 if (!$this->sql_fetchrow($query_id))
317 * Get last inserted id after insert statement
319 function sql_nextid()
321 $query_id = $this->query_result
;
323 if ($query_id !== false && $this->last_query_text
!= '')
325 if (preg_match('#^INSERT[\t\n ]+INTO[\t\n ]+([a-z0-9\_\-]+)#is', $this->last_query_text
, $tablename))
327 $query = 'SELECT ' . $tablename[1] . '_seq.currval FROM DUAL';
328 $stmt = @ociparse
($this->db_connect_id
, $query);
329 @ociexecute
($stmt, OCI_DEFAULT
);
331 $temp_result = @ocifetchinto
($stmt, $temp_array, OCI_ASSOC + OCI_RETURN_NULLS
);
332 @ocifreestatement
($stmt);
336 return $temp_array['CURRVAL'];
351 function sql_freeresult($query_id = false)
355 if ($query_id === false)
357 $query_id = $this->query_result
;
360 if (isset($cache->sql_rowset
[$query_id]))
362 return $cache->sql_freeresult($query_id);
365 if (isset($this->open_queries
[(int) $query_id]))
367 unset($this->open_queries
[(int) $query_id]);
368 return @ocifreestatement
($query_id);
375 * Escape string used in sql query
377 function sql_escape($msg)
379 return str_replace("'", "''", $msg);
382 function _sql_custom_build($stage, $data)
388 * return sql error array
391 function _sql_error()
393 $error = @ocierror
();
394 $error = (!$error) ? @ocierror
($this->query_result
) : $error;
395 $error = (!$error) ? @ocierror
($this->db_connect_id
) : $error;
399 $this->last_error_result
= $error;
403 $error = (isset($this->last_error_result
) && $this->last_error_result
) ?
$this->last_error_result
: array();
410 * Close sql connection
413 function _sql_close()
415 return @ocilogoff
($this->db_connect_id
);
419 * Build db-specific report
422 function _sql_report($mode, $query = '')
430 $endtime = explode(' ', microtime());
431 $endtime = $endtime[0] +
$endtime[1];
433 $result = @ociparse
($this->db_connect_id
, $query);
434 $success = @ociexecute
($result, OCI_DEFAULT
);
437 while (@ocifetchinto
($result, $row, OCI_ASSOC + OCI_RETURN_NULLS
))
439 // Take the time spent on parsing rows into account
441 @ocifreestatement
($result);
443 $splittime = explode(' ', microtime());
444 $splittime = $splittime[0] +
$splittime[1];
446 $this->sql_report('record_fromcache', $query, $endtime, $splittime);