2 rcs_id('$Id: PearDB_mysql.php,v 1.19 2005-04-10 10:43:25 rurban Exp $');
4 require_once('lib/WikiDB/backend/PearDB.php');
6 // The slowest function overall is mysql_connect with [680ms]
7 // 2nd is db_mysql::simpleQuery with [257ms]
8 class WikiDB_backend_PearDB_mysql
9 extends WikiDB_backend_PearDB
14 function WikiDB_backend_PearDB_mysql($dbparams) {
15 $this->WikiDB_backend_PearDB($dbparams);
16 //$this->_serverinfo = $this->_dbh->ServerInfo();
17 $row = $this->_dbh->GetOne("SELECT version()");
18 if (!DB::isError($row) and !empty($row)) {
19 $arr = explode('.',$row);
20 $this->_serverinfo['version'] = (string)(($arr[0] * 100) + $arr[1]) . "." . (integer)$arr[2];
21 if ($this->_serverinfo['version'] < 323.0) {
22 // Older MySQL's don't have CASE WHEN ... END
23 $this->_expressions['maxmajor'] = "MAX(IF(minor_edit=0,version,0))";
24 $this->_expressions['maxminor'] = "MAX(IF(minor_edit<>0,version,0))";
26 // esp. needed for utf databases
27 if ($this->_serverinfo['version'] > 401.0) {
29 $aliases = array('iso-8859-1' => 'latin1',
31 //http://dev.mysql.com/doc/mysql/en/charset-connection.html
32 if (isset($aliases[strtolower($charset)])) {
33 // mysql needs special unusual names and doesn't resolve aliases
34 mysql_query("SET NAMES '". $aliases[$charset] . "'");
36 mysql_query("SET NAMES '$charset'");
43 * Kill timed out processes. ( so far only called on about every 50-th save. )
46 if (empty($this->_dbparams['timeout'])) return;
47 $result = mysql_query("SHOW processlist");
48 while ($row = mysql_fetch_array($result)) {
49 if ($row["db"] == $this->_dbh->dsn['database']
50 and $row["User"] == $this->_dbh->dsn['username']
51 and $row["Time"] > $this->_dbparams['timeout']
52 and $row["Command"] == "Sleep")
54 $process_id = $row["Id"];
55 mysql_query("KILL $process_id");
61 * Create a new revision of a page.
63 function set_versiondata($pagename, $version, $data) {
65 $version_tbl = $this->_table_names['version_tbl'];
67 $minor_edit = (int) !empty($data['is_minor_edit']);
68 unset($data['is_minor_edit']);
70 $mtime = (int)$data['mtime'];
71 unset($data['mtime']);
72 assert(!empty($mtime));
74 @$content = (string) $data['%content'];
75 unset($data['%content']);
76 unset($data['%pagedata']);
79 $id = $this->_get_pageid($pagename, true);
80 // requires PRIMARY KEY (id,version)!
81 // VALUES supported since mysql-3.22.5
82 $dbh->query(sprintf("REPLACE INTO $version_tbl"
83 . " (id,version,mtime,minor_edit,content,versiondata)"
84 . " VALUES(%d,%d,%d,%d,'%s','%s')",
85 $id, $version, $mtime, $minor_edit,
86 $dbh->escapeSimple($content),
87 $dbh->escapeSimple($this->_serialize($data))
89 // real binding (prepare,execute) only since mysqli + PHP5
90 $this->_update_recent_table($id);
91 $this->_update_nonempty_table($id);
95 function _update_recent_table($pageid = false) {
97 extract($this->_table_names);
98 extract($this->_expressions);
100 $pageid = (int)$pageid;
102 // optimized: mysql can do this with one REPLACE INTO.
103 // supported in every (?) mysql version
104 // requires PRIMARY KEY (id)!
105 $dbh->query("REPLACE INTO $recent_tbl"
106 . " (id, latestversion, latestmajor, latestminor)"
107 . " SELECT id, $maxversion, $maxmajor, $maxminor"
108 . " FROM $version_tbl"
109 . ( $pageid ? " WHERE id=$pageid" : "")
113 /* // REPLACE will not delete empy pages, so it was removed --ru
114 function _update_nonempty_table($pageid = false) {
116 extract($this->_table_names);
118 $pageid = (int)$pageid;
120 // Optimized: mysql can do this with one REPLACE INTO.
121 // supported in every (?) mysql version
122 // requires PRIMARY KEY (id)
123 $dbh->query("REPLACE INTO $nonempty_tbl (id)"
124 . " SELECT $recent_tbl.id"
125 . " FROM $recent_tbl, $version_tbl"
126 . " WHERE $recent_tbl.id=$version_tbl.id"
127 . " AND version=latestversion"
129 . ( $pageid ? " AND $recent_tbl.id=$pageid" : ""));
136 function optimize() {
139 foreach ($this->_table_names as $table) {
140 $dbh->query("OPTIMIZE TABLE $table");
148 function _lock_tables($write_lock = true) {
149 $lock_type = $write_lock ? "WRITE" : "READ";
150 foreach ($this->_table_names as $table) {
151 $tables[] = "$table $lock_type";
153 $this->_dbh->query("LOCK TABLES " . join(",", $tables));
159 function _unlock_tables() {
160 $this->_dbh->query("UNLOCK TABLES");
163 function increaseHitCount($pagename) {
165 // Hits is the only thing we can update in a fast manner.
166 // Note that this will fail silently if the page does not
167 // have a record in the page table. Since it's just the
168 // hit count, who cares?
170 $dbh->query(sprintf("UPDATE LOW_PRIORITY %s SET hits=hits+1 WHERE pagename='%s' %s",
171 $this->_table_names['page_tbl'],
172 $dbh->escapeSimple($pagename),
173 ($this->_serverinfo['version'] >= 323.0) ? "LIMIT 1": ""));
179 class WikiDB_backend_PearDB_mysql_search
180 extends WikiDB_backend_PearDB_search
182 function _pagename_match_clause($node) {
183 $word = $node->sql();
184 if ($node->op == 'REGEX') { // posix regex extensions
185 return "pagename REGEXP '$word'";
187 return ($this->_case_exact
188 ? "pagename LIKE '$word'"
189 : "LOWER(pagename) LIKE '$word'");
194 // (c-file-style: "gnu")
199 // c-hanging-comment-ender-p: nil
200 // indent-tabs-mode: nil