root/dev/common/includes/class.db_memcache.php @ 391

Revision 391, 6.4 KB (checked in by kovell, 11 years ago)

Fixes: kill_detail comment posting works and non-existent kll_id gives correct error, t3 subsystems have correct location, potential conflicts with old mods and db classes removed.

Line 
1<?php
2
3require_once('db.php');
4
5class DBMemcachedQuery
6{
7    function DBMemcachedQuery()
8    {
9        static $totalexectime = 0;
10                $this->totalexectime_ = &$totalexectime;
11        $this->executed_ = false;
12        $this->_cache = array();
13        $this->_cached = false;
14
15        // this is the minimum runtime a query has to run to be
16        // eligible for caching in seconds
17        $this->_minruntime = 0.1;
18
19        // maximum size of a cached result set (1MB)
20        $this->_maxcachesize = 1048576;
21        $this->d = true;
22    }
23
24    function checkCache()
25    {
26        global $mc;
27
28        // only cache selects
29        // we don't use select ... into so there is no problem
30        $this->_sql = str_replace(array("\r\n", "\n"), ' ', $this->_sql);
31        if (strtolower(substr($this->_sql, 0, 6)) != 'select' && strtolower(substr($this->_sql, 0, 4)) != 'show')
32            return false;
33
34        $cached = $mc->get(KB_SITE . '_sql_' . $this->_hash);
35        if($cached) {
36            return true;
37        }
38
39        return false;
40    }
41
42    function parseSQL()
43    {
44        // gets all involved tables for a select statement
45        $text = strtolower($this->_sql).' ';
46
47        // we try to get the text from 'from' to 'where' because all involved
48        // tables are declared in that part
49        $from = strpos($text, 'from')+5;
50        if (!$to = strpos($text, 'where'))
51        {
52            $to = strlen($text);
53        }
54        $parse = trim(substr($text, $from, $to-$from));
55
56        $tables = array();
57        if (strpos($parse, ',') !== false)
58        {
59            // , is a synonym for join so we'll replace them
60            $parse = str_replace(',', ' join ', $parse);
61        }
62
63        $parse = 'join '.$parse;
64        if (strpos($parse, 'join'))
65        {
66            // if this query is a join we parse it with regexp to get all tables
67            preg_match_all('/join (.*?) /', $parse, $match);
68            $tables = $match[1];
69        }
70        else
71        {
72            // no join so it is hopefully a simple table select
73            $tables[] = $parse;
74        }
75
76        $this->_usedtables = $tables;
77    }
78
79    function genCache()
80    {
81        global $mc;
82
83        // this function fetches all rows and writes the data into a textfile
84
85        // don't attemp to cache updates!
86        if (strtolower(substr($this->_sql, 0, 6)) != 'select' && strtolower(substr($this->_sql, 0, 4)) != 'show')
87        {
88            return false;
89        }
90
91        $bsize = 0;
92        while ($row = $this->getRow())
93        {
94            $this->_cache[] = $row;
95
96            $bsize += strlen(join('', $row));
97            if ($bsize > $this->_maxcachesize)
98            {
99                $this->_cache[] = array();
100                $this->_cached = false;
101                $this->rewind();
102                return false;
103            }
104
105        }
106
107        // write data into textfile
108        $mc->set(KB_SITE . '_sql_' . $this->_hash, $this->_cache, 0, 600);
109
110        $this->_cached = true;
111        $this->_currrow = 0;
112        $this->executed_ = true;
113    }
114
115    function execute($sql)
116    {
117        global $mc; 
118
119        $this->_sql = trim($sql);
120        $this->_hash = md5($this->_sql);
121        $this->_cache = array();
122        $this->_cached = false;
123
124        $cached = $mc->get(KB_SITE . '_sql_' . $this->_hash);
125        if($cached) {
126            $this->_cache = $cached;
127            $this->_cached = true;
128            $this->_currrow = 0;
129            $this->executed_ = true;
130            $this->queryCachedCount(true);
131            return true;
132        }
133
134        // we got no or no valid cache so open the connection and run the query
135        $this->dbconn_ = new DBConnection;
136
137        $t1 = strtok(microtime(), ' ') + strtok('');
138
139        $this->resid_ = mysql_query($sql, $this->dbconn_->id());
140
141        if ($this->resid_ === false)
142        {
143            if(defined('KB_PROFILE'))
144                        {
145                                DBDebug::recordError("Database error: ".$this->dbconn_->id()->error);
146                                DBDebug::recordError("SQL: ".$this->_sql);
147                        }
148            if (DB_HALTONERROR === true)
149            {
150                echo "Database error: ".mysql_error($this->dbconn_->id())."<br/>";
151                echo "SQL: ".$this->_sql."<br/>";
152                exit;
153            }
154            else
155            {
156                return false;
157            }
158        }
159
160        $this->exectime_ = strtok(microtime(), ' ') + strtok('') - $t1;
161        $this->totalexectime_ += $this->exectime_;
162        $this->executed_ = true;
163
164        if (KB_PROFILE == 2)
165        {
166            file_put_contents('/tmp/profile.lst', $sql."\nExecution time: ".$this->exectime_."\n", FILE_APPEND);
167        }
168
169        // if the query was too slow we'll fetch all rows and run it cached
170        $this->genCache();
171
172        $this->queryCount(true);
173        return true;
174    }
175
176    function queryCount($increase = false)
177    {
178        static $count;
179
180        if ($increase)
181        {
182            $count++;
183        }
184
185        return $count;
186    }
187
188    function queryCachedCount($increase = false)
189    {
190        static $count;
191
192        if ($increase)
193        {
194            $count++;
195        }
196
197        return $count;
198    }
199
200    function recordCount()
201    {
202        if ($this->_cached)
203        {
204            return count($this->_cache);
205        }
206        return mysql_num_rows($this->resid_);
207    }
208
209    function getRow()
210    {
211        if ($this->_cached)
212        {
213            if (!isset($this->_cache[$this->_currrow]))
214            {
215                return false;
216            }
217            // return the current row and increase the pointer by one
218            return $this->_cache[$this->_currrow++];
219        }
220        if (is_resource($this->resid_))
221        {
222            return mysql_fetch_assoc($this->resid_);
223        }
224        return false;
225    }
226
227    function rewind()
228    {
229        if ($this->_cached)
230        {
231            $this->_currrow = 0;
232        }
233        @mysql_data_seek($this->resid_, 0);
234    }
235
236    function getInsertID()
237    {
238        return mysql_insert_id();
239    }
240
241    function execTime()
242    {
243        return $this->exectime_;
244    }
245
246    function executed()
247    {
248        return $this->executed_;
249    }
250
251    function getErrorMsg()
252    {
253        $msg = $this->sql_."<br>";
254        $msg .= "Query failed. ".mysql_error($this->dbconn_->id());
255
256        return $msg;
257    }
258    //Not implemented with mysql library
259    function autocommit($commit = true)
260    {
261        return false;
262    }
263   
264    //Not implemented with mysql library
265    function rollback()
266    {
267        return false;
268    }
269}
270?>
Note: See TracBrowser for help on using the browser.