| <?php |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| if (!defined('IN_PHPBB')) |
| { |
| exit; |
| } |
| |
| include_once($phpbb_root_path . 'includes/db/dbal.' . $phpEx); |
| |
| |
| |
| |
| |
| class dbal_oracle extends dbal |
| { |
| var $last_query_text = ''; |
| |
| |
| |
| |
| function sql_connect($sqlserver, $sqluser, $sqlpassword, $database, $port = false, $persistency = false, $new_link = false) |
| { |
| $this->persistency = $persistency; |
| $this->user = $sqluser; |
| $this->server = $sqlserver . (($port) ? ':' . $port : ''); |
| $this->dbname = $database; |
| |
| $connect = $database; |
| |
| |
| if ($sqlserver !== '' && $sqlserver !== '/') |
| { |
| if (substr($sqlserver, -1, 1) == '/') |
| { |
| $sqlserver == substr($sqlserver, 0, -1); |
| } |
| $connect = $sqlserver . (($port) ? ':' . $port : '') . '/' . $database; |
| } |
| |
| $this->db_connect_id = ($new_link) ? @ocinlogon($this->user, $sqlpassword, $connect, 'UTF8') : (($this->persistency) ? @ociplogon($this->user, $sqlpassword, $connect, 'UTF8') : @ocilogon($this->user, $sqlpassword, $connect, 'UTF8')); |
| |
| return ($this->db_connect_id) ? $this->db_connect_id : $this->sql_error(''); |
| } |
| |
| |
| |
| |
| |
| |
| function sql_server_info($raw = false) |
| { |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| $this->sql_server_version = @ociserverversion($this->db_connect_id); |
| |
| return $this->sql_server_version; |
| } |
| |
| |
| |
| |
| |
| function _sql_transaction($status = 'begin') |
| { |
| switch ($status) |
| { |
| case 'begin': |
| return true; |
| break; |
| |
| case 'commit': |
| return @ocicommit($this->db_connect_id); |
| break; |
| |
| case 'rollback': |
| return @ocirollback($this->db_connect_id); |
| break; |
| } |
| |
| return true; |
| } |
| |
| |
| |
| |
| |
| function _rewrite_col_compare($args) |
| { |
| if (sizeof($args) == 4) |
| { |
| if ($args[2] == '=') |
| { |
| return '(' . $args[0] . ' OR (' . $args[1] . ' is NULL AND ' . $args[3] . ' is NULL))'; |
| } |
| else if ($args[2] == '<>') |
| { |
| |
| return '(' . $args[0] . ' OR ((' . $args[1] . ' is NULL AND ' . $args[3] . ' is NOT NULL) OR (' . $args[1] . ' is NOT NULL AND ' . $args[3] . ' is NULL)))'; |
| } |
| } |
| else |
| { |
| return $this->_rewrite_where($args[0]); |
| } |
| } |
| |
| |
| |
| |
| |
| function _rewrite_where($where_clause) |
| { |
| preg_match_all('/\s*(AND|OR)?\s*([\w_.]++)\s*(?:(=|<[=>]?|>=?)\s*((?>\'(?>[^\']++|\'\')*+\'|[\d-.]+))|((NOT )?IN\s*\((?>\'(?>[^\']++|\'\')*+\',? ?|[\d-.]+,? ?)*+\)))/', $where_clause, $result, PREG_SET_ORDER); |
| $out = ''; |
| foreach ($result as $val) |
| { |
| if (!isset($val[5])) |
| { |
| if ($val[4] !== "''") |
| { |
| $out .= $val[0]; |
| } |
| else |
| { |
| $out .= ' ' . $val[1] . ' ' . $val[2]; |
| if ($val[3] == '=') |
| { |
| $out .= ' is NULL'; |
| } |
| else if ($val[3] == '<>') |
| { |
| $out .= ' is NOT NULL'; |
| } |
| } |
| } |
| else |
| { |
| $in_clause = array(); |
| $sub_exp = substr($val[5], strpos($val[5], '(') + 1, -1); |
| $extra = false; |
| preg_match_all('/\'(?>[^\']++|\'\')*+\'|[\d-.]++/', $sub_exp, $sub_vals, PREG_PATTERN_ORDER); |
| $i = 0; |
| foreach ($sub_vals[0] as $sub_val) |
| { |
| |
| |
| |
| if ($sub_val !== "''") |
| { |
| $in_clause[(int) $i++/1000][] = $sub_val; |
| } |
| else |
| { |
| $extra = true; |
| } |
| } |
| if (!$extra && $i < 1000) |
| { |
| $out .= $val[0]; |
| } |
| else |
| { |
| $out .= ' ' . $val[1] . '('; |
| $in_array = array(); |
| |
| |
| foreach ($in_clause as $in_values) |
| { |
| $in_array[] = $val[2] . ' ' . (isset($val[6]) ? $val[6] : '') . 'IN(' . implode(', ', $in_values) . ')'; |
| } |
| |
| |
| $out .= implode(' OR ', $in_array); |
| |
| |
| if ($extra) |
| { |
| $out .= ' OR ' . $val[2] . ' is ' . (isset($val[6]) ? $val[6] : '') . 'NULL'; |
| } |
| $out .= ')'; |
| |
| unset($in_array, $in_clause); |
| } |
| } |
| } |
| |
| return $out; |
| } |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| function sql_query($query = '', $cache_ttl = 0) |
| { |
| if ($query != '') |
| { |
| global $cache; |
| |
| |
| if (defined('DEBUG_EXTRA')) |
| { |
| $this->sql_report('start', $query); |
| } |
| |
| $this->last_query_text = $query; |
| $this->query_result = ($cache_ttl && method_exists($cache, 'sql_load')) ? $cache->sql_load($query) : false; |
| $this->sql_add_num_queries($this->query_result); |
| |
| if ($this->query_result === false) |
| { |
| $in_transaction = false; |
| if (!$this->transaction) |
| { |
| $this->sql_transaction('begin'); |
| } |
| else |
| { |
| $in_transaction = true; |
| } |
| |
| $array = array(); |
| |
| |
| if (strlen($query) > 4000) |
| { |
| if (preg_match('/^(INSERT INTO[^(]++)\\(([^()]+)\\) VALUES[^(]++\\((.*?)\\)$/s', $query, $regs)) |
| { |
| if (strlen($regs[3]) > 4000) |
| { |
| $cols = explode(', ', $regs[2]); |
| preg_match_all('/\'(?:[^\']++|\'\')*+\'|[\d-.]+/', $regs[3], $vals, PREG_PATTERN_ORDER); |
| |
| $inserts = $vals[0]; |
| unset($vals); |
| |
| foreach ($inserts as $key => $value) |
| { |
| if (!empty($value) && $value[0] === "'" && strlen($value) > 4002) |
| { |
| $inserts[$key] = ':' . strtoupper($cols[$key]); |
| $array[$inserts[$key]] = str_replace("''", "'", substr($value, 1, -1)); |
| } |
| } |
| |
| $query = $regs[1] . '(' . $regs[2] . ') VALUES (' . implode(', ', $inserts) . ')'; |
| } |
| } |
| else if (preg_match_all('/^(UPDATE [\\w_]++\\s+SET )([\\w_]++\\s*=\\s*(?:\'(?:[^\']++|\'\')*+\'|[\d-.]+)(?:,\\s*[\\w_]++\\s*=\\s*(?:\'(?:[^\']++|\'\')*+\'|[\d-.]+))*+)\\s+(WHERE.*)$/s', $query, $data, PREG_SET_ORDER)) |
| { |
| if (strlen($data[0][2]) > 4000) |
| { |
| $update = $data[0][1]; |
| $where = $data[0][3]; |
| preg_match_all('/([\\w_]++)\\s*=\\s*(\'(?:[^\']++|\'\')*+\'|[\d-.]++)/', $data[0][2], $temp, PREG_SET_ORDER); |
| unset($data); |
| |
| $cols = array(); |
| foreach ($temp as $value) |
| { |
| if (!empty($value[2]) && $value[2][0] === "'" && strlen($value[2]) > 4002) |
| { |
| $cols[] = $value[1] . '=:' . strtoupper($value[1]); |
| $array[$value[1]] = str_replace("''", "'", substr($value[2], 1, -1)); |
| } |
| else |
| { |
| $cols[] = $value[1] . '=' . $value[2]; |
| } |
| } |
| |
| $query = $update . implode(', ', $cols) . ' ' . $where; |
| unset($cols); |
| } |
| } |
| } |
| |
| switch (substr($query, 0, 6)) |
| { |
| case 'DELETE': |
| if (preg_match('/^(DELETE FROM [\w_]++ WHERE)((?:\s*(?:AND|OR)?\s*[\w_]+\s*(?:(?:=|<>)\s*(?>\'(?>[^\']++|\'\')*+\'|[\d-.]+)|(?:NOT )?IN\s*\((?>\'(?>[^\']++|\'\')*+\',? ?|[\d-.]+,? ?)*+\)))*+)$/', $query, $regs)) |
| { |
| $query = $regs[1] . $this->_rewrite_where($regs[2]); |
| unset($regs); |
| } |
| break; |
| |
| case 'UPDATE': |
| if (preg_match('/^(UPDATE [\\w_]++\\s+SET [\\w_]+\s*=\s*(?:\'(?:[^\']++|\'\')*+\'|[\d-.]++|:\w++)(?:, [\\w_]+\s*=\s*(?:\'(?:[^\']++|\'\')*+\'|[\d-.]++|:\w++))*+\\s+WHERE)(.*)$/s', $query, $regs)) |
| { |
| $query = $regs[1] . $this->_rewrite_where($regs[2]); |
| unset($regs); |
| } |
| break; |
| |
| case 'SELECT': |
| $query = preg_replace_callback('/([\w_.]++)\s*(?:(=|<>)\s*(?>\'(?>[^\']++|\'\')*+\'|[\d-.]++|([\w_.]++))|(?:NOT )?IN\s*\((?>\'(?>[^\']++|\'\')*+\',? ?|[\d-.]++,? ?)*+\))/', array($this, '_rewrite_col_compare'), $query); |
| break; |
| } |
| |
| $this->query_result = @ociparse($this->db_connect_id, $query); |
| |
| foreach ($array as $key => $value) |
| { |
| @ocibindbyname($this->query_result, $key, $array[$key], -1); |
| } |
| |
| $success = @ociexecute($this->query_result, OCI_DEFAULT); |
| |
| if (!$success) |
| { |
| $this->sql_error($query); |
| $this->query_result = false; |
| } |
| else |
| { |
| if (!$in_transaction) |
| { |
| $this->sql_transaction('commit'); |
| } |
| } |
| |
| if (defined('DEBUG_EXTRA')) |
| { |
| $this->sql_report('stop', $query); |
| } |
| |
| if ($cache_ttl && method_exists($cache, 'sql_save')) |
| { |
| $this->open_queries[(int) $this->query_result] = $this->query_result; |
| $cache->sql_save($query, $this->query_result, $cache_ttl); |
| } |
| else if (strpos($query, 'SELECT') === 0 && $this->query_result) |
| { |
| $this->open_queries[(int) $this->query_result] = $this->query_result; |
| } |
| } |
| else if (defined('DEBUG_EXTRA')) |
| { |
| $this->sql_report('fromcache', $query); |
| } |
| } |
| else |
| { |
| return false; |
| } |
| |
| return $this->query_result; |
| } |
| |
| |
| |
| |
| function _sql_query_limit($query, $total, $offset = 0, $cache_ttl = 0) |
| { |
| $this->query_result = false; |
| |
| $query = 'SELECT * FROM (SELECT /*+ FIRST_ROWS */ rownum AS xrownum, a.* FROM (' . $query . ') a WHERE rownum <= ' . ($offset + $total) . ') WHERE xrownum >= ' . $offset; |
| |
| return $this->sql_query($query, $cache_ttl); |
| } |
| |
| |
| |
| |
| function sql_affectedrows() |
| { |
| return ($this->query_result) ? @ocirowcount($this->query_result) : false; |
| } |
| |
| |
| |
| |
| function sql_fetchrow($query_id = false) |
| { |
| global $cache; |
| |
| if ($query_id === false) |
| { |
| $query_id = $this->query_result; |
| } |
| |
| if (isset($cache->sql_rowset[$query_id])) |
| { |
| return $cache->sql_fetchrow($query_id); |
| } |
| |
| if ($query_id !== false) |
| { |
| $row = array(); |
| $result = @ocifetchinto($query_id, $row, OCI_ASSOC + OCI_RETURN_NULLS); |
| |
| if (!$result || !$row) |
| { |
| return false; |
| } |
| |
| $result_row = array(); |
| foreach ($row as $key => $value) |
| { |
| |
| if (is_null($value)) |
| { |
| $value = ''; |
| } |
| |
| |
| if (is_object($value)) |
| { |
| $value = $value->load(); |
| } |
| |
| $result_row[strtolower($key)] = $value; |
| } |
| |
| return $result_row; |
| } |
| |
| return false; |
| } |
| |
| |
| |
| |
| |
| function sql_rowseek($rownum, &$query_id) |
| { |
| global $cache; |
| |
| if ($query_id === false) |
| { |
| $query_id = $this->query_result; |
| } |
| |
| if (isset($cache->sql_rowset[$query_id])) |
| { |
| return $cache->sql_rowseek($rownum, $query_id); |
| } |
| |
| if ($query_id === false) |
| { |
| return false; |
| } |
| |
| |
| @ociexecute($query_id, OCI_DEFAULT); |
| |
| |
| for ($i = 0; $i < $rownum; $i++) |
| { |
| if (!$this->sql_fetchrow($query_id)) |
| { |
| return false; |
| } |
| } |
| |
| return true; |
| } |
| |
| |
| |
| |
| function sql_nextid() |
| { |
| $query_id = $this->query_result; |
| |
| if ($query_id !== false && $this->last_query_text != '') |
| { |
| if (preg_match('#^INSERT[\t\n ]+INTO[\t\n ]+([a-z0-9\_\-]+)#is', $this->last_query_text, $tablename)) |
| { |
| $query = 'SELECT ' . $tablename[1] . '_seq.currval FROM DUAL'; |
| $stmt = @ociparse($this->db_connect_id, $query); |
| @ociexecute($stmt, OCI_DEFAULT); |
| |
| $temp_result = @ocifetchinto($stmt, $temp_array, OCI_ASSOC + OCI_RETURN_NULLS); |
| @ocifreestatement($stmt); |
| |
| if ($temp_result) |
| { |
| return $temp_array['CURRVAL']; |
| } |
| else |
| { |
| return false; |
| } |
| } |
| } |
| |
| return false; |
| } |
| |
| |
| |
| |
| function sql_freeresult($query_id = false) |
| { |
| global $cache; |
| |
| if ($query_id === false) |
| { |
| $query_id = $this->query_result; |
| } |
| |
| if (isset($cache->sql_rowset[$query_id])) |
| { |
| return $cache->sql_freeresult($query_id); |
| } |
| |
| if (isset($this->open_queries[(int) $query_id])) |
| { |
| unset($this->open_queries[(int) $query_id]); |
| return @ocifreestatement($query_id); |
| } |
| |
| return false; |
| } |
| |
| |
| |
| |
| function sql_escape($msg) |
| { |
| return str_replace(array("'", "\0"), array("''", ''), $msg); |
| } |
| |
| |
| |
| |
| |
| function _sql_like_expression($expression) |
| { |
| return $expression . " ESCAPE '\\'"; |
| } |
| |
| function _sql_custom_build($stage, $data) |
| { |
| return $data; |
| } |
| |
| |
| |
| |
| |
| function _sql_error() |
| { |
| $error = @ocierror(); |
| $error = (!$error) ? @ocierror($this->query_result) : $error; |
| $error = (!$error) ? @ocierror($this->db_connect_id) : $error; |
| |
| if ($error) |
| { |
| $this->last_error_result = $error; |
| } |
| else |
| { |
| $error = (isset($this->last_error_result) && $this->last_error_result) ? $this->last_error_result : array(); |
| } |
| |
| return $error; |
| } |
| |
| |
| |
| |
| |
| function _sql_close() |
| { |
| return @ocilogoff($this->db_connect_id); |
| } |
| |
| |
| |
| |
| |
| function _sql_report($mode, $query = '') |
| { |
| switch ($mode) |
| { |
| case 'start': |
| |
| $html_table = false; |
| |
| |
| $sql = "SELECT table_name |
| FROM USER_TABLES |
| WHERE table_name LIKE '%PLAN_TABLE%'"; |
| $stmt = ociparse($this->db_connect_id, $sql); |
| ociexecute($stmt); |
| $result = array(); |
| |
| if (ocifetchinto($stmt, $result, OCI_ASSOC + OCI_RETURN_NULLS)) |
| { |
| $table = $result['TABLE_NAME']; |
| |
| |
| $statement_id = substr(md5($query), 0, 30); |
| |
| |
| $stmt2 = ociparse($this->db_connect_id, "DELETE FROM $table WHERE statement_id='$statement_id'"); |
| ociexecute($stmt2); |
| ocifreestatement($stmt2); |
| |
| |
| $sql = "EXPLAIN PLAN |
| SET STATEMENT_ID = '$statement_id' |
| FOR $query"; |
| $stmt2 = ociparse($this->db_connect_id, $sql); |
| ociexecute($stmt2); |
| ocifreestatement($stmt2); |
| |
| |
| $sql = "SELECT operation, options, object_name, object_type, cardinality, cost |
| FROM plan_table |
| START WITH id = 0 AND statement_id = '$statement_id' |
| CONNECT BY PRIOR id = parent_id |
| AND statement_id = '$statement_id'"; |
| $stmt2 = ociparse($this->db_connect_id, $sql); |
| ociexecute($stmt2); |
| |
| $row = array(); |
| while (ocifetchinto($stmt2, $row, OCI_ASSOC + OCI_RETURN_NULLS)) |
| { |
| $html_table = $this->sql_report('add_select_row', $query, $html_table, $row); |
| } |
| |
| ocifreestatement($stmt2); |
| |
| |
| $stmt2 = ociparse($this->db_connect_id, "DELETE FROM $table WHERE statement_id='$statement_id'"); |
| ociexecute($stmt2); |
| ocifreestatement($stmt2); |
| } |
| |
| ocifreestatement($stmt); |
| |
| if ($html_table) |
| { |
| $this->html_hold .= '</table>'; |
| } |
| |
| break; |
| |
| case 'fromcache': |
| $endtime = explode(' ', microtime()); |
| $endtime = $endtime[0] + $endtime[1]; |
| |
| $result = @ociparse($this->db_connect_id, $query); |
| $success = @ociexecute($result, OCI_DEFAULT); |
| $row = array(); |
| |
| while (@ocifetchinto($result, $row, OCI_ASSOC + OCI_RETURN_NULLS)) |
| { |
| |
| } |
| @ocifreestatement($result); |
| |
| $splittime = explode(' ', microtime()); |
| $splittime = $splittime[0] + $splittime[1]; |
| |
| $this->sql_report('record_fromcache', $query, $endtime, $splittime); |
| |
| break; |
| } |
| } |
| } |
| |
| ?> |