]> CyberLeo.Net >> Repos - SourceForge/phpwiki.git/blob - lib/WikiDB/backend/PearDB_mysql.php
more mysql-4.1 quirks: add utf8 to the charset aliases table. (Bug #1180108)
[SourceForge/phpwiki.git] / lib / WikiDB / backend / PearDB_mysql.php
1 <?php // -*-php-*-
2 rcs_id('$Id: PearDB_mysql.php,v 1.19 2005-04-10 10:43:25 rurban Exp $');
3
4 require_once('lib/WikiDB/backend/PearDB.php');
5
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
10 {
11     /**
12      * Constructor.
13      */
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))";
25             }
26             // esp. needed for utf databases
27             if ($this->_serverinfo['version'] > 401.0) {
28                 global $charset;
29                 $aliases = array('iso-8859-1' => 'latin1',
30                                  'utf-8'      => 'utf8');
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] . "'");
35                 } else {
36                     mysql_query("SET NAMES '$charset'");
37                 }
38             }
39         }
40     }
41     
42     /**
43      * Kill timed out processes. ( so far only called on about every 50-th save. )
44      */
45     function _timeout() {
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") 
53             {
54                     $process_id = $row["Id"]; 
55                     mysql_query("KILL $process_id");
56             }
57         }
58     }
59
60     /**
61      * Create a new revision of a page.
62      */
63     function set_versiondata($pagename, $version, $data) {
64         $dbh = &$this->_dbh;
65         $version_tbl = $this->_table_names['version_tbl'];
66         
67         $minor_edit = (int) !empty($data['is_minor_edit']);
68         unset($data['is_minor_edit']);
69         
70         $mtime = (int)$data['mtime'];
71         unset($data['mtime']);
72         assert(!empty($mtime));
73
74         @$content = (string) $data['%content'];
75         unset($data['%content']);
76         unset($data['%pagedata']);
77         
78         $this->lock();
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))
88                             ));
89         // real binding (prepare,execute) only since mysqli + PHP5
90         $this->_update_recent_table($id);
91         $this->_update_nonempty_table($id);
92         $this->unlock();
93     }
94
95     function _update_recent_table($pageid = false) {
96         $dbh = &$this->_dbh;
97         extract($this->_table_names);
98         extract($this->_expressions);
99
100         $pageid = (int)$pageid;
101
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" : "")
110                     . " GROUP BY id" );
111     }
112
113     /* // REPLACE will not delete empy pages, so it was removed --ru
114     function _update_nonempty_table($pageid = false) {
115         $dbh = &$this->_dbh;
116         extract($this->_table_names);
117
118         $pageid = (int)$pageid;
119
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"
128                     . "  AND content<>''"
129                     . ( $pageid ? " AND $recent_tbl.id=$pageid" : ""));
130     }
131     */
132    
133     /**
134      * Pack tables.
135      */
136     function optimize() {
137         $dbh = &$this->_dbh;
138         $this->_timeout();
139         foreach ($this->_table_names as $table) {
140             $dbh->query("OPTIMIZE TABLE $table");
141         }
142         return 1;
143     }
144
145     /**
146      * Lock tables.
147      */
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";
152         }
153         $this->_dbh->query("LOCK TABLES " . join(",", $tables));
154     }
155
156     /**
157      * Release all locks.
158      */
159     function _unlock_tables() {
160         $this->_dbh->query("UNLOCK TABLES");
161     }
162
163     function increaseHitCount($pagename) {
164         $dbh = &$this->_dbh;
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?
169         // LIMIT since 3.23
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": ""));
174         return;
175     }
176
177 };
178
179 class WikiDB_backend_PearDB_mysql_search
180 extends WikiDB_backend_PearDB_search
181 {
182     function _pagename_match_clause($node) { 
183         $word = $node->sql();
184         if ($node->op == 'REGEX') { // posix regex extensions
185             return "pagename REGEXP '$word'";
186         } else {
187             return ($this->_case_exact 
188                     ? "pagename LIKE '$word'" 
189                     : "LOWER(pagename) LIKE '$word'");
190         }
191     }
192 }
193
194 // (c-file-style: "gnu")
195 // Local Variables:
196 // mode: php
197 // tab-width: 8
198 // c-basic-offset: 4
199 // c-hanging-comment-ender-p: nil
200 // indent-tabs-mode: nil
201 // End:   
202 ?>