aboutsummaryrefslogtreecommitdiffstats
path: root/phpBB/includes
diff options
context:
space:
mode:
Diffstat (limited to 'phpBB/includes')
-rw-r--r--phpBB/includes/acp/acp_database.php174
-rw-r--r--phpBB/includes/acp/acp_profile.php36
-rw-r--r--phpBB/includes/acp/acp_users.php3
-rw-r--r--phpBB/includes/db/db2.php496
-rw-r--r--phpBB/includes/db/db_tools.php95
-rw-r--r--phpBB/includes/functions_install.php22
-rw-r--r--phpBB/includes/functions_user.php4
-rw-r--r--phpBB/includes/ucp/ucp_profile.php2
8 files changed, 824 insertions, 8 deletions
diff --git a/phpBB/includes/acp/acp_database.php b/phpBB/includes/acp/acp_database.php
index d7ce8db8b3..64806eda59 100644
--- a/phpBB/includes/acp/acp_database.php
+++ b/phpBB/includes/acp/acp_database.php
@@ -113,6 +113,10 @@ class acp_database
case 'firebird':
$extractor = new firebird_extractor($download, $store, $format, $filename, $time);
break;
+
+ case 'db2':
+ $extractor = new db2_extractor($download, $store, $format, $filename, $time);
+ break;
}
$extractor->write_start($table_prefix);
@@ -131,6 +135,7 @@ class acp_database
{
case 'sqlite':
case 'firebird':
+ case 'db2':
$extractor->flush('DELETE FROM ' . $table_name . ";\n");
break;
@@ -1552,6 +1557,175 @@ class mssql_extractor extends base_extractor
/**
* @package acp
*/
+class db2_extractor extends base_extractor
+{
+ function write_start($prefix)
+ {
+ $sql_data = "--\n";
+ $sql_data .= "-- phpBB Backup Script\n";
+ $sql_data .= "-- Dump of tables for $prefix\n";
+ $sql_data .= "-- DATE : " . gmdate("d-m-Y H:i:s", $this->time) . " GMT\n";
+ $sql_data .= "--\n";
+ $this->flush($sql_data);
+ }
+
+ function write_table($table_name)
+ {
+ global $db;
+ $sql_data = '-- Table: ' . $table_name . "\n";
+ $sql_data .= "\nCREATE TABLE $table_name (\n";
+ $rows = array();
+
+ // switch to db2_columns()?
+ $sql = "SELECT colname, typename, length, default, identity, nulls
+ FROM syscat.columns
+ WHERE tabname = '$table_name'";
+ $result = $db->sql_query($sql);
+
+ while ($row = $db->sql_fetchrow($result))
+ {
+ $line = "\t{$row['colname']} {$row['typename']}";
+
+ if ($row['identity'] == 'Y')
+ {
+ $line .= ' GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1)';
+ }
+
+ if ($row['typename'] == 'VARCHAR' || $row['typename'] == 'CHARACTER' || $row['typename'] == 'CLOB')
+ {
+ $line .= ' (' . $row['length'] . ')';
+ }
+
+ if ($row['nulls'] == 'N')
+ {
+ $line .= ' NOT NULL';
+ }
+ else
+ {
+ $line .= ' NULL';
+ }
+
+ if ($row['default'] !== null)
+ {
+ $line .= ' DEFAULT ' . $row['default'];
+ }
+
+ $rows[] = $line;
+ }
+ $db->sql_freeresult($result);
+
+ // switch to db2_columns()?
+ $sql = "SELECT colname
+ FROM SYSCAT.KEYCOLUSE
+ WHERE tabname = '$table_name'";
+ $result = $db->sql_query($sql);
+ $prim_cols = array();
+ while ($row = $db->sql_fetchrow($result))
+ {
+ $prim_cols[] = $row['colname'];
+ }
+ $db->sql_freeresult($result);
+ if (sizeof($prim_cols))
+ {
+ $rows[] = "\tPRIMARY KEY (" . implode($prim_cols) . ')';
+ }
+
+ $sql_data .= implode(",\n", $rows);
+ $sql_data .= "\n);\n\n";
+ $rows = array();
+
+ $sql = "SELECT colnames, indname
+ FROM SYSCAT.INDEXES
+ WHERE TABNAME = '$table_name'
+ AND UNIQUERULE <> 'P'";
+ $result = $db->sql_query($sql);
+ $index = array();
+ while ($row = $db->sql_fetchrow($result))
+ {
+ $inds = explode('+', $row['colnames']);
+ unset($inds[0]);
+ $sql_data .= 'CREATE INDEX ' . $row['indname'] . ' ON ' . $table_name . ' (' . implode(', ', $inds) . ") PCTFREE 10 MINPCTUSED 10 ALLOW REVERSE SCANS PAGE SPLIT SYMMETRIC COLLECT SAMPLED DETAILED STATISTICS;\n";
+ }
+ $db->sql_freeresult($result);
+
+ $this->flush($sql_data);
+ }
+
+ function write_data($table_name)
+ {
+ global $db;
+ $ary_type = $ary_name = array();
+ $result = db2_columns($db->db_connect_id, '', '%', $table_name);
+ $i = 0;
+ while ($row = $db->sql_fetchrow($result))
+ {
+ $ary_type[$i] = $row['type_name'];
+ $ary_name[$i++] = strtolower($row['column_name']);
+ }
+ $db->sql_freeresult($result);
+
+ // Grab all of the data from current table.
+ $sql = "SELECT *
+ FROM $table_name";
+ $result = $db->sql_query($sql);
+
+ $sql_data = '';
+ $i_num_fields = $i;
+
+ while ($row = $db->sql_fetchrow($result))
+ {
+ $schema_vals = $schema_fields = array();
+
+ // Build the SQL statement to recreate the data.
+ for ($i = 0; $i < $i_num_fields; $i++)
+ {
+ $str_val = $row[$ary_name[$i]];
+
+ if (preg_match('#char|clob#i', $ary_type[$i]))
+ {
+ $str_quote = "'";
+ $str_empty = '';
+ $str_val = sanitize_data_generic(str_replace("'", "''", $str_val));
+ }
+ else if (preg_match('#date|timestamp#i', $ary_type[$i]))
+ {
+ if (empty($str_val))
+ {
+ $str_quote = '';
+ }
+ else
+ {
+ $str_quote = "'";
+ }
+ }
+ else
+ {
+ $str_quote = '';
+ $str_empty = 'NULL';
+ }
+
+ if (empty($str_val) && $str_val !== '0')
+ {
+ $str_val = $str_empty;
+ }
+
+ $schema_vals[$i] = $str_quote . $str_val . $str_quote;
+ $schema_fields[$i] = '"' . $ary_name[$i] . "'";
+ }
+
+ // Take the ordered fields and their associated data and build it
+ // into a valid sql statement to recreate that field in the data.
+ $sql_data = "INSERT INTO $table_name (" . implode(', ', $schema_fields) . ') VALUES (' . implode(', ', $schema_vals) . ");\n";
+
+ $this->flush($sql_data);
+ }
+ $db->sql_freeresult($result);
+ }
+}
+
+/**
+* @package acp
+*/
class oracle_extractor extends base_extractor
{
function write_table($table_name)
diff --git a/phpBB/includes/acp/acp_profile.php b/phpBB/includes/acp/acp_profile.php
index 2a9c0e8c19..bd7d58717b 100644
--- a/phpBB/includes/acp/acp_profile.php
+++ b/phpBB/includes/acp/acp_profile.php
@@ -1605,6 +1605,42 @@ class acp_profile
}
break;
+
+ case 'db2':
+
+ // We are defining the biggest common value, because of the possibility to edit the min/max values of each field.
+ $sql = 'ALTER TABLE ' . PROFILE_FIELDS_DATA_TABLE . " ADD \"$field_ident\" ";
+
+ switch ($field_type)
+ {
+ case FIELD_STRING:
+ $sql .= ' VARCHAR(255) ';
+ break;
+
+ case FIELD_DATE:
+ $sql .= 'VARCHAR(10) ';
+ break;
+
+ case FIELD_TEXT:
+ $sql .= "varchar(32672)";
+ // ADD {$field_ident}_bbcode_uid VARCHAR2(5) NOT NULL,
+ // ADD {$field_ident}_bbcode_bitfield NUMBER(11) UNSIGNED";
+ break;
+
+ case FIELD_BOOL:
+ $sql .= 'smallint ';
+ break;
+
+ case FIELD_DROPDOWN:
+ $sql .= 'integer ';
+ break;
+
+ case FIELD_INT:
+ $sql .= 'float ';
+ break;
+ }
+
+ break;
}
return $sql;
diff --git a/phpBB/includes/acp/acp_users.php b/phpBB/includes/acp/acp_users.php
index f87e175301..13612cf363 100644
--- a/phpBB/includes/acp/acp_users.php
+++ b/phpBB/includes/acp/acp_users.php
@@ -775,7 +775,7 @@ class acp_users
{
$sql_ary += array(
'user_email' => $update_email,
- 'user_email_hash' => crc32($update_email) . strlen($update_email)
+ 'user_email_hash' => hexdec(crc32($update_email) . strlen($update_email))
);
add_log('user', $user_id, 'LOG_USER_UPDATE_EMAIL', $user_row['username'], $user_row['user_email'], $update_email);
@@ -1130,6 +1130,7 @@ class acp_users
case 'oracle':
case 'firebird':
case 'postgres':
+ case 'db2':
$right_delim = $left_delim = '"';
break;
diff --git a/phpBB/includes/db/db2.php b/phpBB/includes/db/db2.php
new file mode 100644
index 0000000000..d1917e6c3a
--- /dev/null
+++ b/phpBB/includes/db/db2.php
@@ -0,0 +1,496 @@
+<?php
+/**
+*
+* @package dbal
+* @version $Id$
+* @copyright (c) 2005 phpBB Group
+* @license http://opensource.org/licenses/gpl-license.php GNU Public License
+*
+*/
+
+/**
+* @ignore
+*/
+if (!defined('IN_PHPBB'))
+{
+ exit;
+}
+
+include_once($phpbb_root_path . 'includes/db/dbal.' . $phpEx);
+
+/**
+* MSSQL Database Abstraction Layer
+* Minimum Requirement is DB2 8.2.2
+* @package dbal
+*/
+class dbal_db2 extends dbal
+{
+ var $multi_insert = true;
+ var $last_query_text = '';
+
+ // can't truncate a table
+ var $truncate = false;
+
+ /**
+ * Connect to server
+ */
+ 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;
+
+ $this->db_connect_id = ($this->persistency) ? @db2_pconnect($this->dbname, $this->user, $sqlpassword, array('autocommit' => DB2_AUTOCOMMIT_ON, 'DB2_ATTR_CASE' => DB2_CASE_LOWER)) : @db2_connect($this->dbname, $this->user, $sqlpassword, array('autocommit' => DB2_AUTOCOMMIT_ON, 'DB2_ATTR_CASE' => DB2_CASE_LOWER));
+
+ return ($this->db_connect_id) ? $this->db_connect_id : $this->sql_error('');
+ }
+
+ /**
+ * Version information about used database
+ */
+ function sql_server_info()
+ {
+ $info = db2_server_info($this->db_connect_id);
+ return $info->DBMS_VER;
+ }
+
+ /**
+ * SQL Transaction
+ * @access private
+ */
+ function _sql_transaction($status = 'begin')
+ {
+ switch ($status)
+ {
+ case 'begin':
+ return @db2_autocommit($this->db_connect_id, DB2_AUTOCOMMIT_OFF);
+ break;
+
+ case 'commit':
+ $result = @db2_commit($this->db_connect_id);
+ @db2_autocommit($this->db_connect_id, DB2_AUTOCOMMIT_ON);
+ return $result;
+ break;
+
+ case 'rollback':
+ $result = @db2_rollback($this->db_connect_id);
+ @db2_autocommit($this->db_connect_id, DB2_AUTOCOMMIT_ON);
+ return $result;
+ break;
+ }
+
+ return true;
+ }
+
+ /**
+ * Base query method
+ *
+ * @param string $query Contains the SQL query which shall be executed
+ * @param int $cache_ttl Either 0 to avoid caching or the time in seconds which the result shall be kept in cache
+ * @return mixed When casted to bool the returned value returns true on success and false on failure
+ *
+ * @access public
+ */
+ function sql_query($query = '', $cache_ttl = 0)
+ {
+ if ($query != '')
+ {
+ global $cache;
+
+ // EXPLAIN only in extra debug mode
+ 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)
+ {
+ $array = array();
+ if (strlen($query) > 32740)
+ {
+ if (preg_match('/^(INSERT INTO[^(]++)\\(([^()]+)\\) VALUES[^(]++\\((.*?)\\)$/s', $query, $regs))
+ {
+ if (strlen($regs[3]) > 32740)
+ {
+ 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) > 32742) // check to see if this thing is greater than the max + 'x2
+ {
+ $inserts[$key] = '?';
+ $array[] = 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][3]) > 32740)
+ {
+ $update = $data[0][1];
+ $where = $data[0][4];
+ preg_match_all('/(\\w++) = (\'(?:[^\']++|\'\')*+\'|\\d++)/', $data[0][3], $temp, PREG_SET_ORDER);
+ unset($data);
+
+ $cols = array();
+ foreach ($temp as $value)
+ {
+ if (!empty($value[2]) && $value[2][0] === "'" && strlen($value[2]) > 32742) // check to see if this thing is greater than the max + 'x2
+ {
+ $array[] = str_replace("''", "'", substr($value[2], 1, -1));
+ $cols[] = $value[1] . '=?';
+ }
+ else
+ {
+ $cols[] = $value[1] . '=' . $value[2];
+ }
+ }
+
+ $query = $update . implode(', ', $cols) . ' ' . $where;
+ unset($cols);
+ }
+ }
+ }
+
+ if (sizeof($array))
+ {
+ if (($this->query_result = @db2_prepare($this->db_connect_id, $query)) === false)
+ {
+ $this->sql_error($query);
+ }
+
+ if (!@db2_execute($this->query_result, $array))
+ {
+ $this->sql_error($query);
+ }
+ }
+ else
+ {
+ if (($this->query_result = @db2_exec($this->db_connect_id, $query)) === false)
+ {
+ $this->sql_error($query);
+ }
+ }
+
+ 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) ? $this->query_result : false;
+ }
+
+ /**
+ * Build LIMIT query
+ */
+ function sql_query_limit($query, $total, $offset = 0, $cache_ttl = 0)
+ {
+ if ($query != '')
+ {
+ $this->query_result = false;
+
+ if ($total && $offset == 0)
+ {
+ return $this->sql_query($query . ' fetch first ' . $total . ' rows only', $cache_ttl);
+ }
+
+
+ // Seek by $offset rows
+ if ($offset)
+ {
+ $limit_sql = 'SELECT a2.*
+ FROM (
+ SELECT ROW_NUMBER() OVER() AS rownum, a1.*
+ FROM (
+ ' . $query . '
+ ) a1
+ ) a2
+ WHERE a2.rownum BETWEEN ' . ($offset + 1) . ' AND ' . ($offset + $total);
+ return $this->sql_query($limit_sql, $cache_ttl);
+ }
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ /**
+ * Return number of affected rows
+ */
+ function sql_affectedrows()
+ {
+ return ($this->db_connect_id) ? @db2_num_rows($this->db_connect_id) : false;
+ }
+
+ /**
+ * Fetch current row
+ */
+ 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)
+ {
+ return false;
+ }
+
+ $row = @db2_fetch_assoc($query_id);
+
+ return $row;
+ }
+
+ /**
+ * Seek to given row number
+ * rownum is zero-based
+ */
+ function sql_rowseek($rownum, $query_id = false)
+ {
+ 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;
+ }
+
+ $this->sql_freeresult($query_id);
+ $query_id = $this->sql_query($this->last_query_text);
+
+ if ($query_id === false)
+ {
+ return false;
+ }
+
+ // We do not fetch the row for rownum == 0 because then the next resultset would be the second row
+ for ($i = 0; $i < $rownum; $i++)
+ {
+ if (!$this->sql_fetchrow($query_id))
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Get last inserted id after insert statement
+ */
+ function sql_nextid()
+ {
+ $result_id = @db2_exec($this->db_connect_id, 'VALUES IDENTITY_VAL_LOCAL()');
+ if ($result_id)
+ {
+ if ($row = @db2_fetch_assoc($result_id))
+ {
+ @db2_free_result($result_id);
+ return (int) $row[1];
+ }
+ @db2_free_result($result_id);
+ }
+
+ return false;
+ }
+
+ /**
+ * Free sql result
+ */
+ 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[$query_id]))
+ {
+ unset($this->open_queries[$query_id]);
+ return @db2_free_result($query_id);
+ }
+
+ return false;
+ }
+
+ /**
+ * Escape string used in sql query
+ */
+ function sql_escape($msg)
+ {
+ return str_replace("'", "''", $msg);
+ }
+
+ /**
+ * Expose a DBMS specific function
+ */
+ function sql_function($type, $col)
+ {
+ switch ($type)
+ {
+ case 'length_varchar':
+ return 'LENGTH(' . $col . ')';
+ break;
+
+ case 'length_text':
+ return 'LENGTH(' . $col . ')';
+ break;
+ }
+ }
+
+ /**
+ * Build LIKE expression
+ * @access private
+ */
+ function _sql_like_expression($expression)
+ {
+ return $expression . " ESCAPE '\\'";
+ }
+
+ /**
+ * return sql error array
+ * @access private
+ */
+ function _sql_error()
+ {
+ $error = array(
+ 'message' => @db2_stmt_errormsg(),
+ 'code' => @db2_stmt_error()
+ );
+ return $error;
+ }
+
+ /**
+ * Build db-specific query data
+ * @access private
+ */
+ function _sql_custom_build($stage, $data)
+ {
+ return $data;
+ }
+
+ /**
+ * Close sql connection
+ * @access private
+ */
+ function _sql_close()
+ {
+ return @db2_close($this->db_connect_id);
+ }
+
+ /**
+ * Build db-specific report
+ * @access private
+ */
+ function _sql_report($mode, $query = '')
+ {
+ switch ($mode)
+ {
+ case 'start':
+
+ $html_table = false;
+ @db2_exec($this->db_connect_id, 'DELETE FROM EXPLAIN_INSTANCE');
+ @db2_exec($this->db_connect_id, 'EXPLAIN PLAN FOR ' . $query);
+
+ // Get the data from the plan
+ $sql = "SELECT O.Operator_ID, S2.Target_ID, O.Operator_Type, S.Object_Name, CAST(O.Total_Cost AS INTEGER) Cost
+ FROM EXPLAIN_OPERATOR O
+ LEFT OUTER JOIN EXPLAIN_STREAM S2 ON O.Operator_ID = S2.Source_ID
+ LEFT OUTER JOIN EXPLAIN_STREAM S ON O.Operator_ID = S.Target_ID AND O.Explain_Time = S.Explain_Time AND S.Object_Name IS NOT NULL
+ ORDER BY O.Explain_Time ASC, Operator_ID ASC";
+ $query_id = @db2_exec($this->db_connect_id, $sql);
+
+ if ($query_id)
+ {
+ while ($row = @db2_fetch_assoc($query_id))
+ {
+ $html_table = $this->sql_report('add_select_row', $query, $html_table, $row);
+ }
+
+ @db2_free_result($query_id);
+ }
+
+ if ($html_table)
+ {
+ $this->html_hold .= '</table>';
+ }
+ break;
+
+ case 'fromcache':
+ $endtime = explode(' ', microtime());
+ $endtime = $endtime[0] + $endtime[1];
+
+ $result = @db2_exec($this->db_connect_id, $query);
+ while ($void = @db2_fetch_assoc($result, IBASE_TEXT))
+ {
+ // Take the time spent on parsing rows into account
+ }
+ @db2_free_result($result);
+
+ $splittime = explode(' ', microtime());
+ $splittime = $splittime[0] + $splittime[1];
+
+ $this->sql_report('record_fromcache', $query, $endtime, $splittime);
+
+ break;
+ }
+ }
+}
+
+?> \ No newline at end of file
diff --git a/phpBB/includes/db/db_tools.php b/phpBB/includes/db/db_tools.php
index 0919854f40..f02ec96a9f 100644
--- a/phpBB/includes/db/db_tools.php
+++ b/phpBB/includes/db/db_tools.php
@@ -181,6 +181,33 @@ class phpbb_db_tools
'VARBINARY' => 'blob',
),
+ 'db2' => array(
+ 'INT:' => 'integer',
+ 'BINT' => 'float',
+ 'UINT' => 'integer',
+ 'UINT:' => 'integer',
+ 'TINT:' => 'smallint',
+ 'USINT' => 'smallint',
+ 'BOOL' => 'smallint',
+ 'VCHAR' => 'varchar(255)',
+ 'VCHAR:' => 'varchar(%d)',
+ 'CHAR:' => 'char(%d)',
+ 'XSTEXT' => 'clob(65K)',
+ 'STEXT' => 'varchar(3000)',
+ 'TEXT' => 'clob(65K)',
+ 'MTEXT' => 'clob(16M)',
+ 'XSTEXT_UNI'=> 'varchar(100)',
+ 'STEXT_UNI' => 'varchar(255)',
+ 'TEXT_UNI' => 'clob(65K)',
+ 'MTEXT_UNI' => 'clob(16M)',
+ 'TIMESTAMP' => 'integer',
+ 'DECIMAL' => 'float',
+ 'VCHAR_UNI' => 'varchar(255)',
+ 'VCHAR_UNI:'=> 'varchar(%d)',
+ 'VCHAR_CI' => 'varchar(255)',
+ 'VARBINARY' => 'varchar(255)',
+ ),
+
'postgres' => array(
'INT:' => 'INT4',
'BINT' => 'INT8',
@@ -505,6 +532,24 @@ class phpbb_db_tools
return false;
break;
+ case 'db2':
+ $sql = "SELECT colname
+ FROM syscat.columns
+ WHERE tabname = '$table'";
+ $result = $this->db->sql_query($sql);
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ // lower case just in case
+ if (strtolower($row['colname']) == $column_name)
+ {
+ $this->db->sql_freeresult($result);
+ return true;
+ }
+ }
+ $this->db->sql_freeresult($result);
+ return false;
+ break;
+
// ugh, SQLite
case 'sqlite':
$sql = "SELECT sql
@@ -762,6 +807,27 @@ class phpbb_db_tools
$sql .= ' NOT NULL ';
$sql .= (!is_null($column_data[1])) ? "DEFAULT '{$column_data[1]}'" : '';
break;
+
+ case 'db2':
+ $sql .= "\t{$column_name} {$column_type} NOT NULL";
+
+ if (isset($column_data[2]) && $column_data[2] == 'auto_increment')
+ {
+ $sql .= ' GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1)';
+ }
+ else
+ {
+ if (preg_match('/^(integer|smallint|float)$/', $column_type))
+ {
+ $sql .= " DEFAULT {$column_data[1]}";
+ }
+ else
+ {
+ $sql .= " DEFAULT '{$column_data[1]}'";
+ }
+ }
+ $sql .= ",\n";
+ break;
}
$return_array['column_type_sql'] = $sql;
@@ -799,6 +865,10 @@ class phpbb_db_tools
$statements[] = 'ALTER TABLE ' . $table_name . ' ADD COLUMN "' . $column_name . '" ' . $column_data['column_type_sql'];
break;
+ case 'db2':
+ $statements[] = 'ALTER TABLE ' . $table_name . ' ADD ' . $column_name . ' ' . $column_data['column_type_sql'];
+ break;
+
case 'sqlite':
if (version_compare(sqlite_libversion(), '3.0') == -1)
{
@@ -890,6 +960,10 @@ class phpbb_db_tools
$statements[] = 'ALTER TABLE ' . $table_name . ' DROP COLUMN "' . $column_name . '"';
break;
+ case 'db2':
+ $statements[] = 'ALTER TABLE ' . $table_name . ' DROP ' . $column_name;
+ break;
+
case 'sqlite':
if (version_compare(sqlite_libversion(), '3.0') == -1)
{
@@ -973,6 +1047,7 @@ class phpbb_db_tools
case 'oracle':
case 'postgres':
case 'sqlite':
+ case 'db2':
$statements[] = 'DROP INDEX ' . $table_name . '_' . $index_name;
break;
}
@@ -991,6 +1066,8 @@ class phpbb_db_tools
{
case 'firebird':
case 'postgres':
+ case 'mysql':
+ case 'db2':
$statements[] = 'ALTER TABLE ' . $table_name . ' ADD PRIMARY KEY (' . implode(', ', $column) . ')';
break;
@@ -1003,10 +1080,6 @@ class phpbb_db_tools
$statements[] = $sql;
break;
- case 'mysql':
- $statements[] = 'ALTER TABLE ' . $table_name . ' ADD PRIMARY KEY (' . implode(', ', $column) . ')';
- break;
-
case 'oracle':
$statements[] = 'ALTER TABLE ' . $table_name . 'add CONSTRAINT pk_' . $table_name . ' PRIMARY KEY (' . implode(', ', $column) . ')';
break;
@@ -1077,6 +1150,7 @@ class phpbb_db_tools
case 'postgres':
case 'oracle':
case 'sqlite':
+ case 'db2':
$statements[] = 'CREATE UNIQUE INDEX ' . $table_name . '_' . $index_name . ' ON ' . $table_name . '(' . implode(', ', $column) . ')';
break;
@@ -1105,6 +1179,7 @@ class phpbb_db_tools
case 'postgres':
case 'oracle':
case 'sqlite':
+ case 'db2':
$statements[] = 'CREATE INDEX ' . $table_name . '_' . $index_name . ' ON ' . $table_name . '(' . implode(', ', $column) . ')';
break;
@@ -1184,6 +1259,13 @@ class phpbb_db_tools
$sql = "PRAGMA index_info('" . $table_name . "');";
$col = 'name';
break;
+
+ case 'db2':
+ $sql = "SELECT indname
+ FROM SYSCAT.INDEXES
+ WHERE TABNAME = '$table_name'
+ AND UNIQUERULE <> 'P'";
+ $col = 'name';
}
$result = $this->db->sql_query($sql);
@@ -1200,6 +1282,7 @@ class phpbb_db_tools
case 'oracle':
case 'postgres':
case 'sqlite':
+ case 'db2':
$row[$col] = substr($row[$col], strlen($table_name) + 1);
break;
}
@@ -1239,6 +1322,10 @@ class phpbb_db_tools
$statements[] = 'ALTER TABLE ' . $table_name . ' MODIFY ' . $column_name . ' ' . $column_data['column_type_sql'];
break;
+ case 'db2':
+ $statements[] = 'ALTER TABLE ' . $table_name . ' ALTER ' . $column_name . ' SET DATA TYPE ' . $column_data['column_type_sql'];
+ break;
+
case 'postgres':
$sql = 'ALTER TABLE ' . $table_name . ' ';
diff --git a/phpBB/includes/functions_install.php b/phpBB/includes/functions_install.php
index 36b38a6036..97775eacf7 100644
--- a/phpBB/includes/functions_install.php
+++ b/phpBB/includes/functions_install.php
@@ -82,6 +82,16 @@ function get_available_dbms($dbms = false, $return_unavailable = false, $only_20
'AVAILABLE' => true,
'2.0.x' => true,
),
+ 'db2' => array(
+ 'LABEL' => 'IBM DB2',
+ 'SCHEMA' => 'db2',
+ 'MODULE' => 'ibm_db2',
+ 'DELIM' => ';',
+ 'COMMENTS' => 'remove_comments',
+ 'DRIVER' => 'db2',
+ 'AVAILABLE' => true,
+ '2.0.x' => false,
+ ),
'oracle' => array(
'LABEL' => 'Oracle',
'SCHEMA' => 'oracle',
@@ -223,6 +233,14 @@ function get_tables($db)
AND rdb$system_flag = 0';
break;
+ case 'db2':
+ $sql = "SELECT tabname
+ FROM SYSCAT.TABLES
+ WHERE type = 'T'
+ AND tabschema = 'DB2ADMIN'";
+ $field = 'tabname';
+ break;
+
case 'oracle':
$sql = 'SELECT table_name
FROM USER_TABLES';
@@ -302,6 +320,10 @@ function connect_check_db($error_connect, &$error, $dbms_details, $table_prefix,
$prefix_length = 90;
break;
+ case 'db2':
+ $prefix_length = 108;
+ break;
+
case 'sqlite':
$prefix_length = 200;
break;
diff --git a/phpBB/includes/functions_user.php b/phpBB/includes/functions_user.php
index 84e75670fb..bacb4462c6 100644
--- a/phpBB/includes/functions_user.php
+++ b/phpBB/includes/functions_user.php
@@ -167,7 +167,7 @@ function user_add($user_row, $cp_data = false)
'user_password' => (isset($user_row['user_password'])) ? $user_row['user_password'] : '',
'user_pass_convert' => 0,
'user_email' => strtolower($user_row['user_email']),
- 'user_email_hash' => crc32(strtolower($user_row['user_email'])) . strlen($user_row['user_email']),
+ 'user_email_hash' => hexdec(crc32(strtolower($user_row['user_email'])) . strlen($user_row['user_email'])),
'group_id' => $user_row['group_id'],
'user_type' => $user_row['user_type'],
);
@@ -1541,7 +1541,7 @@ function validate_email($email, $allowed_email = false)
{
$sql = 'SELECT user_email_hash
FROM ' . USERS_TABLE . "
- WHERE user_email_hash = " . (crc32($email) . strlen($email));
+ WHERE user_email_hash = " . hexdec(crc32($email) . strlen($email));
$result = $db->sql_query($sql);
$row = $db->sql_fetchrow($result);
$db->sql_freeresult($result);
diff --git a/phpBB/includes/ucp/ucp_profile.php b/phpBB/includes/ucp/ucp_profile.php
index 0f3cc218c3..a223d5232e 100644
--- a/phpBB/includes/ucp/ucp_profile.php
+++ b/phpBB/includes/ucp/ucp_profile.php
@@ -110,7 +110,7 @@ class ucp_profile
'username' => ($auth->acl_get('u_chgname') && $config['allow_namechange']) ? $data['username'] : $user->data['username'],
'username_clean' => ($auth->acl_get('u_chgname') && $config['allow_namechange']) ? utf8_clean_string($data['username']) : $user->data['username_clean'],
'user_email' => ($auth->acl_get('u_chgemail')) ? $data['email'] : $user->data['user_email'],
- 'user_email_hash' => ($auth->acl_get('u_chgemail')) ? crc32($data['email']) . strlen($data['email']) : $user->data['user_email_hash'],
+ 'user_email_hash' => ($auth->acl_get('u_chgemail')) ? hexdec(crc32($data['email']) . strlen($data['email'])) : $user->data['user_email_hash'],
'user_password' => ($auth->acl_get('u_chgpasswd') && $data['new_password']) ? phpbb_hash($data['new_password']) : $user->data['user_password'],
'user_passchg' => ($auth->acl_get('u_chgpasswd') && $data['new_password']) ? time() : 0,
);