aboutsummaryrefslogtreecommitdiffstats
path: root/phpBB/includes/db
diff options
context:
space:
mode:
authorDavid M <davidmj@users.sourceforge.net>2007-06-16 13:49:49 +0000
committerDavid M <davidmj@users.sourceforge.net>2007-06-16 13:49:49 +0000
commit367f5103d96b192dfca453e6c1a9e4f1a96b8122 (patch)
treef81e47becef01427a64516651c3d26a89e0ad314 /phpBB/includes/db
parent27c082d99ccf135f807de624a3e215e9d5c04b34 (diff)
downloadforums-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.php53
-rw-r--r--phpBB/includes/db/oracle.php46
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);
}
}
}