diff options
author | David M <davidmj@users.sourceforge.net> | 2007-06-16 13:49:49 +0000 |
---|---|---|
committer | David M <davidmj@users.sourceforge.net> | 2007-06-16 13:49:49 +0000 |
commit | 367f5103d96b192dfca453e6c1a9e4f1a96b8122 (patch) | |
tree | f81e47becef01427a64516651c3d26a89e0ad314 /phpBB/includes/db | |
parent | 27c082d99ccf135f807de624a3e215e9d5c04b34 (diff) | |
download | forums-367f5103d96b192dfca453e6c1a9e4f1a96b8122.tar forums-367f5103d96b192dfca453e6c1a9e4f1a96b8122.tar.gz forums-367f5103d96b192dfca453e6c1a9e4f1a96b8122.tar.bz2 forums-367f5103d96b192dfca453e6c1a9e4f1a96b8122.tar.xz forums-367f5103d96b192dfca453e6c1a9e4f1a96b8122.zip |
- Oracle can't handle IN clauses with more than 1000 elements (Bug #12449)
- Firebird can now work properly in PHP4
git-svn-id: file:///svn/phpbb/trunk@7767 89ea8834-ac86-4346-8a33-228a782c2dd0
Diffstat (limited to 'phpBB/includes/db')
-rw-r--r-- | phpBB/includes/db/firebird.php | 53 | ||||
-rw-r--r-- | phpBB/includes/db/oracle.php | 46 |
2 files changed, 65 insertions, 34 deletions
diff --git a/phpBB/includes/db/firebird.php b/phpBB/includes/db/firebird.php index ad3c58671a..6139d8608b 100644 --- a/phpBB/includes/db/firebird.php +++ b/phpBB/includes/db/firebird.php @@ -27,6 +27,7 @@ class dbal_firebird extends dbal { var $last_query_text = ''; var $service_handle = false; + var $affected_rows = 0; /** * Connect to server @@ -109,13 +110,11 @@ class dbal_firebird extends dbal if ($this->query_result === false) { - $prepared = false; + $array = array(); // We overcome Firebird's 32767 char limit by binding vars if (strlen($query) > 32767) { - $array = array(); - - if (preg_match('/^(INSERT INTO[^(]+)\\(([^()]+)\\) VALUES[^(]+\\((.*?)\\)$/s', $query, $regs)) + if (preg_match('/^(INSERT INTO[^(]++)\\(([^()]+)\\) VALUES[^(]++\\((.*?)\\)$/s', $query, $regs)) { if (strlen($regs[3]) > 32767) { @@ -134,45 +133,55 @@ class dbal_firebird extends dbal } $query = $regs[1] . '(' . $regs[2] . ') VALUES (' . implode(', ', $inserts) . ')'; - unset($art); - - $prepared = true; } } - else if (preg_match_all('/^(UPDATE ([\\w_]++)\\s+SET )(\\w+ = (?:\'(?:[^\']++|\'\')*+\'|\\d+)(?:, \\w+ = (?:\'(?:[^\']++|\'\')*+\'|\\d+))*+)\\s+(WHERE.*)$/s', $query, $data, PREG_SET_ORDER)) + else if (preg_match('/^(UPDATE ([\\w_]++)\\s+SET )([\\w_]++\\s*=\\s*(?:\'(?:[^\']++|\'\')*+\'|\\d+)(?:,\\s*[\\w_]++\\s*=\\s*(?:\'(?:[^\']++|\'\')*+\'|\\d+))*+)\\s+(WHERE.*)$/s', $query, $data)) { - if (strlen($data[0][3]) > 32767) + if (strlen($data[3]) > 32767) { - $update = $data[0][1]; - $where = $data[0][4]; - preg_match_all('/(\\w++) = (\'(?:[^\']++|\'\')*+\'|\\d++)/', $data[0][3], $temp, PREG_SET_ORDER); + $update = $data[1]; + $where = $data[4]; + preg_match_all('/(\\w++)\\s*=\\s*(\'(?:[^\']++|\'\')*+\'|\\d++)/', $data[3], $temp, PREG_SET_ORDER); unset($data); - $art = array(); + $cols = array(); foreach ($temp as $value) { if (!empty($value[2]) && $value[2][0] === "'" && strlen($value[2]) > 32769) // check to see if this thing is greater than the max + 'x2 { $array[] = str_replace("''", "'", substr($value[2], 1, -1)); - $art[] = $value[1] . '=?'; + $cols[] = $value[1] . '=?'; } else { - $art[] = $value[1] . '=' . $value[2]; + $cols[] = $value[1] . '=' . $value[2]; } } - $query = $update . implode(', ', $art) . ' ' . $where; - unset($art); - - $prepared = true; + $query = $update . implode(', ', $cols) . ' ' . $where; + unset($cols); } } } - if ($prepared) + if (!function_exists('ibase_affected_rows') && (preg_match('/^UPDATE ([\w_]++)\s+SET [\w_]++\s*=\s*(?:\'(?:[^\']++|\'\')*+\'|\d+)(?:,\s*[\w_]++\s*=\s*(?:\'(?:[^\']++|\'\')*+\'|\d+))*+\s+(WHERE.*)$/s', $query, $regs) || preg_match('/^DELETE FROM ([\w_]++)\s*WHERE\s*(.*)$/s', $query, $regs))) + { + $affected_sql = 'SELECT COUNT(*) as num_rows_affected FROM ' . $regs[1] . ' ' . $regs[2]; + + if (!($temp_q_id = @ibase_query($this->db_connect_id, $affected_sql))) + { + return false; + } + + $temp_result = @ibase_fetch_assoc($temp_q_id); + @ibase_free_result($temp_q_id); + + $this->affected_rows = ($temp_result) ? $temp_result['NUM_ROWS_AFFECTED'] : false; + } + + if (sizeof($array)) { - $p_query = ibase_prepare($this->db_connect_id, $query); + $p_query = @ibase_prepare($this->db_connect_id, $query); array_unshift($array, $p_query); $this->query_result = call_user_func_array('ibase_execute', $array); unset($array); @@ -252,7 +261,7 @@ class dbal_firebird extends dbal } else { - return ($this->query_result) ? true : false; + return $this->affected_rows; } } diff --git a/phpBB/includes/db/oracle.php b/phpBB/includes/db/oracle.php index 0059acb1dc..709cb653e9 100644 --- a/phpBB/includes/db/oracle.php +++ b/phpBB/includes/db/oracle.php @@ -144,24 +144,47 @@ class dbal_oracle extends dbal $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) { + // two things: + // 1) This determines if an empty string was in the IN clausing, making us turn it into a NULL comparison + // 2) This fixes the 1000 list limit that Oracle has (ORA-01795) if ($sub_val !== "''") { - $in_clause[] = $sub_val; + $in_clause[(int) $i++/1000][] = $sub_val; } else { $extra = true; } } - if (!$extra) + if (!$extra && $i < 1000) { $out .= $val[0]; } else { - $out .= ' ' . $val[1] . ' (' . $val[2]. ' ' . (isset($val[6]) ? $val[6] : '') . 'IN(' . implode(', ', $in_clause) . ') OR ' . $val[2] . ' is ' . (isset($val[6]) ? $val[6] : '') . 'NULL)'; + $out .= ' ' . $val[1] . '('; + $in_array = array(); + + // constuct each IN() clause + foreach ($in_clause as $in_values) + { + $in_array[] = $val[2] . ' ' . (isset($val[6]) ? $val[6] : '') . 'IN(' . implode(', ', $in_values) . ')'; + } + + // Join the IN() clauses against a few ORs (IN is just a nicer OR anyway) + $out .= implode(' OR ', $in_array); + + // handle the empty string case + if ($extra) + { + $out .= ' OR ' . $val[2] . ' is ' . (isset($val[6]) ? $val[6] : '') . 'NULL'; + } + $out .= ')'; + + unset($in_array, $in_clause); } } } @@ -211,7 +234,7 @@ class dbal_oracle extends dbal // We overcome Oracle's 4000 char limit by binding vars if (strlen($query) > 4000) { - if (preg_match('/^(INSERT INTO[^(]+)\\(([^()]+)\\) VALUES[^(]+\\((.*?)\\)$/s', $query, $regs)) + if (preg_match('/^(INSERT INTO[^(]++)\\(([^()]+)\\) VALUES[^(]++\\((.*?)\\)$/s', $query, $regs)) { if (strlen($regs[3]) > 4000) { @@ -231,34 +254,33 @@ class dbal_oracle extends dbal } $query = $regs[1] . '(' . $regs[2] . ') VALUES (' . implode(', ', $inserts) . ')'; - unset($art); } } - else if (preg_match_all('/^(UPDATE [\\w_]++\\s+SET )([\\w_]+ = (?:\'(?:[^\']++|\'\')*+\'|\\d+)(?:, [\\w_]+ = (?:\'(?:[^\']++|\'\')*+\'|\\d+))*+)\\s+(WHERE.*)$/s', $query, $data, PREG_SET_ORDER)) + 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_]++) = (\'(?:[^\']++|\'\')*+\'|\\d++)/', $data[0][2], $temp, PREG_SET_ORDER); + preg_match_all('/([\\w_]++)\\s*=\\s*(\'(?:[^\']++|\'\')*+\'|\\d++)/', $data[0][2], $temp, PREG_SET_ORDER); unset($data); - $art = array(); + $cols = array(); foreach ($temp as $value) { if (!empty($value[2]) && $value[2][0] === "'" && strlen($value[2]) > 4002) // check to see if this thing is greater than the max + 'x2 { - $art[] = $value[1] . '=:' . strtoupper($value[1]); + $cols[] = $value[1] . '=:' . strtoupper($value[1]); $array[$value[1]] = str_replace("''", "'", substr($value[2], 1, -1)); } else { - $art[] = $value[1] . '=' . $value[2]; + $cols[] = $value[1] . '=' . $value[2]; } } - $query = $update . implode(', ', $art) . ' ' . $where; - unset($art); + $query = $update . implode(', ', $cols) . ' ' . $where; + unset($cols); } } } |