root/dev/common/class.db_cache.php @ 183

Revision 183, 6.4 KB (checked in by exi, 16 years ago)

Fixed missing t2 icon for items without a II but with the proper techlevel in the database.
Added sql show to the qcache as cacheable entry.
Fixed db.php to really look for the define.

Line 
1<?php
2
3class DBConnection
4{
5    function DBConnection()
6    {
7        if (!$this->id_ = mysql_pconnect(DB_HOST, DB_USER, DB_PASS))
8            die("Unable to connect to mysql database.");
9
10        mysql_select_db(DB_NAME);
11    }
12
13    function id()
14    {
15        return $this->id_;
16    }
17
18    function affectedRows()
19    {
20        return mysql_affected_rows($this->id_);
21    }
22}
23
24class DBQuery
25{
26    function DBQuery()
27    {
28        $this->executed_ = false;
29        $this->_cache = array();
30        $this->_cached = false;
31
32        // this is the minimum runtime a query has to run to be
33        // eligible for caching in seconds
34        $this->_minruntime = 0.1;
35    }
36
37    function checkCache()
38    {
39        // only cache selects
40        // we don't use select ... into so there is no problem
41        if (strtolower(substr($this->_sql, 0, 6)) != 'select' && strtolower(substr($this->_sql, 0, 4)) != 'show')
42        {
43            // this is no select, update the table
44            $this->markAffectedTables();
45            return false;
46        }
47
48        if (file_exists(KB_CACHEDIR.'/qcache_qry_'.$this->_hash))
49        {
50            $this->_mtime = filemtime(KB_CACHEDIR.'/qcache_qry_'.$this->_hash);
51            if ($this->isCacheValid())
52            {
53                return true;
54            }
55        }
56
57        return false;
58    }
59
60    function parseSQL()
61    {
62        // gets all involved tables for a select statement
63        $text = strtolower($this->_sql).' ';
64        $from = strpos($text, 'from')+5;
65        if (!$to = strpos($text, 'where'))
66        {
67            $to = strlen($text);
68        }
69        $parse = trim(substr($text, $from, $to-$from));
70
71        $tables = array();
72        if (strpos($parse, 'join'))
73        {
74            preg_match_all('/join (.*?) /', $parse, $match);
75            $tables = $match[1];
76        }
77        else
78        {
79            $tables[] = $parse;
80        }
81
82        $this->_usedtables = $tables;
83    }
84
85    function isCacheValid()
86    {
87        // check if one of the tables needs to be updated
88
89        // first, we need to get all involved tables
90        $this->parseSQL();
91
92        foreach ($this->_usedtables as $table)
93        {
94            $file = KB_CACHEDIR.'/qcache_tbl_'.$table;
95            if (file_exists($file))
96            {
97                // if one of the tables is outdated, the query is outdated
98                if ($this->_mtime < filemtime($file))
99                {
100                    return false;
101                }
102            }
103        }
104        return true;
105    }
106
107    function markAffectedTables()
108    {
109        // this function invalidates cache files for touched tables
110        $text = trim(strtolower($this->_sql));
111        $ta = explode(' ', $text);
112
113        $tables = array();
114        if ($ta[0] == 'update')
115        {
116            $tables[] = $ta[1];
117        }
118        elseif ($ta[0] == 'insert')
119        {
120            $tables[] = $ta[2];
121        }
122        elseif ($ta[0] == 'replace')
123        {
124            $tables[] = $ta[2];
125        }
126        elseif ($ta[0] == 'delete')
127        {
128            $tables[] = $ta[2];
129        }
130        else
131        {
132            var_dump($ta);
133            trigger_error('No suitable handler for query found.',E_USER_WARNING);
134            return false;
135        }
136
137        foreach ($tables as $table)
138        {
139            $file = KB_CACHEDIR.'/qcache_tbl_'.$table;
140            touch($file);
141        }
142    }
143
144    function genCache()
145    {
146        // this function fetches all rows and writes the data into a textfile
147
148        while ($row = $this->getRow())
149        {
150            $this->_cache[] = $row;
151        }
152
153        // write data into textfile
154        file_put_contents(KB_CACHEDIR.'/qcache_qry_'.$this->_hash, serialize($this->_cache));
155
156        $this->_cached = true;
157        $this->_currrow = 0;
158    }
159
160    function loadCache()
161    {
162        // loads the cachefile into the memory
163        $this->_cache = unserialize(file_get_contents(KB_CACHEDIR.'/qcache_qry_'.$this->_hash));
164
165        $this->_cached = true;
166        $this->_currrow = 0;
167        $this->executed_ = true;
168    }
169
170    function execute($sql)
171    {
172        $this->_sql = $sql;
173        $this->_hash = md5($sql);
174
175        if ($this->checkCache())
176        {
177            $this->loadCache();
178            return true;
179        }
180        $this->dbconn_ = new DBConnection;
181
182        $t1 = strtok(microtime(), ' ') + strtok('');
183
184        $this->resid_ = mysql_query($sql, $this->dbconn_->id());
185
186        if ($this->resid_ == false)
187        {
188            if (defined('DB_HALTONERROR') && DB_HALTONERROR)
189            {
190                echo "Database error: " . mysql_error($this->dbconn_->id()) . "<br>";
191                echo "SQL: " . $sql . "<br>";
192                exit;
193            }
194            else
195            {
196                return false;
197            }
198        }
199
200        $this->exectime_ = strtok(microtime(), ' ') + strtok('') - $t1;
201        $this->executed_ = true;
202
203        if (KB_PROFILE == 2)
204        {
205            file_put_contents('/tmp/profile.lst', $sql . "\nExecution time: " . $this->exectime_ . "\n", FILE_APPEND);
206        }
207
208        if ($this->exectime_ > $this->_minruntime)
209        {
210            $this->genCache();
211        }
212
213        return true;
214    }
215
216    function recordCount()
217    {
218        if ($this->_cached)
219        {
220            return count($this->_cache);
221        }
222        return mysql_num_rows($this->resid_);
223    }
224
225    function getRow()
226    {
227        if ($this->_cached)
228        {
229            // return the current row and increase the pointer by one
230            return $this->_cache[$this->_currrow++];
231        }
232        if ($this->resid_)
233        {
234            return mysql_fetch_assoc($this->resid_);
235        }
236        return false;
237    }
238
239    function rewind()
240    {
241        if ($this->_cached)
242        {
243            $this->_currrow = 0;
244        }
245        @mysql_data_seek($this->resid_, 0);
246    }
247
248    function getInsertID()
249    {
250        return mysql_insert_id();
251    }
252
253    function execTime()
254    {
255        return $this->exectime_;
256    }
257
258    function executed()
259    {
260        return $this->executed_;
261    }
262
263    function getErrorMsg()
264    {
265        $msg = $this->sql_ . "<br>";
266        $msg .= "Query failed. " . mysql_error($this->dbconn_->id());
267
268        return $msg;
269    }
270}
271?>
Note: See TracBrowser for help on using the browser.