diff options
Diffstat (limited to 'include/dblayer/functions_mysql.inc.php')
-rw-r--r-- | include/dblayer/functions_mysql.inc.php | 463 |
1 files changed, 463 insertions, 0 deletions
diff --git a/include/dblayer/functions_mysql.inc.php b/include/dblayer/functions_mysql.inc.php new file mode 100644 index 000000000..23d232675 --- /dev/null +++ b/include/dblayer/functions_mysql.inc.php @@ -0,0 +1,463 @@ +<?php +// +-----------------------------------------------------------------------+ +// | Piwigo - a PHP based picture gallery | +// +-----------------------------------------------------------------------+ +// | Copyright(C) 2008-2009 Piwigo Team http://piwigo.org | +// | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | +// | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | +// +-----------------------------------------------------------------------+ +// | This program is free software; you can redistribute it and/or modify | +// | it under the terms of the GNU General Public License as published by | +// | the Free Software Foundation | +// | | +// | This program is distributed in the hope that it will be useful, but | +// | WITHOUT ANY WARRANTY; without even the implied warranty of | +// | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | +// | General Public License for more details. | +// | | +// | You should have received a copy of the GNU General Public License | +// | along with this program; if not, write to the Free Software | +// | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, | +// | USA. | +// +-----------------------------------------------------------------------+ + +/** + * + * simple functions + * + */ + +function pwg_db_connect($host, $user, $password, $database) +{ + $link = mysql_connect($host, $user, $password) or my_error('mysql_connect', true); + mysql_select_db($database, $link) or my_error('mysql_select_db', true); + + return $link; +} + +function pwg_db_check_charset() +{ + defined('PWG_CHARSET') and defined('DB_CHARSET') + or fatal_error('PWG_CHARSET and/or DB_CHARSET is not defined'); + if ( version_compare(mysql_get_server_info(), '4.1.0', '>=') ) + { + if (DB_CHARSET!='') + { + pwg_query('SET NAMES "'.DB_CHARSET.'"'); + } + } + elseif ( strtolower(PWG_CHARSET)!='iso-8859-1' ) + { + fatal_error('PWG supports only iso-8859-1 charset on MySql version '.mysql_get_server_info()); + } +} + +function pwg_get_db_version() +{ + list($mysql_version) = pwg_db_fetch_row(pwg_query('SELECT VERSION();')); + + return $mysql_version; +} + +function pwg_query($query) +{ + global $conf,$page,$debug,$t2; + + $start = get_moment(); + ($result = mysql_query($query)) or my_error($query, $conf['die_on_sql_error']); + + $time = get_moment() - $start; + + if (!isset($page['count_queries'])) + { + $page['count_queries'] = 0; + $page['queries_time'] = 0; + } + + $page['count_queries']++; + $page['queries_time']+= $time; + + if ($conf['show_queries']) + { + $output = ''; + $output.= '<pre>['.$page['count_queries'].'] '; + $output.= "\n".$query; + $output.= "\n".'(this query time : '; + $output.= '<b>'.number_format($time, 3, '.', ' ').' s)</b>'; + $output.= "\n".'(total SQL time : '; + $output.= number_format($page['queries_time'], 3, '.', ' ').' s)'; + $output.= "\n".'(total time : '; + $output.= number_format( ($time+$start-$t2), 3, '.', ' ').' s)'; + if ( $result!=null and preg_match('/\s*SELECT\s+/i',$query) ) + { + $output.= "\n".'(num rows : '; + $output.= mysql_num_rows($result).' )'; + } + elseif ( $result!=null + and preg_match('/\s*INSERT|UPDATE|REPLACE|DELETE\s+/i',$query) ) + { + $output.= "\n".'(affected rows : '; + $output.= mysql_affected_rows().' )'; + } + $output.= "</pre>\n"; + + $debug .= $output; + } + + return $result; +} + +function pwg_db_changes($result) +{ + return mysql_affected_rows($result); +} + +function pwg_db_num_rows($result) +{ + return mysql_num_rows($result); +} + +function pwg_db_fetch_assoc($result) +{ + return mysql_fetch_assoc($result); +} + +function pwg_db_fetch_row($result) +{ + return mysql_fetch_row($result); +} + +function pwg_db_fetch_object($result) +{ + return mysql_fetch_object($result); +} + +function pwg_free_result($result) +{ + return mysql_free_result($result); +} + +function pwg_db_real_escape_string($s) +{ + return mysql_real_escape_string($s); +} + +function pwg_db_insert_id() +{ + return mysql_insert_id(); +} + +/** + * + * complex functions + * + */ + +/** + * creates an array based on a query, this function is a very common pattern + * used here + * + * @param string $query + * @param string $fieldname + * @return array + */ +function array_from_query($query, $fieldname) +{ + $array = array(); + + $result = pwg_query($query); + while ($row = mysql_fetch_assoc($result)) + { + array_push($array, $row[$fieldname]); + } + + return $array; +} + +define('MASS_UPDATES_SKIP_EMPTY', 1); +/** + * updates multiple lines in a table + * + * @param string table_name + * @param array dbfields + * @param array datas + * @param int flags - if MASS_UPDATES_SKIP_EMPTY - empty values do not overwrite existing ones + * @return void + */ +function mass_updates($tablename, $dbfields, $datas, $flags=0) +{ + if (count($datas) == 0) + return; + // depending on the MySQL version, we use the multi table update or N update queries + if (count($datas) < 10 or version_compare(mysql_get_server_info(), '4.0.4') < 0) + { // MySQL is prior to version 4.0.4, multi table update feature is not available + foreach ($datas as $data) + { + $query = ' +UPDATE '.$tablename.' + SET '; + $is_first = true; + foreach ($dbfields['update'] as $key) + { + $separator = $is_first ? '' : ",\n "; + + if (isset($data[$key]) and $data[$key] != '') + { + $query.= $separator.$key.' = \''.$data[$key].'\''; + } + else + { + if ($flags & MASS_UPDATES_SKIP_EMPTY ) + continue; // next field + $query.= "$separator$key = NULL"; + } + $is_first = false; + } + if (!$is_first) + {// only if one field at least updated + $query.= ' + WHERE '; + $is_first = true; + foreach ($dbfields['primary'] as $key) + { + if (!$is_first) + { + $query.= ' AND '; + } + if ( isset($data[$key]) ) + { + $query.= $key.' = \''.$data[$key].'\''; + } + else + { + $query.= $key.' IS NULL'; + } + $is_first = false; + } + pwg_query($query); + } + } // foreach update + } // if mysql_ver or count<X + else + { + // creation of the temporary table + $query = ' +SHOW FULL COLUMNS FROM '.$tablename; + $result = pwg_query($query); + $columns = array(); + $all_fields = array_merge($dbfields['primary'], $dbfields['update']); + while ($row = pwg_db_fetch_assoc($result)) + { + if (in_array($row['Field'], $all_fields)) + { + $column = $row['Field']; + $column.= ' '.$row['Type']; + + $nullable = true; + if (!isset($row['Null']) or $row['Null'] == '' or $row['Null']=='NO') + { + $column.= ' NOT NULL'; + $nullable = false; + } + if (isset($row['Default'])) + { + $column.= " default '".$row['Default']."'"; + } + elseif ($nullable) + { + $column.= " default NULL"; + } + if (isset($row['Collation']) and $row['Collation'] != 'NULL') + { + $column.= " collate '".$row['Collation']."'"; + } + array_push($columns, $column); + } + } + + $temporary_tablename = $tablename.'_'.micro_seconds(); + + $query = ' +CREATE TABLE '.$temporary_tablename.' +( + '.implode(",\n ", $columns).', + UNIQUE KEY the_key ('.implode(',', $dbfields['primary']).') +)'; + + pwg_query($query); + mass_inserts($temporary_tablename, $all_fields, $datas); + if ( $flags & MASS_UPDATES_SKIP_EMPTY ) + $func_set = create_function('$s', 'return "t1.$s = IFNULL(t2.$s, t1.$s)";'); + else + $func_set = create_function('$s', 'return "t1.$s = t2.$s";'); + + // update of images table by joining with temporary table + $query = ' +UPDATE '.$tablename.' AS t1, '.$temporary_tablename.' AS t2 + SET '. + implode( + "\n , ", + array_map($func_set,$dbfields['update']) + ).' + WHERE '. + implode( + "\n AND ", + array_map( + create_function('$s', 'return "t1.$s = t2.$s";'), + $dbfields['primary'] + ) + ); + pwg_query($query); + $query = ' +DROP TABLE '.$temporary_tablename; + pwg_query($query); + } +} + + +/** + * inserts multiple lines in a table + * + * @param string table_name + * @param array dbfields + * @param array inserts + * @return void + */ +function mass_inserts($table_name, $dbfields, $datas) +{ + if (count($datas) != 0) + { + $first = true; + + $query = 'SHOW VARIABLES LIKE \'max_allowed_packet\''; + list(, $packet_size) = pwg_db_fetch_row(pwg_query($query)); + $packet_size = $packet_size - 2000; // The last list of values MUST not exceed 2000 character*/ + $query = ''; + + foreach ($datas as $insert) + { + if (strlen($query) >= $packet_size) + { + pwg_query($query); + $first = true; + } + + if ($first) + { + $query = ' +INSERT INTO '.$table_name.' + ('.implode(',', $dbfields).') + VALUES'; + $first = false; + } + else + { + $query .= ' + , '; + } + + $query .= '('; + foreach ($dbfields as $field_id => $dbfield) + { + if ($field_id > 0) + { + $query .= ','; + } + + if (!isset($insert[$dbfield]) or $insert[$dbfield] === '') + { + $query .= 'NULL'; + } + else + { + $query .= "'".$insert[$dbfield]."'"; + } + } + $query .= ')'; + } + Log::getInstance()->debug($query); + pwg_query($query); + } +} + +/** + * Do maintenance on all PWG tables + * + * @return none + */ +function do_maintenance_all_tables() +{ + global $prefixeTable, $page; + + $all_tables = array(); + + // List all tables + $query = 'SHOW TABLES LIKE \''.$prefixeTable.'%\''; + $result = pwg_query($query); + while ($row = pwg_db_fetch_assoc($result)) + { + array_push($all_tables, $row[0]); + } + + // Repair all tables + $query = 'REPAIR TABLE '.implode(', ', $all_tables); + $mysql_rc = pwg_query($query); + + // Re-Order all tables + foreach ($all_tables as $table_name) + { + $all_primary_key = array(); + + $query = 'DESC '.$table_name.';'; + $result = pwg_query($query); + while ($row = pwg_db_fetch_assoc($result)) + { + if ($row['Key'] == 'PRI') + { + array_push($all_primary_key, $row['Field']); + } + } + + if (count($all_primary_key) != 0) + { + $query = 'ALTER TABLE '.$table_name.' ORDER BY '.implode(', ', $all_primary_key).';'; + $mysql_rc = $mysql_rc && pwg_query($query); + } + } + + // Optimize all tables + $query = 'OPTIMIZE TABLE '.implode(', ', $all_tables); + $mysql_rc = $mysql_rc && pwg_query($query); + if ($mysql_rc) + { + array_push( + $page['infos'], + l10n('Optimizations completed') + ); + } + else + { + array_push( + $page['errors'], + l10n('Optimizations errors') + ); + } +} + +// my_error returns (or send to standard output) the message concerning the +// error occured for the last mysql query. +function my_error($header, $die) +{ + $error = "[mysql error ".mysql_errno().'] '.mysql_error()."\n"; + $error .= $header; + + if ($die) + { + fatal_error($error); + } + echo("<pre>"); + trigger_error($error, E_USER_WARNING); + echo("</pre>"); +} + +?>
\ No newline at end of file |