1046 lines
26 KiB
PHP
1046 lines
26 KiB
PHP
<?php
|
|
/***************************************************************************
|
|
* You can find the license in the docs directory
|
|
*
|
|
* Unicode Reminder メモ
|
|
*
|
|
* This module includes all database function necessary to do queries from
|
|
* the database.
|
|
***************************************************************************/
|
|
|
|
/***************************************************************************
|
|
Overview:
|
|
|
|
sql($sql) ... Query SQL and return result
|
|
sql_escape($value) ... Escape parameter for SQL-use
|
|
sql_escape_backtick($value) ... escape $value for use within backticks
|
|
sql_value($sql, $default) ... Query SQL and return first row of first line
|
|
sql_fetch_array($rs) ... mysql_fetch_array with charset conversion
|
|
sql_fetch_assoc($rs) ... mysql_fetch_assoc with charset conversion
|
|
sql_fetch_row($rs) ... mysql_fetch_row with charset conversion
|
|
sql_temp_table($table) ... registers an placeholder for use as temporary
|
|
table and drop's temporary tables if
|
|
mysql_pconnect is used
|
|
sql_drop_temp_table($table) ... unregisters and drops an tmp-table placeholder
|
|
sql_free_result($rs) ... mysql_free_result
|
|
sql_affected_rows() ... mysql_affected_rows
|
|
sql_insert_id() ... mysql_insert_id
|
|
sql_num_rows($rs) ... mysql_num_rows
|
|
sql_connect_root() ... connect the database with all privileges
|
|
sql_export_recordset($f, $rs) ... export recordset to file
|
|
sql_export_table($f, $table) ... export table to file
|
|
sql_export_table_to_file($filename, $table)
|
|
|
|
// slave query functions
|
|
sql_slave_exclude() ... do not use slave servers for the current user
|
|
until the slaves have replicated to this point
|
|
(e.g. after a new cache was hidden)
|
|
sql_slave($sql)
|
|
sql_value_slave($sql, $default)
|
|
sql_temp_table_slave($table)
|
|
sql_drop_temp_table_slave($table)
|
|
sql_affected_rows_slave()
|
|
sql_insert_id_slave()
|
|
sql_connect_anyslave()
|
|
sql_connect_slave($id)
|
|
sqlf_slave($sql)
|
|
|
|
// for sqldebugger
|
|
sqlf($sql) ... sql for framwork functions
|
|
sqll($sql) ... sql for business layer functions
|
|
sqlf_value($sql, $default) ... sql_value for framwork functions
|
|
sqll_value($sql, $default) ... sql_value for business layer functions
|
|
|
|
// only for internal use ... invoked automatically
|
|
sql_connect() ... connect to the database
|
|
sql_disconnect() ... disconnect database
|
|
sql_disconnect_slave() ... disconnect slave database
|
|
sql_error() ... report an error and stop processing
|
|
sql_warn($warnmessage) ... report a warning and resume processing
|
|
|
|
***************************************************************************/
|
|
|
|
$db['connected'] = false;
|
|
$db['debug'] = (($opt['debug'] & DEBUG_SQLDEBUGGER) == DEBUG_SQLDEBUGGER);
|
|
$db['dblink'] = false;
|
|
$db['dblink_slave'] = false;
|
|
$db['slave_id'] = -1;
|
|
$db['slave_server'] = '';
|
|
$db['temptable_initialized'] = false;
|
|
$db['temptables'] = array();
|
|
$db['temptables_slave'] = array();
|
|
$db['mode'] = DB_MODE_USER;
|
|
$db['error'] = false;
|
|
|
|
/*
|
|
sql("SELECT id FROM &tmpdb.table WHERE a=&1 AND &tmpdb.b='&2'", 12345, 'abc');
|
|
|
|
Important: only use ASCII charecters with ord() < 128 in your queries, otherwise
|
|
they will fail when $opt['charset']['mysql'] is not UTF-8.
|
|
However, parameters pased with &x or escaped with sql_escape will be
|
|
converted from UTF-8 to $opt['charset']['iconv'].
|
|
|
|
returns: recordset or false
|
|
*/
|
|
function sql($sql)
|
|
{
|
|
global $db;
|
|
|
|
// establish db connection
|
|
if ($db['connected'] != true)
|
|
sql_connect();
|
|
|
|
// prepare args
|
|
$args = func_get_args();
|
|
unset($args[0]);
|
|
|
|
if (isset($args[1]) && is_array($args[1]))
|
|
{
|
|
$tmp_args = $args[1];
|
|
unset($args);
|
|
|
|
// correct indizes
|
|
$args = array_merge(array(0), $tmp_args);
|
|
unset($tmp_args);
|
|
unset($args[0]);
|
|
}
|
|
|
|
return sql_internal($db['dblink'], $sql, $args);
|
|
}
|
|
|
|
function sql_slave($sql)
|
|
{
|
|
global $db;
|
|
|
|
if ($db['dblink_slave'] === false)
|
|
sql_connect_anyslave();
|
|
|
|
// prepare args
|
|
$args = func_get_args();
|
|
unset($args[0]);
|
|
|
|
if (isset($args[1]) && is_array($args[1]))
|
|
{
|
|
$tmp_args = $args[1];
|
|
unset($args);
|
|
|
|
// correct indizes
|
|
$args = array_merge(array(0), $tmp_args);
|
|
unset($tmp_args);
|
|
unset($args[0]);
|
|
}
|
|
|
|
return sql_internal($db['dblink_slave'], $sql, $args);
|
|
}
|
|
|
|
function sql_internal($dblink, $sql)
|
|
{
|
|
global $opt, $db, $sqldebugger;
|
|
|
|
$args = func_get_args();
|
|
unset($args[0]);
|
|
unset($args[1]);
|
|
|
|
/* as an option, you can give as second parameter an array
|
|
* with all values for the placeholder. The array has to be
|
|
* with numeric indizes.
|
|
*/
|
|
if (isset($args[2]) && is_array($args[2]))
|
|
{
|
|
$tmp_args = $args[2];
|
|
unset($args);
|
|
|
|
// correct indizes
|
|
$args = array_merge(array(0), $tmp_args);
|
|
unset($tmp_args);
|
|
unset($args[0]);
|
|
}
|
|
|
|
$sqlpos = 0;
|
|
$filtered_sql = '';
|
|
|
|
// replace every &x in $sql with the placeholder or parameter
|
|
$nextarg = strpos($sql, '&');
|
|
while ($nextarg !== false)
|
|
{
|
|
// & escaped?
|
|
$escapesCount = 0;
|
|
while ((($nextarg - $escapesCount - 1) > 0) && (substr($sql, $nextarg - $escapesCount - 1, 1) == '\\')) $escapesCount++;
|
|
if (($escapesCount % 2) == 1)
|
|
$nextarg++;
|
|
else
|
|
{
|
|
$nextchar = substr($sql, $nextarg + 1, 1);
|
|
if (is_numeric($nextchar))
|
|
{
|
|
$arglength = 0;
|
|
$arg = '';
|
|
|
|
// find next non-digit
|
|
while (preg_match('/^[0-9]{1}/', $nextchar) == 1)
|
|
{
|
|
$arg .= $nextchar;
|
|
|
|
$arglength++;
|
|
$nextchar = substr($sql, $nextarg + $arglength + 1, 1);
|
|
}
|
|
|
|
// ok ... replace
|
|
$filtered_sql .= substr($sql, $sqlpos, $nextarg - $sqlpos);
|
|
$sqlpos = $nextarg + $arglength;
|
|
|
|
if (isset($args[$arg]))
|
|
{
|
|
if (is_numeric($args[$arg]))
|
|
$filtered_sql .= $args[$arg];
|
|
else
|
|
{
|
|
if ((substr($sql, $sqlpos - $arglength - 1, 1) == '\'') && (substr($sql, $sqlpos + 1, 1) == '\''))
|
|
$filtered_sql .= sql_escape($args[$arg]);
|
|
else if ((substr($sql, $sqlpos - $arglength - 1, 1) == '`') && (substr($sql, $sqlpos + 1, 1) == '`'))
|
|
$filtered_sql .= sql_escape_backtick($args[$arg]);
|
|
else
|
|
sql_error();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// NULL
|
|
if ((substr($sql, $sqlpos - $arglength - 1, 1) == '\'') && (substr($sql, $sqlpos + 1, 1) == '\''))
|
|
{
|
|
// strip apostroph and insert NULL
|
|
$filtered_sql = substr($filtered_sql, 0, strlen($filtered_sql) - 1);
|
|
$filtered_sql .= 'NULL';
|
|
$sqlpos++;
|
|
}
|
|
else
|
|
$filtered_sql .= 'NULL';
|
|
}
|
|
|
|
$sqlpos++;
|
|
}
|
|
else
|
|
{
|
|
$arglength = 0;
|
|
$arg = '';
|
|
|
|
// find next non-alphanumeric char
|
|
while (preg_match('/^[a-zA-Z0-9]{1}/', $nextchar) == 1)
|
|
{
|
|
$arg .= $nextchar;
|
|
|
|
$arglength++;
|
|
$nextchar = substr($sql, $nextarg + $arglength + 1, 1);
|
|
}
|
|
|
|
// ok ... replace
|
|
$filtered_sql .= substr($sql, $sqlpos, $nextarg - $sqlpos);
|
|
|
|
if (isset($opt['db']['placeholder'][$arg]))
|
|
{
|
|
if (substr($sql, $nextarg - 1, 1) != '`')
|
|
$filtered_sql .= '`';
|
|
|
|
$filtered_sql .= sql_escape_backtick($opt['db']['placeholder'][$arg]);
|
|
|
|
if (substr($sql, $nextarg + $arglength + 1, 1) != '`')
|
|
$filtered_sql .= '`';
|
|
}
|
|
else if (isset($db['temptables'][$arg]))
|
|
{
|
|
if (substr($sql, $nextarg - 1, 1) != '`')
|
|
$filtered_sql .= '`';
|
|
|
|
$filtered_sql .= sql_escape_backtick($opt['db']['placeholder']['tmpdb']) . '`.`' . sql_escape_backtick($db['temptables'][$arg]);
|
|
|
|
if (substr($sql, $nextarg + $arglength + 1, 1) != '`')
|
|
$filtered_sql .= '`';
|
|
}
|
|
else
|
|
sql_error();
|
|
|
|
$sqlpos = $nextarg + $arglength + 1;
|
|
}
|
|
}
|
|
|
|
$nextarg = strpos($sql, '&', $nextarg + 1);
|
|
}
|
|
|
|
// append the rest
|
|
$filtered_sql .= substr($sql, $sqlpos);
|
|
|
|
// strip escapes of &
|
|
$nextarg = strpos($filtered_sql, '\&');
|
|
while ($nextarg !== false)
|
|
{
|
|
$escapesCount = 0;
|
|
while ((($nextarg - $escapesCount - 1) > 0) && (substr($filtered_sql, $nextarg - $escapesCount - 1, 1) == '\\')) $escapesCount++;
|
|
if (($escapesCount % 2) == 0)
|
|
{
|
|
// strip escapes of &
|
|
$filtered_sql = substr($filtered_sql, 0, $nextarg) . '&' . substr($filtered_sql, $nextarg + 2);
|
|
$nextarg--;
|
|
}
|
|
|
|
$nextarg = strpos($filtered_sql, '\&', $nextarg + 2);
|
|
}
|
|
|
|
//
|
|
// ok ... filtered_sql is ready for usage
|
|
//
|
|
|
|
/* todo:
|
|
- errorlogging
|
|
- LIMIT
|
|
- block DROP/DELETE
|
|
*/
|
|
|
|
if (isset($db['debug']) && ($db['debug'] == true))
|
|
{
|
|
require_once($opt['rootpath'] . 'lib2/sqldebugger.class.php');
|
|
$result = $sqldebugger->execute($filtered_sql, $dblink, ($dblink===$db['dblink_slave']), $db['slave_server']);
|
|
if ($result === false)
|
|
{
|
|
sql_error();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// measure time
|
|
if ($opt['db']['warn']['time'] > 0)
|
|
{
|
|
require_once($opt['rootpath'] . 'lib2/bench.inc.php');
|
|
$cSqlExecution = new Cbench;
|
|
$cSqlExecution->start();
|
|
}
|
|
|
|
$result = @mysql_query($filtered_sql, $dblink);
|
|
if ($result === false)
|
|
{
|
|
sql_error();
|
|
}
|
|
|
|
if ($opt['db']['warn']['time'] > 0)
|
|
{
|
|
$cSqlExecution->stop();
|
|
|
|
if ($cSqlExecution->diff() > $opt['db']['warn']['time'])
|
|
sql_warn('execution took ' . $cSqlExecution->diff() . ' seconds');
|
|
}
|
|
}
|
|
|
|
return $result;
|
|
}
|
|
|
|
function sqlf($sql)
|
|
{
|
|
global $db;
|
|
$nOldMode = $db['mode'];
|
|
$db['mode'] = DB_MODE_FRAMEWORK;
|
|
$args = func_get_args();
|
|
unset($args[0]);
|
|
$result = sql($sql, $args);
|
|
$db['mode'] = $nOldMode;
|
|
return $result;
|
|
}
|
|
|
|
function sqlf_slave($sql)
|
|
{
|
|
global $db;
|
|
$nOldMode = $db['mode'];
|
|
$db['mode'] = DB_MODE_FRAMEWORK;
|
|
$args = func_get_args();
|
|
unset($args[0]);
|
|
$result = sql_slave($sql, $args);
|
|
$db['mode'] = $nOldMode;
|
|
return $result;
|
|
}
|
|
|
|
function sqll($sql)
|
|
{
|
|
global $db;
|
|
$nOldMode = $db['mode'];
|
|
$db['mode'] = DB_MODE_BUSINESSLAYER;
|
|
$args = func_get_args();
|
|
unset($args[0]);
|
|
$result = sql($sql, $args);
|
|
$db['mode'] = $nOldMode;
|
|
return $result;
|
|
}
|
|
|
|
function sqlf_value($sql, $default)
|
|
{
|
|
global $db;
|
|
$nOldMode = $db['mode'];
|
|
$db['mode'] = DB_MODE_FRAMEWORK;
|
|
$args = func_get_args();
|
|
unset($args[0]);
|
|
unset($args[1]);
|
|
$result = sql_value($sql, $default, $args);
|
|
$db['mode'] = $nOldMode;
|
|
return $result;
|
|
}
|
|
|
|
function sqll_value($sql, $default)
|
|
{
|
|
global $db;
|
|
$nOldMode = $db['mode'];
|
|
$db['mode'] = DB_MODE_BUSINESSLAYER;
|
|
$args = func_get_args();
|
|
unset($args[0]);
|
|
unset($args[1]);
|
|
$result = sql_value($sql, $default, $args);
|
|
$db['mode'] = $nOldMode;
|
|
return $result;
|
|
}
|
|
|
|
function sql_escape($value)
|
|
{
|
|
global $db, $opt;
|
|
|
|
// convert the charset of $value
|
|
if ($opt['charset']['iconv'] != 'UTF-8')
|
|
$value = iconv('UTF-8', $opt['charset']['iconv'], $value);
|
|
|
|
// establish db connection
|
|
if ($db['connected'] != true) sql_connect();
|
|
|
|
$value = mysql_real_escape_string($value, $db['dblink']);
|
|
$value = str_replace('&', '\&', $value);
|
|
return $value;
|
|
}
|
|
|
|
function sql_escape_backtick($value)
|
|
{
|
|
$value = sql_escape($value);
|
|
$value = str_replace('`', '``', $value);
|
|
return $value;
|
|
}
|
|
|
|
function sql_value($sql, $default)
|
|
{
|
|
$args = func_get_args();
|
|
unset($args[0]);
|
|
unset($args[1]);
|
|
|
|
if (isset($args[2]) && is_array($args[2]))
|
|
{
|
|
$tmp_args = $args[2];
|
|
unset($args);
|
|
|
|
// correct indizes
|
|
$args = array_merge(array(0), $tmp_args);
|
|
unset($tmp_args);
|
|
unset($args[0]);
|
|
}
|
|
|
|
return sql_value_internal(false, $sql, $default, $args);
|
|
}
|
|
|
|
function sql_value_slave($sql, $default)
|
|
{
|
|
$args = func_get_args();
|
|
unset($args[0]);
|
|
unset($args[1]);
|
|
|
|
if (isset($args[2]) && is_array($args[2]))
|
|
{
|
|
$tmp_args = $args[2];
|
|
unset($args);
|
|
|
|
// correct indizes
|
|
$args = array_merge(array(0), $tmp_args);
|
|
unset($tmp_args);
|
|
unset($args[0]);
|
|
}
|
|
|
|
return sql_value_internal(true, $sql, $default, $args);
|
|
}
|
|
|
|
function sql_value_internal($bQuerySlave, $sql, $default)
|
|
{
|
|
$args = func_get_args();
|
|
unset($args[0]);
|
|
unset($args[1]);
|
|
unset($args[2]);
|
|
|
|
/* as an option, you can give as third parameter an array
|
|
* with all values for the placeholder. The array has to be
|
|
* with numeric indizes.
|
|
*/
|
|
if (isset($args[3]) && is_array($args[3]))
|
|
{
|
|
$tmp_args = $args[3];
|
|
unset($args);
|
|
|
|
// correct indizes
|
|
$args = array_merge(array(0), $tmp_args);
|
|
unset($tmp_args);
|
|
unset($args[0]);
|
|
}
|
|
|
|
if ($bQuerySlave == true)
|
|
$rs = sql_slave($sql, $args);
|
|
else
|
|
$rs = sql($sql, $args);
|
|
|
|
$r = sql_fetch_row($rs);
|
|
sql_free_result($rs);
|
|
|
|
if ($r)
|
|
{
|
|
if ($r[0] == null)
|
|
return $default;
|
|
else
|
|
return $r[0];
|
|
}
|
|
else
|
|
return $default;
|
|
}
|
|
|
|
/*
|
|
Replacement for builtin MySQL functions
|
|
(includes database charset conversion)
|
|
*/
|
|
function sql_fetch_array($rs)
|
|
{
|
|
global $opt;
|
|
$retval = mysql_fetch_array($rs);
|
|
if (is_array($retval))
|
|
if ($opt['charset']['iconv'] != 'UTF-8')
|
|
foreach ($retval AS $k => $v)
|
|
$retval[$k] = iconv($opt['charset']['iconv'], 'UTF-8', $v);
|
|
return $retval;
|
|
}
|
|
|
|
function sql_fetch_assoc($rs)
|
|
{
|
|
global $opt;
|
|
$retval = mysql_fetch_assoc($rs);
|
|
if (is_array($retval))
|
|
if ($opt['charset']['iconv'] != 'UTF-8')
|
|
foreach ($retval AS $k => $v)
|
|
$retval[$k] = iconv($opt['charset']['iconv'], 'UTF-8', $v);
|
|
return $retval;
|
|
}
|
|
|
|
function sql_fetch_row($rs)
|
|
{
|
|
global $opt;
|
|
$retval = mysql_fetch_row($rs);
|
|
if (is_array($retval))
|
|
if ($opt['charset']['iconv'] != 'UTF-8')
|
|
foreach ($retval AS $k => $v)
|
|
$retval[$k] = iconv($opt['charset']['iconv'], 'UTF-8', $v);
|
|
return $retval;
|
|
}
|
|
|
|
function sql_affected_rows()
|
|
{
|
|
global $db;
|
|
return mysql_affected_rows($db['dblink']);
|
|
}
|
|
|
|
function sql_affected_rows_slave()
|
|
{
|
|
global $db;
|
|
return mysql_affected_rows($db['dblink_slave']);
|
|
}
|
|
|
|
function sql_free_result($rs)
|
|
{
|
|
return mysql_free_result($rs);
|
|
}
|
|
|
|
function sql_insert_id()
|
|
{
|
|
global $db;
|
|
return mysql_insert_id($db['dblink']);
|
|
}
|
|
|
|
function sql_insert_id_slave()
|
|
{
|
|
global $db;
|
|
return mysql_insert_id($db['dblink_slave']);
|
|
}
|
|
|
|
function sql_num_rows($rs)
|
|
{
|
|
return mysql_num_rows($rs);
|
|
}
|
|
|
|
function sql_temp_table($table)
|
|
{
|
|
global $db, $opt;
|
|
|
|
if ($db['connected'] == false)
|
|
sql_connect();
|
|
|
|
if ($opt['db']['pconnect'] == true)
|
|
{
|
|
if ($db['temptable_initialized'] == false)
|
|
{
|
|
$rs = sqlf("SELECT `threadid`, `name` FROM &db.`sys_temptables` WHERE `threadid`='&1'", mysql_thread_id($db['dblink']));
|
|
while ($r = sql_fetch_assoc($rs))
|
|
{
|
|
sqlf("DROP TEMPORARY TABLE IF EXISTS &tmpdb.`&1`", $r['name']);
|
|
}
|
|
sql_free_result($rs);
|
|
sqlf("DELETE FROM &db.`sys_temptables` WHERE `threadid`='&1'", mysql_thread_id($db['dblink']));
|
|
|
|
$db['temptable_initialized'] = true;
|
|
}
|
|
|
|
sqlf("INSERT IGNORE INTO &db.`sys_temptables` (`threadid`, `name`) VALUES ('&1', '&2')", mysql_thread_id($db['dblink']), $table);
|
|
}
|
|
|
|
$db['temptables'][$table] = $table;
|
|
}
|
|
|
|
function sql_temp_table_slave($table)
|
|
{
|
|
global $db, $opt;
|
|
|
|
if ($db['dblink_slave'] === false)
|
|
sql_connect_anyslave();
|
|
|
|
if ($opt['db']['pconnect'] == true)
|
|
sqlf_slave("INSERT IGNORE INTO &db.`sys_temptables` (`threadid`, `name`) VALUES ('&1', '&2')", mysql_thread_id($db['dblink_slave']), $table);
|
|
|
|
$db['temptables'][$table] = $table;
|
|
$db['temptables_slave'][$table] = $table;
|
|
}
|
|
|
|
function sql_drop_temp_table($table)
|
|
{
|
|
global $db, $opt;
|
|
|
|
sqlf("DROP TEMPORARY TABLE IF EXISTS &tmpdb.`&1`", $table);
|
|
|
|
if ($opt['db']['pconnect'] == true)
|
|
sqlf("DELETE FROM &db.`sys_temptables` WHERE `threadid`='&1' AND `name`='&2'", mysql_thread_id($db['dblink']), $table);
|
|
|
|
unset($db['temptables'][$table]);
|
|
}
|
|
|
|
function sql_drop_temp_table_slave($table)
|
|
{
|
|
global $db, $opt;
|
|
|
|
sqlf_slave("DROP TEMPORARY TABLE IF EXISTS &tmpdb.`&1`", $table);
|
|
|
|
if ($opt['db']['pconnect'] == true)
|
|
sqlf_slave("DELETE FROM &db.`sys_temptables` WHERE `threadid`='&1' AND `name`='&2'", mysql_thread_id($db['dblink']), $table);
|
|
|
|
unset($db['temptables'][$table]);
|
|
unset($db['temptables_slave'][$table]);
|
|
}
|
|
|
|
//database handling
|
|
function sql_connect($username=null, $password=null, $raiseError=true)
|
|
{
|
|
global $opt, $db;
|
|
|
|
if ($username == null)
|
|
$username = $opt['db']['username'];
|
|
if ($password == null)
|
|
$password = $opt['db']['password'];
|
|
|
|
//connect to the database by the given method - no php error reporting!
|
|
if ($opt['db']['pconnect'] == true)
|
|
$db['dblink'] = @mysql_pconnect($opt['db']['servername'], $username, $password);
|
|
else
|
|
$db['dblink'] = @mysql_connect($opt['db']['servername'], $username, $password);
|
|
|
|
if ($db['dblink'] !== false)
|
|
{
|
|
mysql_query("SET NAMES '" . mysql_real_escape_string($opt['charset']['mysql'], $db['dblink']) . "'", $db['dblink']);
|
|
|
|
//database connection established ... set the used database
|
|
if (@mysql_select_db($opt['db']['placeholder']['db'], $db['dblink']) == false)
|
|
{
|
|
//error while setting the database ... disconnect
|
|
sql_disconnect();
|
|
$db['dblink'] = false;
|
|
}
|
|
}
|
|
|
|
// output the error form if there was an error
|
|
if ($db['dblink'] === false)
|
|
{
|
|
if ($raiseError == true)
|
|
sql_error();
|
|
}
|
|
else
|
|
$db['connected'] = true;
|
|
}
|
|
|
|
function sql_slave_exclude()
|
|
{
|
|
global $login;
|
|
if ($login->userid == 0)
|
|
return;
|
|
|
|
sql("INSERT INTO `sys_repl_exclude` (`user_id`, `datExclude`) VALUES ('&1', NOW())
|
|
ON DUPLICATE KEY UPDATE `datExclude`=NOW()", $login->userid);
|
|
}
|
|
|
|
function sql_connect_anyslave()
|
|
{
|
|
global $db, $opt, $login;
|
|
|
|
if ($db['dblink_slave'] !== false)
|
|
return;
|
|
|
|
$nMaxTimeDiff = $opt['db']['slave']['max_behind'];
|
|
if ($login->userid != 0)
|
|
{
|
|
$nMaxTimeDiff = sql_value("SELECT TIMESTAMP(NOW())-TIMESTAMP(`datExclude`) FROM `sys_repl_exclude` WHERE `user_id`='&1'", $opt['db']['slave']['max_behind'], $login->userid);
|
|
if ($nMaxTimeDiff > $opt['db']['slave']['max_behind'])
|
|
$nMaxTimeDiff = $opt['db']['slave']['max_behind'];
|
|
}
|
|
|
|
$id = sqlf_value("SELECT `id`, `weight`*RAND() AS `w` FROM `sys_repl_slaves` WHERE `active`=1 AND `online`=1 AND (TIMESTAMP(NOW())-TIMESTAMP(`last_check`)+`time_diff`<'&1') ORDER BY `w` DESC LIMIT 1", -1, $nMaxTimeDiff);
|
|
|
|
sql_connect_slave($id);
|
|
}
|
|
|
|
function sql_connect_master_as_slave()
|
|
{
|
|
global $db;
|
|
|
|
// the right slave is connected
|
|
if ($db['dblink_slave'] !== false)
|
|
{
|
|
sql_error();
|
|
return;
|
|
}
|
|
|
|
// use existing master connection
|
|
$db['slave_id'] = -1;
|
|
$db['dblink_slave'] = $db['dblink'];
|
|
$db['slave_server'] = 'master';
|
|
}
|
|
|
|
function sql_connect_slave($id)
|
|
{
|
|
global $opt, $db;
|
|
|
|
if ($id == -1)
|
|
{
|
|
sql_connect_master_as_slave();
|
|
return;
|
|
}
|
|
|
|
// the right slave is connected
|
|
if ($db['dblink_slave'] !== false)
|
|
{
|
|
// TODO: disconnect if other slave is connected
|
|
if ($db['slave_id'] != $id)
|
|
sql_error();
|
|
|
|
return;
|
|
}
|
|
|
|
$db['slave_id'] = $id;
|
|
$slave = $opt['db']['slaves'][$id];
|
|
|
|
// for display in SQL debugger
|
|
$db['slave_server'] = $slave['server'];
|
|
|
|
if ($opt['db']['pconnect'] == true)
|
|
$db['dblink_slave'] = @mysql_pconnect($slave['server'], $slave['username'], $slave['password']);
|
|
else
|
|
$db['dblink_slave'] = @mysql_connect($slave['server'], $slave['username'], $slave['password']);
|
|
|
|
if ($db['dblink_slave'] !== false)
|
|
{
|
|
if (mysql_select_db($opt['db']['placeholder']['db'], $db['dblink_slave']) == false)
|
|
sql_error();
|
|
|
|
mysql_query("SET NAMES '" . mysql_real_escape_string($opt['charset']['mysql'], $db['dblink_slave']) . "'", $db['dblink_slave']);
|
|
|
|
// initialize temp tables on slave server
|
|
$rs = sqlf_slave("SELECT `threadid`, `name` FROM `sys_temptables` WHERE `threadid`='&1'", mysql_thread_id($db['dblink_slave']));
|
|
while ($r = sql_fetch_assoc($rs))
|
|
{
|
|
sqlf_slave("DROP TEMPORARY TABLE IF EXISTS &tmpdb.`&1`", $r['name']);
|
|
}
|
|
sql_free_result($rs);
|
|
sqlf_slave("DELETE FROM &db.`sys_temptables` WHERE `threadid`='&1'", mysql_thread_id($db['dblink_slave']));
|
|
}
|
|
else
|
|
sql_error();
|
|
}
|
|
|
|
function sql_connect_root()
|
|
{
|
|
global $tpl, $db, $opt;
|
|
|
|
if (file_exists($opt['rootpath'] . 'config2/sqlroot.inc.php'))
|
|
require($opt['rootpath'] . 'config2/sqlroot.inc.php');
|
|
else
|
|
return false;
|
|
|
|
sql_disconnect();
|
|
sql_connect($opt['sqlroot']['username'], $opt['sqlroot']['password'], false);
|
|
if ($db['dblink'] === false)
|
|
{
|
|
sql_disconnect();
|
|
sql_connect();
|
|
if ($db['connected'] == false)
|
|
$tpl->error(ERROR_DB_COULD_NOT_RECONNECT);
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
//disconnect the databse
|
|
function sql_disconnect()
|
|
{
|
|
global $opt, $db;
|
|
sql_disconnect_slave();
|
|
|
|
if (($opt['db']['pconnect'] == true) && ($db['dblink'] !== false))
|
|
{
|
|
if (count($db['temptables']) > 0)
|
|
{
|
|
foreach ($db['temptables'] AS $table)
|
|
sqlf("DROP TEMPORARY TABLE IF EXISTS &tmpdb.`&1`", $table);
|
|
|
|
sqlf("DELETE FROM &db.`sys_temptables` WHERE `threadid`='&1'", mysql_thread_id($db['dblink']));
|
|
$db['temptables'] = array();
|
|
$db['temptables_slave'] = array();
|
|
}
|
|
}
|
|
|
|
if ($db['dblink'] === $db['dblink_slave'])
|
|
$db['dblink_slave'] = false;
|
|
|
|
//is connected and no persistent connect used?
|
|
if (($opt['db']['pconnect'] == false) && ($db['dblink'] !== false))
|
|
{
|
|
mysql_close($db['dblink']);
|
|
$db['dblink'] = false;
|
|
$db['connected'] = false;
|
|
}
|
|
}
|
|
|
|
//disconnect the databse
|
|
function sql_disconnect_slave()
|
|
{
|
|
global $opt, $db;
|
|
|
|
if ($db['dblink_slave'] === false)
|
|
return;
|
|
|
|
if (($opt['db']['pconnect'] == true) && ($db['dblink'] !== false))
|
|
{
|
|
if (count($db['temptables']) > 0)
|
|
{
|
|
foreach ($db['temptables'] AS $k => $table)
|
|
{
|
|
if (isset($db['temptables_slave'][$table]))
|
|
{
|
|
sqlf_slave("DROP TEMPORARY TABLE IF EXISTS &tmpdb.`&1`", $table);
|
|
unset($db['temptables_slave'][$table]);
|
|
unset($db['temptables'][$k]);
|
|
}
|
|
}
|
|
|
|
if (count($db['temptables_slave']) > 0)
|
|
sqlf_slave("DELETE FROM &db.`sys_temptables` WHERE `threadid`='&1'", mysql_thread_id($db['dblink_slave']));
|
|
$db['temptables_slave'] = array();
|
|
}
|
|
}
|
|
|
|
if ($db['dblink'] === $db['dblink_slave'])
|
|
{
|
|
$db['dblink_slave'] = false;
|
|
return;
|
|
}
|
|
|
|
//is connected and no persistent connect used?
|
|
if (($opt['db']['pconnect'] == false) && ($db['dblink_slave'] !== false))
|
|
mysql_close($db['dblink_slave']);
|
|
$db['dblink_slave'] = false;
|
|
}
|
|
|
|
function sql_error()
|
|
{
|
|
global $tpl, $opt, $db;
|
|
global $bSmartyNoTranslate;
|
|
|
|
if ($db['error'] == true)
|
|
die("sql_error() recursion, aborting!\nCheck if database connect does work.\nMost often, an error mail tried to load translations from database.\nMySQL Error no " . mysql_errno() . "\n");
|
|
|
|
$db['error'] = true;
|
|
|
|
$errno = mysql_errno();
|
|
$error = mysql_error();
|
|
|
|
if ($db['connected'] == false)
|
|
$bSmartyNoTranslate = true;
|
|
|
|
if ($opt['db']['error']['mail'] != '')
|
|
{
|
|
require_once($opt['rootpath'] . 'lib2/mail.class.php');
|
|
$mail = new mail();
|
|
$mail->subject = $opt['db']['error']['subject'];
|
|
$mail->to = $opt['db']['error']['mail'];
|
|
|
|
$mail->name = 'sql_error';
|
|
|
|
$mail->assign('errno', $errno);
|
|
$mail->assign('error', $error);
|
|
$mail->assign('trace', print_r(debug_backtrace(), true));
|
|
|
|
$mail->send();
|
|
$mail = null;
|
|
}
|
|
|
|
if ($opt['gui'] == GUI_HTML)
|
|
{
|
|
if (isset($tpl))
|
|
{
|
|
if ($opt['db']['error']['display'] == true)
|
|
$tpl->error('MySQL error' . ' (' . $errno . '): ' . $error);
|
|
else
|
|
$tpl->error('A database command could not be performed.');
|
|
}
|
|
else
|
|
{
|
|
if ($opt['db']['error']['display'] == true)
|
|
die('<html><body>' . htmlspecialchars('MySQL error (' .$errno . '): ' . $error) . '</body></html>');
|
|
else
|
|
die('<html><body>A database command could not be performed</body></html>');
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// CLI script, simple text output
|
|
if ($opt['db']['error']['display'] == true)
|
|
die('MySQL error' . ' (' . $errno . '): ' . $error . "\n");
|
|
else
|
|
die("A database command could not be performed.\n");
|
|
}
|
|
}
|
|
|
|
function sql_warn($warnmessage)
|
|
{
|
|
global $opt;
|
|
|
|
if ($opt['db']['error']['mail'] != '')
|
|
{
|
|
require_once($opt['rootpath'] . 'lib2/mail.class.php');
|
|
$mail = new mail();
|
|
$mail->name = 'sql_warn';
|
|
$mail->subject = $opt['db']['warn']['subject'];
|
|
$mail->to = $opt['db']['warn']['mail'];
|
|
|
|
$mail->assign('warnmessage', $warnmessage);
|
|
$mail->assign('trace', print_r(debug_backtrace(), true));
|
|
|
|
$mail->send();
|
|
$mail = null;
|
|
}
|
|
}
|
|
|
|
function sql_export_recordset($f, $rs, $table, $truncate=true)
|
|
{
|
|
fwrite($f, "SET NAMES 'utf8';\n");
|
|
|
|
if ($truncate == true)
|
|
fwrite($f, "TRUNCATE TABLE `" . sql_escape($table) . "`;\n");
|
|
|
|
while ($r = sql_fetch_assoc($rs))
|
|
{
|
|
$fields = array();
|
|
$values = array();
|
|
|
|
foreach ($r AS $k => $v)
|
|
{
|
|
$fields[] = '`' . sql_escape($k) . '`';
|
|
if ($v === null)
|
|
$values[] = "NULL";
|
|
else
|
|
$values[] = "'" . sql_escape($v) . "'";
|
|
}
|
|
unset($r);
|
|
|
|
fwrite($f, "INSERT INTO `" . sql_escape($table) . "` (" . implode(', ', $fields) . ") VALUES (" . implode(', ', $values) . ");\n");
|
|
}
|
|
}
|
|
|
|
function sql_export_table($f, $table)
|
|
{
|
|
$primary = array();
|
|
$rsIndex = sql("SHOW INDEX FROM `&1`", $table);
|
|
while ($r = sql_fetch_assoc($rsIndex))
|
|
{
|
|
if ($r['Key_name'] == 'PRIMARY')
|
|
{
|
|
$primary[] = '`' . sql_escape($r['Column_name']) . '` ASC';
|
|
}
|
|
}
|
|
sql_free_result($rsIndex);
|
|
|
|
$sql = "SELECT * FROM `" . sql_escape($table) . "`";
|
|
if (count($primary) > 0)
|
|
{
|
|
$sql .= ' ORDER BY ' . implode(', ', $primary);
|
|
}
|
|
|
|
$rs = sql($sql);
|
|
sql_export_recordset($f, $rs, $table);
|
|
sql_free_result($rs);
|
|
}
|
|
|
|
function sql_export_tables_to_file($filename, $tables)
|
|
{
|
|
$f = fopen($filename, 'w');
|
|
|
|
fwrite($f, "-- Content of tables:\n");
|
|
|
|
foreach ($tables AS $t)
|
|
fwrite($f, "-- $t\n");
|
|
fwrite($f, "\n");
|
|
|
|
foreach ($tables AS $t)
|
|
{
|
|
fwrite($f, "-- Table $t\n");
|
|
sql_export_table($f, $t);
|
|
fwrite($f, "\n");
|
|
}
|
|
|
|
fclose($f);
|
|
}
|
|
|
|
function sql_export_table_to_file($filename, $table)
|
|
{
|
|
$f = fopen($filename, 'w');
|
|
sql_export_table($f, $table);
|
|
fclose($f);
|
|
}
|
|
|
|
function sql_export_structure($f, $table)
|
|
{
|
|
$rs = sql("SHOW CREATE TABLE `&1`", $table);
|
|
$r = sql_fetch_array($rs);
|
|
sql_free_result($rs);
|
|
|
|
$sTableSql = $r[1];
|
|
$sTableSql = preg_replace('/ AUTO_INCREMENT=[0-9]{1,} /', ' ', $sTableSql);
|
|
|
|
fwrite($f, "SET NAMES 'utf8';\n");
|
|
fwrite($f, "DROP TABLE IF EXISTS `" . sql_escape($table) . "`;\n");
|
|
fwrite($f, $sTableSql . " ;\n");
|
|
}
|
|
|
|
function sql_export_structure_to_file($filename, $table)
|
|
{
|
|
$f = fopen($filename, 'w');
|
|
sql_export_structure($f, $table);
|
|
fclose($f);
|
|
}
|
|
?>
|