]> CyberLeo.Net >> Repos - SourceForge/phpwiki.git/blob - lib/WikiDB/backend/ADODB_mysql.php
mysql charsets: mysql needs different names and doesn't resolve aliases
[SourceForge/phpwiki.git] / lib / WikiDB / backend / ADODB_mysql.php
1 <?php // -*-php-*-
2 rcs_id('$Id: ADODB_mysql.php,v 1.14 2005-04-01 14:32:44 rurban Exp $');
3
4 require_once('lib/WikiDB/backend/ADODB.php');
5
6 /*
7  * PROBLEM: mysql seems to be the simpliest (or most stupid) db on earth. 
8  * (tested with 4.0.18)
9  * Whenever a table is write-locked, you cannot even write to other unrelated 
10  * tables. So it seems that we have to lock all tables!
11  * As workaround we try it with application locks, uniquely named locks, 
12  * to prevent from concurrent writes of locks with the same name.
13  * The lock name is a strcat of the involved tables.
14  */
15 define('DO_APP_LOCK',true);
16 define('DO_FULL_LOCK',false);
17
18 /**
19  * WikiDB layer for ADODB-mysql, called by lib/WikiDB/ADODB.php.
20  * Now with support for the newer adodb library, the adodb extension library 
21  * and more database drivers.
22  * To use transactions use the mysqlt driver: "mysqlt:..."
23  * 
24  * @author: Lawrence Akka, Reini Urban
25  */
26 class WikiDB_backend_ADODB_mysql
27 extends WikiDB_backend_ADODB
28 {
29     /**
30      * Constructor.
31      */
32     function WikiDB_backend_ADODB_mysql($dbparams) {
33         $this->WikiDB_backend_ADODB($dbparams);
34
35         $this->_serverinfo = $this->_dbh->ServerInfo();
36         if (!empty($this->_serverinfo['version'])) {
37             $arr = explode('.',$this->_serverinfo['version']);
38             $this->_serverinfo['version'] = (string)(($arr[0] * 100) + $arr[1]) . "." . (integer)$arr[2];
39         }
40         if ($this->_serverinfo['version'] < 323.0) {
41             // Older MySQL's don't have CASE WHEN ... END
42             $this->_expressions['maxmajor'] = "MAX(IF(minor_edit=0,version,0))";
43             $this->_expressions['maxminor'] = "MAX(IF(minor_edit<>0,version,0))";
44         }
45
46         // esp. needed for utf databases
47         if ($this->_serverinfo['version'] > 401.0) {
48             global $charset;
49             //http://dev.mysql.com/doc/mysql/en/charset-connection.html
50             if (strtolower($charset) == 'iso-8859-1') {
51                 // mysql needs different names and doesn't resolve aliases
52                 mysql_query("SET NAMES 'latin1'");
53                 //mysql_query("SET CHARACTER SET latin1");
54             } else {
55                 //SET NAMES 'latin1' or 'utf8'
56                 mysql_query("SET NAMES '$charset'");
57             }
58         }
59     }
60     
61     /**
62      * Kill timed out processes. ( so far only called on about every 50-th save. )
63      */
64     function _timeout() {
65         if (empty($this->_dbparams['timeout'])) return;
66         $result = mysql_query("SHOW processlist");
67         while ($row = mysql_fetch_array($result)) { 
68             if ($row["db"] == $this->_dsn['database']
69                 and $row["User"] == $this->_dsn['username']
70                 and $row["Time"] > $this->_dbparams['timeout']
71                 and $row["Command"] == "Sleep")
72             {
73                 $process_id = $row["Id"]; 
74                 mysql_query("KILL $process_id");
75             }
76         }
77     }
78
79     /**
80      * Pack tables.
81      */
82     function optimize() {
83         $dbh = &$this->_dbh;
84         $this->_timeout();
85         foreach ($this->_table_names as $table) {
86             $dbh->Execute("OPTIMIZE TABLE $table");
87         }
88         return 1;
89     }
90
91     /**
92      * Lock tables. As fine-grained application lock, which locks only the same transaction
93      * (conflicting updates and edits), and as full table write lock.
94      *
95      * New: which tables as params,
96      *      support nested locks via app locks
97      *
98      */
99     function _lock_tables($tables, $write_lock = true) {
100         if (!$tables) return;
101         if (DO_APP_LOCK) {
102             $lock = join('-',$tables);
103             $result = $this->_dbh->GetRow("SELECT GET_LOCK('$lock',10)");
104             if (!$result or $result[0] == 0) {
105                 trigger_error( "WARNING: Couldn't obtain application lock " . $lock . "\n<br />",
106                                E_USER_WARNING);
107                 return;                          
108             }
109         }
110         if (DO_FULL_LOCK) {
111             // if this is not enough:
112             $lock_type = $write_lock ? "WRITE" : "READ";
113             foreach ($this->_table_names as $key => $table) {
114                 $locks[] = "$table $lock_type";
115             }
116             $this->_dbh->Execute("LOCK TABLES " . join(",", $locks));
117         }
118     }
119
120     /**
121      * Release the locks.
122      * Support nested locks
123      */
124     function _unlock_tables($tables) {
125         if (!$tables) {
126             $this->_dbh->Execute("UNLOCK TABLES");
127             return;
128         }
129         if (DO_APP_LOCK) {
130             $lock = join('-',$tables);
131             $result = $this->_dbh->Execute("SELECT RELEASE_LOCK('$lock')");
132         }
133         if (DO_FULL_LOCK) {
134             // if this is not enough:
135             $this->_dbh->Execute("UNLOCK TABLES");
136         }
137     }
138
139     function increaseHitCount($pagename) {
140         $dbh = &$this->_dbh;
141         // Hits is the only thing we can update in a fast manner.
142         // Note that this will fail silently if the page does not
143         // have a record in the page table.  Since it's just the
144         // hit count, who cares?
145         // LIMIT since 3.23
146         $dbh->Execute(sprintf("UPDATE LOW_PRIORITY %s SET hits=hits+1 WHERE pagename=%s %s",
147                               $this->_table_names['page_tbl'],
148                               $dbh->qstr($pagename),
149                               ($this->_serverinfo['version'] >= 323.0) ? "LIMIT 1": "")
150                               );
151         return;
152     }
153
154 };
155
156 // (c-file-style: "gnu")
157 // Local Variables:
158 // mode: php
159 // tab-width: 8
160 // c-basic-offset: 4
161 // c-hanging-comment-ender-p: nil
162 // indent-tabs-mode: nil
163 // End:   
164 ?>