]> CyberLeo.Net >> Repos - SourceForge/phpwiki.git/blob - lib/WikiDB/backend/PearDB_mysql.php
new regex search parser and SQL backends (90% complete, glob and pcre backends missing)
[SourceForge/phpwiki.git] / lib / WikiDB / backend / PearDB_mysql.php
1 <?php // -*-php-*-
2 rcs_id('$Id: PearDB_mysql.php,v 1.13 2004-11-26 18:39:02 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         }
27     }
28     
29     /**
30      * Kill timed out processes. ( so far only called on about every 50-th save. )
31      */
32     function _timeout() {
33         if (empty($this->_dbparams['timeout'])) return;
34         $result = mysql_query("SHOW processlist");
35         while ($row = mysql_fetch_array($result)) { 
36             if ($row["db"] == $this->_dbh->dsn['database']
37                 and $row["User"] == $this->_dbh->dsn['username']
38                 and $row["Time"] > $this->_dbparams['timeout']
39                 and $row["Command"] == "Sleep") 
40             {
41                     $process_id = $row["Id"]; 
42                     mysql_query("KILL $process_id");
43             }
44         }
45     }
46
47     /**
48      * Create a new revision of a page.
49      */
50     function set_versiondata($pagename, $version, $data) {
51         $dbh = &$this->_dbh;
52         $version_tbl = $this->_table_names['version_tbl'];
53         
54         $minor_edit = (int) !empty($data['is_minor_edit']);
55         unset($data['is_minor_edit']);
56         
57         $mtime = (int)$data['mtime'];
58         unset($data['mtime']);
59         assert(!empty($mtime));
60
61         @$content = (string) $data['%content'];
62         unset($data['%content']);
63         unset($data['%pagedata']);
64         
65         $this->lock();
66         $id = $this->_get_pageid($pagename, true);
67         // requires PRIMARY KEY (id,version)!
68         // VALUES supported since mysql-3.22.5
69         $dbh->query(sprintf("REPLACE INTO $version_tbl"
70                             . " (id,version,mtime,minor_edit,content,versiondata)"
71                             . " VALUES(%d,%d,%d,%d,'%s','%s')",
72                             $id, $version, $mtime, $minor_edit,
73                             $dbh->escapeSimple($content),
74                             $dbh->escapeSimple($this->_serialize($data))
75                             ));
76         // real binding (prepare,execute) only since mysqli + PHP5
77         $this->_update_recent_table($id);
78         $this->_update_nonempty_table($id);
79         $this->unlock();
80     }
81
82     function _update_recent_table($pageid = false) {
83         $dbh = &$this->_dbh;
84         extract($this->_table_names);
85         extract($this->_expressions);
86
87         $pageid = (int)$pageid;
88
89         // optimized: mysql can do this with one REPLACE INTO.
90         // supported in every (?) mysql version
91         // requires PRIMARY KEY (id)!
92         $dbh->query("REPLACE INTO $recent_tbl"
93                     . " (id, latestversion, latestmajor, latestminor)"
94                     . " SELECT id, $maxversion, $maxmajor, $maxminor"
95                     . " FROM $version_tbl"
96                     . ( $pageid ? " WHERE id=$pageid" : "")
97                     . " GROUP BY id" );
98     }
99
100     function _update_nonempty_table($pageid = false) {
101         $dbh = &$this->_dbh;
102         extract($this->_table_names);
103
104         $pageid = (int)$pageid;
105
106         // Optimized: mysql can do this with one REPLACE INTO.
107         // supported in every (?) mysql version
108         // requires PRIMARY KEY (id)
109         $dbh->query("REPLACE INTO $nonempty_tbl (id)"
110                     . " SELECT $recent_tbl.id"
111                     . " FROM $recent_tbl, $version_tbl"
112                     . " WHERE $recent_tbl.id=$version_tbl.id"
113                     . "       AND version=latestversion"
114                     . "  AND content<>''"
115                     . ( $pageid ? " AND $recent_tbl.id=$pageid" : ""));
116     }
117    
118     /**
119      * Pack tables.
120      */
121     function optimize() {
122         $dbh = &$this->_dbh;
123         $this->_timeout();
124         foreach ($this->_table_names as $table) {
125             $dbh->query("OPTIMIZE TABLE $table");
126         }
127         return 1;
128     }
129
130     /**
131      * Lock tables.
132      */
133     function _lock_tables($write_lock = true) {
134         $lock_type = $write_lock ? "WRITE" : "READ";
135         foreach ($this->_table_names as $table) {
136             $tables[] = "$table $lock_type";
137         }
138         $this->_dbh->query("LOCK TABLES " . join(",", $tables));
139     }
140
141     /**
142      * Release all locks.
143      */
144     function _unlock_tables() {
145         $this->_dbh->query("UNLOCK TABLES");
146     }
147
148     function increaseHitCount($pagename) {
149         $dbh = &$this->_dbh;
150         // Hits is the only thing we can update in a fast manner.
151         // Note that this will fail silently if the page does not
152         // have a record in the page table.  Since it's just the
153         // hit count, who cares?
154         // LIMIT since 3.23
155         $dbh->query(sprintf("UPDATE LOW_PRIORITY %s SET hits=hits+1 WHERE pagename='%s' %s",
156                             $this->_table_names['page_tbl'],
157                             $dbh->escapeSimple($pagename),
158                             ($this->_serverinfo['version'] >= 323.0) ? "LIMIT 1": ""));
159         return;
160     }
161
162 };
163
164 // (c-file-style: "gnu")
165 // Local Variables:
166 // mode: php
167 // tab-width: 8
168 // c-basic-offset: 4
169 // c-hanging-comment-ender-p: nil
170 // indent-tabs-mode: nil
171 // End:   
172 ?>