mirror of
https://github.com/phpbb/phpbb.git
synced 2025-06-28 22:28:51 +00:00
- 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
This commit is contained in:
parent
27c082d99c
commit
367f5103d9
5 changed files with 69 additions and 36 deletions
|
@ -278,6 +278,8 @@ p a {
|
||||||
<li>[Fix] Show "no image" image when a non-selectable item was selected in the acp imageset editor - IE (Bug #12423)</li>
|
<li>[Fix] Show "no image" image when a non-selectable item was selected in the acp imageset editor - IE (Bug #12423)</li>
|
||||||
<li>[Fix] Update session information without new pageload (Bug #12393, Bug #12441)</li>
|
<li>[Fix] Update session information without new pageload (Bug #12393, Bug #12441)</li>
|
||||||
<li>[Fix] Let polls be edited correctly (Bug #12433)</li>
|
<li>[Fix] Let polls be edited correctly (Bug #12433)</li>
|
||||||
|
<li>[Fix] Overcome Oracle's inability to handle IN() clauses with over one thousand elements (Bug #12449)</li>
|
||||||
|
<li>[Fix] Simulate Firebird's affected rows mechanism for older versions of PHP</li>
|
||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
|
|
@ -27,6 +27,7 @@ class dbal_firebird extends dbal
|
||||||
{
|
{
|
||||||
var $last_query_text = '';
|
var $last_query_text = '';
|
||||||
var $service_handle = false;
|
var $service_handle = false;
|
||||||
|
var $affected_rows = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Connect to server
|
* Connect to server
|
||||||
|
@ -109,13 +110,11 @@ class dbal_firebird extends dbal
|
||||||
|
|
||||||
if ($this->query_result === false)
|
if ($this->query_result === false)
|
||||||
{
|
{
|
||||||
$prepared = false;
|
$array = array();
|
||||||
// We overcome Firebird's 32767 char limit by binding vars
|
// We overcome Firebird's 32767 char limit by binding vars
|
||||||
if (strlen($query) > 32767)
|
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)
|
if (strlen($regs[3]) > 32767)
|
||||||
{
|
{
|
||||||
|
@ -134,45 +133,55 @@ class dbal_firebird extends dbal
|
||||||
}
|
}
|
||||||
|
|
||||||
$query = $regs[1] . '(' . $regs[2] . ') VALUES (' . implode(', ', $inserts) . ')';
|
$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];
|
$update = $data[1];
|
||||||
$where = $data[0][4];
|
$where = $data[4];
|
||||||
preg_match_all('/(\\w++) = (\'(?:[^\']++|\'\')*+\'|\\d++)/', $data[0][3], $temp, PREG_SET_ORDER);
|
preg_match_all('/(\\w++)\\s*=\\s*(\'(?:[^\']++|\'\')*+\'|\\d++)/', $data[3], $temp, PREG_SET_ORDER);
|
||||||
unset($data);
|
unset($data);
|
||||||
|
|
||||||
$art = array();
|
$cols = array();
|
||||||
foreach ($temp as $value)
|
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
|
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));
|
$array[] = str_replace("''", "'", substr($value[2], 1, -1));
|
||||||
$art[] = $value[1] . '=?';
|
$cols[] = $value[1] . '=?';
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
$art[] = $value[1] . '=' . $value[2];
|
$cols[] = $value[1] . '=' . $value[2];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$query = $update . implode(', ', $art) . ' ' . $where;
|
$query = $update . implode(', ', $cols) . ' ' . $where;
|
||||||
unset($art);
|
unset($cols);
|
||||||
|
|
||||||
$prepared = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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)))
|
||||||
{
|
{
|
||||||
$p_query = ibase_prepare($this->db_connect_id, $query);
|
$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);
|
||||||
array_unshift($array, $p_query);
|
array_unshift($array, $p_query);
|
||||||
$this->query_result = call_user_func_array('ibase_execute', $array);
|
$this->query_result = call_user_func_array('ibase_execute', $array);
|
||||||
unset($array);
|
unset($array);
|
||||||
|
@ -252,7 +261,7 @@ class dbal_firebird extends dbal
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return ($this->query_result) ? true : false;
|
return $this->affected_rows;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -144,24 +144,47 @@ class dbal_oracle extends dbal
|
||||||
$sub_exp = substr($val[5], strpos($val[5], '(') + 1, -1);
|
$sub_exp = substr($val[5], strpos($val[5], '(') + 1, -1);
|
||||||
$extra = false;
|
$extra = false;
|
||||||
preg_match_all('/\'(?>[^\']++|\'\')*+\'|\d++/', $sub_exp, $sub_vals, PREG_PATTERN_ORDER);
|
preg_match_all('/\'(?>[^\']++|\'\')*+\'|\d++/', $sub_exp, $sub_vals, PREG_PATTERN_ORDER);
|
||||||
|
$i = 0;
|
||||||
foreach ($sub_vals[0] as $sub_val)
|
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 !== "''")
|
if ($sub_val !== "''")
|
||||||
{
|
{
|
||||||
$in_clause[] = $sub_val;
|
$in_clause[(int) $i++/1000][] = $sub_val;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
$extra = true;
|
$extra = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!$extra)
|
if (!$extra && $i < 1000)
|
||||||
{
|
{
|
||||||
$out .= $val[0];
|
$out .= $val[0];
|
||||||
}
|
}
|
||||||
else
|
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
|
// We overcome Oracle's 4000 char limit by binding vars
|
||||||
if (strlen($query) > 4000)
|
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)
|
if (strlen($regs[3]) > 4000)
|
||||||
{
|
{
|
||||||
|
@ -231,34 +254,33 @@ class dbal_oracle extends dbal
|
||||||
}
|
}
|
||||||
|
|
||||||
$query = $regs[1] . '(' . $regs[2] . ') VALUES (' . implode(', ', $inserts) . ')';
|
$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)
|
if (strlen($data[0][2]) > 4000)
|
||||||
{
|
{
|
||||||
$update = $data[0][1];
|
$update = $data[0][1];
|
||||||
$where = $data[0][3];
|
$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);
|
unset($data);
|
||||||
|
|
||||||
$art = array();
|
$cols = array();
|
||||||
foreach ($temp as $value)
|
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
|
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));
|
$array[$value[1]] = str_replace("''", "'", substr($value[2], 1, -1));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
$art[] = $value[1] . '=' . $value[2];
|
$cols[] = $value[1] . '=' . $value[2];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$query = $update . implode(', ', $art) . ' ' . $where;
|
$query = $update . implode(', ', $cols) . ' ' . $where;
|
||||||
unset($art);
|
unset($cols);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1475,7 +1475,7 @@ function mass_auth($ug_type, $forum_id, $ug_id, $acl_list, $setting = ACL_NO)
|
||||||
{
|
{
|
||||||
$sql = 'SELECT role_id
|
$sql = 'SELECT role_id
|
||||||
FROM ' . ACL_ROLES_TABLE . "
|
FROM ' . ACL_ROLES_TABLE . "
|
||||||
WHERE role_description = 'ROLE_DESCRIPTION_" . $db->sql_escape($acl_list) . "'";
|
WHERE role_name = 'ROLE_" . $db->sql_escape($acl_list) . "'";
|
||||||
$result = $db->sql_query_limit($sql, 1);
|
$result = $db->sql_query_limit($sql, 1);
|
||||||
$row = $db->sql_fetchrow($result);
|
$row = $db->sql_fetchrow($result);
|
||||||
$db->sql_freeresult($result);
|
$db->sql_freeresult($result);
|
||||||
|
|
|
@ -1711,7 +1711,7 @@ function phpbb_check_username_collisions()
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'oracle':
|
case 'oracle':
|
||||||
$create_sql = 'CREATE TABLE ' . $table_prefix . 'userconv
|
$create_sql = 'CREATE TABLE ' . $table_prefix . 'userconv (
|
||||||
user_id number(8) NOT NULL,
|
user_id number(8) NOT NULL,
|
||||||
username_clean varchar2(255) DEFAULT \'\'
|
username_clean varchar2(255) DEFAULT \'\'
|
||||||
)';
|
)';
|
||||||
|
|
Loading…
Add table
Reference in a new issue