0337d704 |
1 | <?php |
2 | /*************************************************************************** |
5ddeb07c |
3 | * Copyright (C) 2003-2007 Polytechnique.org * |
0337d704 |
4 | * http://opensource.polytechnique.org/ * |
5 | * * |
6 | * This program is free software; you can redistribute it and/or modify * |
7 | * it under the terms of the GNU General Public License as published by * |
8 | * the Free Software Foundation; either version 2 of the License, or * |
9 | * (at your option) any later version. * |
10 | * * |
11 | * This program is distributed in the hope that it will be useful, * |
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * |
14 | * GNU General Public License for more details. * |
15 | * * |
16 | * You should have received a copy of the GNU General Public License * |
17 | * along with this program; if not, write to the Free Software * |
18 | * Foundation, Inc., * |
19 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * |
20 | **************************************************************************/ |
21 | |
08cce2ff |
22 | class XDB |
0337d704 |
23 | { |
32d9ae72 |
24 | private static $mysqli = null; |
25 | |
821744e0 |
26 | public static function connect() |
32d9ae72 |
27 | { |
821744e0 |
28 | global $globals; |
29 | XDB::$mysqli = new mysqli($globals->dbhost, $globals->dbuser, $globals->dbpwd, $globals->dbdb); |
d3f26be9 |
30 | if ($globals->debug & 1) { |
31 | $bt = new PlBacktrace('MySQL'); |
32 | if (mysqli_connect_errno()) { |
33 | $bt->newEvent("MySQLI connection", 0, mysqli_connect_error()); |
34 | return false; |
35 | } |
32d9ae72 |
36 | } |
37 | XDB::$mysqli->autocommit(true); |
821744e0 |
38 | XDB::$mysqli->set_charset($globals->dbcharset); |
32d9ae72 |
39 | return true; |
40 | } |
f1ca33de |
41 | |
ed3f4d3e |
42 | public static function _prepare($args) |
43 | { |
08cce2ff |
44 | $query = array_map(Array('XDB', '_db_escape'), $args); |
0337d704 |
45 | $query[0] = str_replace('{?}', '%s', str_replace('%', '%%', $args[0])); |
46 | return call_user_func_array('sprintf', $query); |
47 | } |
13a25546 |
48 | |
6995a9b9 |
49 | public static function _reformatQuery($query) |
7c571120 |
50 | { |
a4f89886 |
51 | $query = preg_split("/\n\\s*/", trim($query)); |
7c571120 |
52 | $length = 0; |
d3c52d30 |
53 | foreach ($query as $key=>$line) { |
54 | $local = -2; |
a14159bf |
55 | if (preg_match('/^([A-Z]+(?:\s+(?:JOIN|BY|FROM|INTO))?)\s+(.*)/u', $line, $matches) |
85d3b330 |
56 | && $matches[1] != 'AND' && $matches[1] != 'OR') |
57 | { |
d3c52d30 |
58 | $local = strlen($matches[1]); |
59 | $line = $matches[1] . ' ' . $matches[2]; |
60 | $length = max($length, $local); |
7c571120 |
61 | } |
d3c52d30 |
62 | $query[$key] = array($line, $local); |
7c571120 |
63 | } |
64 | $res = ''; |
d3c52d30 |
65 | foreach ($query as $array) { |
66 | list($line, $local) = $array; |
9630c649 |
67 | $local = max(0, $length - $local); |
7c571120 |
68 | $res .= str_repeat(' ', $local) . $line . "\n"; |
69 | $length += 2 * (substr_count($line, '(') - substr_count($line, ')')); |
70 | } |
71 | return $res; |
72 | } |
73 | |
ed3f4d3e |
74 | public static function _query($query) |
75 | { |
f1ca33de |
76 | global $globals; |
77 | |
821744e0 |
78 | if (!XDB::$mysqli && !XDB::connect()) { |
79 | return false; |
80 | } |
81 | |
5fb22b39 |
82 | if ($globals->debug & 1) { |
f1ca33de |
83 | $explain = array(); |
5fb22b39 |
84 | if (strpos($query, 'FOUND_ROWS()') === false) { |
32d9ae72 |
85 | $res = XDB::$mysqli->query("EXPLAIN $query"); |
86 | if ($res) { |
87 | while ($row = $res->fetch_assoc()) { |
5fb22b39 |
88 | $explain[] = $row; |
89 | } |
32d9ae72 |
90 | $res->free(); |
5fb22b39 |
91 | } |
f1ca33de |
92 | } |
d3f26be9 |
93 | PlBacktrace::$bt['MySQL']->start(XDB::_reformatQuery($query)); |
f1ca33de |
94 | } |
95 | |
32d9ae72 |
96 | $res = XDB::$mysqli->query($query); |
0381e170 |
97 | |
f1ca33de |
98 | if ($globals->debug & 1) { |
d3f26be9 |
99 | PlBacktrace::$bt['MySQL']->stop(@$res->num_rows ? $res->num_rows : XDB::$mysqli->affected_rows, |
100 | XDB::$mysqli->error, |
101 | $explain); |
f1ca33de |
102 | } |
f1ca33de |
103 | return $res; |
104 | } |
105 | |
6995a9b9 |
106 | public static function query() |
0337d704 |
107 | { |
08cce2ff |
108 | return new XOrgDBResult(XDB::_prepare(func_get_args())); |
0337d704 |
109 | } |
110 | |
6995a9b9 |
111 | public static function execute() |
f1ca33de |
112 | { |
113 | return XDB::_query(XDB::_prepare(func_get_args())); |
0337d704 |
114 | } |
13a25546 |
115 | |
6995a9b9 |
116 | public static function iterator() |
0337d704 |
117 | { |
08cce2ff |
118 | return new XOrgDBIterator(XDB::_prepare(func_get_args())); |
0337d704 |
119 | } |
13a25546 |
120 | |
6995a9b9 |
121 | public static function iterRow() |
0337d704 |
122 | { |
08cce2ff |
123 | return new XOrgDBIterator(XDB::_prepare(func_get_args()), MYSQL_NUM); |
0337d704 |
124 | } |
13a25546 |
125 | |
6995a9b9 |
126 | public static function insertId() |
13a25546 |
127 | { |
32d9ae72 |
128 | return XDB::$mysqli->insert_id; |
13a25546 |
129 | } |
130 | |
0380bf85 |
131 | public static function errno() |
132 | { |
0380bf85 |
133 | return XDB::$mysqli->errno; |
134 | } |
135 | |
136 | public static function error() |
137 | { |
0380bf85 |
138 | return XDB::$mysqli->error; |
139 | } |
140 | |
141 | public static function affectedRows() |
142 | { |
143 | return XDB::$mysqli->affected_rows; |
144 | } |
145 | |
6995a9b9 |
146 | public static function _db_escape($var) |
0337d704 |
147 | { |
148 | switch (gettype($var)) { |
13a25546 |
149 | case 'boolean': |
150 | return $var ? 1 : 0; |
151 | |
152 | case 'integer': |
153 | case 'double': |
154 | case 'float': |
155 | return $var; |
156 | |
157 | case 'string': |
158 | return "'".addslashes($var)."'"; |
159 | |
160 | case 'NULL': |
161 | return 'NULL'; |
162 | |
163 | case 'object': |
164 | case 'array': |
165 | return "'".addslashes(serialize($var))."'"; |
166 | |
167 | default: |
168 | die(var_export($var, true).' is not a valid for a database entry'); |
0337d704 |
169 | } |
170 | } |
0337d704 |
171 | } |
172 | |
0337d704 |
173 | class XOrgDBResult |
174 | { |
0337d704 |
175 | |
32d9ae72 |
176 | private $_res; |
0337d704 |
177 | |
0381e170 |
178 | public function __construct($query) |
0337d704 |
179 | { |
755abda6 |
180 | $this->_res = XDB::_query($query); |
0337d704 |
181 | } |
182 | |
0381e170 |
183 | public function free() |
0337d704 |
184 | { |
0381e170 |
185 | if ($this->_res) { |
186 | $this->_res->free(); |
187 | } |
0337d704 |
188 | unset($this); |
189 | } |
190 | |
0381e170 |
191 | protected function _fetchRow() |
0337d704 |
192 | { |
0381e170 |
193 | return $this->_res ? $this->_res->fetch_row() : null; |
0337d704 |
194 | } |
195 | |
0381e170 |
196 | protected function _fetchAssoc() |
0337d704 |
197 | { |
0381e170 |
198 | return $this->_res ? $this->_res->fetch_assoc() : null; |
0337d704 |
199 | } |
200 | |
0381e170 |
201 | public function fetchAllRow() |
0337d704 |
202 | { |
203 | $result = Array(); |
0381e170 |
204 | if (!$this->_res) { |
205 | return $result; |
206 | } |
32d9ae72 |
207 | while ($result[] = $this->_res->fetch_row()); |
0337d704 |
208 | array_pop($result); |
209 | $this->free(); |
210 | return $result; |
211 | } |
212 | |
0381e170 |
213 | public function fetchAllAssoc() |
0337d704 |
214 | { |
215 | $result = Array(); |
0381e170 |
216 | if (!$this->_res) { |
217 | return $result; |
218 | } |
32d9ae72 |
219 | while ($result[] = $this->_res->fetch_assoc()); |
0337d704 |
220 | array_pop($result); |
221 | $this->free(); |
222 | return $result; |
223 | } |
224 | |
0381e170 |
225 | public function fetchOneAssoc() |
0337d704 |
226 | { |
227 | $tmp = $this->_fetchAssoc(); |
228 | $this->free(); |
229 | return $tmp; |
230 | } |
231 | |
0381e170 |
232 | public function fetchOneRow() |
0337d704 |
233 | { |
234 | $tmp = $this->_fetchRow(); |
235 | $this->free(); |
236 | return $tmp; |
237 | } |
238 | |
0381e170 |
239 | public function fetchOneCell() |
0337d704 |
240 | { |
241 | $tmp = $this->_fetchRow(); |
242 | $this->free(); |
243 | return $tmp[0]; |
244 | } |
245 | |
0381e170 |
246 | public function fetchColumn($key = 0) |
0337d704 |
247 | { |
248 | $res = Array(); |
249 | if (is_numeric($key)) { |
250 | while($tmp = $this->_fetchRow()) { |
251 | $res[] = $tmp[$key]; |
252 | } |
253 | } else { |
254 | while($tmp = $this->_fetchAssoc()) { |
255 | $res[] = $tmp[$key]; |
256 | } |
257 | } |
258 | $this->free(); |
259 | return $res; |
260 | } |
261 | |
0381e170 |
262 | public function fetchOneField() |
0380bf85 |
263 | { |
0381e170 |
264 | return $this->_res ? $this->_res->fetch_field() : null; |
0380bf85 |
265 | } |
266 | |
0381e170 |
267 | public function fetchFields() |
0380bf85 |
268 | { |
269 | $res = array(); |
270 | while ($res[] = $this->fetchOneField()); |
271 | return $res; |
272 | } |
273 | |
0381e170 |
274 | public function numRows() |
0337d704 |
275 | { |
0381e170 |
276 | return $this->_res ? $this->_res->num_rows : 0; |
0337d704 |
277 | } |
0380bf85 |
278 | |
0381e170 |
279 | public function fieldCount() |
0380bf85 |
280 | { |
0381e170 |
281 | return $this->_res ? $this->_res->field_count : 0; |
0380bf85 |
282 | } |
0337d704 |
283 | } |
284 | |
2b1ee50b |
285 | require_once dirname(__FILE__) . '/pliterator.php'; |
286 | |
0381e170 |
287 | class XOrgDBIterator extends XOrgDBResult implements PlIterator |
0337d704 |
288 | { |
85d3b330 |
289 | private $_result; |
290 | private $_pos; |
291 | private $_total; |
0380bf85 |
292 | private $_fpos; |
293 | private $_fields; |
85d3b330 |
294 | private $_mode = MYSQL_ASSOC; |
0337d704 |
295 | |
0381e170 |
296 | public function __construct($query, $mode = MYSQL_ASSOC) |
0337d704 |
297 | { |
0381e170 |
298 | parent::__construct($query); |
0337d704 |
299 | $this->_pos = 0; |
0381e170 |
300 | $this->_total = $this->numRows(); |
0380bf85 |
301 | $this->_fpost = 0; |
0381e170 |
302 | $this->_fields = $this->fieldCount(); |
0337d704 |
303 | $this->_mode = $mode; |
304 | } |
305 | |
0381e170 |
306 | public function next() |
0337d704 |
307 | { |
308 | $this->_pos ++; |
309 | if ($this->_pos > $this->_total) { |
0381e170 |
310 | $this->free(); |
0337d704 |
311 | unset($this); |
312 | return null; |
313 | } |
0381e170 |
314 | return $this->_mode != MYSQL_ASSOC ? $this->_fetchRow() : $this->_fetchAssoc(); |
0337d704 |
315 | } |
316 | |
0381e170 |
317 | public function first() |
0337d704 |
318 | { |
319 | return $this->_pos == 1; |
320 | } |
321 | |
0381e170 |
322 | public function last() |
0337d704 |
323 | { |
0380bf85 |
324 | return $this->_pos == $this->_total; |
0337d704 |
325 | } |
326 | |
0381e170 |
327 | public function total() |
0337d704 |
328 | { |
329 | return $this->_total; |
330 | } |
0380bf85 |
331 | |
0381e170 |
332 | public function nextField() |
0380bf85 |
333 | { |
334 | $this->_fpos++; |
335 | if ($this->_fpos > $this->_fields) { |
336 | return null; |
337 | } |
0381e170 |
338 | return $this->fetchOneField(); |
0380bf85 |
339 | } |
340 | |
0381e170 |
341 | public function firstField() |
0380bf85 |
342 | { |
343 | return $this->_fpos == 1; |
344 | } |
345 | |
0381e170 |
346 | public function lastField() |
0380bf85 |
347 | { |
348 | return $this->_fpos == $this->_fields; |
349 | } |
350 | |
0381e170 |
351 | public function totalFields() |
0380bf85 |
352 | { |
353 | return $this->_fields; |
354 | } |
0337d704 |
355 | } |
356 | |
a7de4ef7 |
357 | // vim:set et sw=4 sts=4 sws=4 foldmethod=marker enc=utf-8: |
0337d704 |
358 | ?> |