1 <?php
2 3 4 5 6 7 8 9 10
11
12
13 14 15 16 17
18 class Neevo implements INeevoObservable, INeevoObserver {
19
20
21
22 public static $defaultDriver = 'mysqli';
23
24
25 private $last;
26
27
28 private $queries = 0;
29
30
31 private $connection;
32
33
34 private $observers;
35
36
37
38 const VERSION = '1.3',
39 REVISION = '@VCREV@ released on @VCDATE@';
40
41
42 const BOOL = 'b',
43 INT = 'i',
44 FLOAT = 'f',
45 TEXT = 's',
46 BINARY = 'bin',
47 DATETIME = 'd',
48 ARR = 'a',
49 LITERAL = 'l',
50 IDENTIFIER = 'id',
51 SUBQUERY = 'sub';
52
53
54 const STMT_SELECT = 'stmt_select',
55 STMT_INSERT = 'stmt_insert',
56 STMT_UPDATE = 'stmt_update',
57 STMT_DELETE = 'stmt_delete';
58
59
60 const JOIN_LEFT = 'join_left',
61 JOIN_INNER = 'join_inner';
62
63
64 const ASC = 'ASC',
65 DESC = 'DESC';
66
67
68 69 70 71 72 73 74 75
76 public function __construct($config, INeevoCache $cache = null){
77 $this->connection = new NeevoConnection($config, $cache);
78 $this->observers = new NeevoObserverMap;
79 $this->attachObserver($this, self::QUERY);
80 }
81
82
83
84
85
86 87 88 89 90 91
92 public function select($columns = null, $table = null){
93 $result = new NeevoResult($this->connection, $columns, $table);
94 foreach($this->observers as $observer){
95 $result->attachObserver($observer, $this->observers->getEvent());
96 }
97 return $result;
98 }
99
100
101 102 103 104 105 106
107 public function insert($table, array $values){
108 $statement = NeevoStmt::createInsert($this->connection, $table, $values);
109 foreach($this->observers as $observer){
110 $statement->attachObserver($observer, $this->observers->getEvent());
111 }
112 return $statement;
113 }
114
115
116 117 118 119 120 121
122 public function update($table, array $data){
123 $statement = NeevoStmt::createUpdate($this->connection, $table, $data);
124 foreach($this->observers as $observer){
125 $statement->attachObserver($observer, $this->observers->getEvent());
126 }
127 return $statement;
128 }
129
130
131 132 133 134 135
136 public function delete($table){
137 $statement = NeevoStmt::createDelete($this->connection, $table);
138 foreach($this->observers as $observer){
139 $statement->attachObserver($observer, $this->observers->getEvent());
140 }
141 return $statement;
142 }
143
144
145 146 147 148 149 150 151 152 153
154 public function loadFile($filename){
155 $this->connection->connect();
156 $abort = ignore_user_abort();
157 @set_time_limit(0);
158 ignore_user_abort(true);
159
160 $handle = @fopen($filename, 'r');
161 if($handle === false){
162 ignore_user_abort($abort);
163 throw new NeevoException("Cannot open file '$filename' for SQL import.");
164 }
165
166 $sql = '';
167 $count = 0;
168 while(!feof($handle)){
169 $content = fgets($handle);
170 $sql .= $content;
171 if(substr(rtrim($content), -1) === ';'){
172
173 $this->connection->getDriver()->runQuery($sql);
174 $sql = '';
175 $count++;
176 }
177 }
178 fclose($handle);
179 ignore_user_abort($abort);
180 return $count;
181 }
182
183
184
185
186
187 188 189 190 191
192 public function begin($savepoint = null){
193 $this->connection->getDriver()->beginTransaction($savepoint);
194 $this->notifyObservers(INeevoObserver::BEGIN);
195 return $this;
196 }
197
198
199 200 201 202 203
204 public function commit($savepoint = null){
205 $this->connection->getDriver()->commit($savepoint);
206 $this->notifyObservers(INeevoObserver::COMMIT);
207 return $this;
208 }
209
210
211 212 213 214 215
216 public function rollback($savepoint = null){
217 $this->connection->getDriver()->rollback($savepoint);
218 $this->notifyObservers(INeevoObserver::ROLLBACK);
219 return $this;
220 }
221
222
223
224
225
226 227 228 229 230 231
232 public function attachObserver(INeevoObserver $observer, $event){
233 $this->observers->attach($observer, $event);
234 $this->connection->attachObserver($observer, $event);
235 $e = new NeevoException;
236 $e->attachObserver($observer, $event);
237 }
238
239
240 241 242 243 244
245 public function detachObserver(INeevoObserver $observer){
246 $this->connection->detachObserver($observer);
247 $this->observers->detach($observer);
248 $e = new NeevoException;
249 $e->detachObserver($observer);
250 }
251
252
253 254 255 256 257
258 public function notifyObservers($event){
259 foreach($this->observers as $observer){
260 if($event & $this->observers->getEvent())
261 $observer->updateStatus($this, $event);
262 }
263 }
264
265
266 267 268 269 270 271
272 public function updateStatus(INeevoObservable $observable, $event){
273 $this->last = $observable->__toString();
274 ++$this->queries;
275 }
276
277
278 279 280 281
282 public function getConnection(){
283 return $this->connection;
284 }
285
286
287 288 289 290
291 public function getLast(){
292 return $this->last;
293 }
294
295
296 297 298 299
300 public function getQueries(){
301 return $this->queries;
302 }
303
304
305 306 307 308 309
310 public static function highlightSql($sql){
311 $keywords1 = 'SELECT|UPDATE|INSERT\s+INTO|DELETE|FROM|VALUES|SET|WHERE|HAVING|GROUP\s+BY|ORDER\s+BY|LIMIT|OFFSET|(?:LEFT |RIGHT |INNER )?JOIN';
312 $keywords2 = 'RANDOM|RAND|ASC|DESC|USING|AND|OR|ON|IN|IS|NOT|NULL|LIKE|TRUE|FALSE|AS';
313
314 $sql = str_replace("\\'", '\\'', $sql);
315 $sql = preg_replace_callback("~(/\\*.*\\*/)|($keywords1)|($keywords2)|('[^']+'|[0-9]+)~", array('Neevo', '_highlightCallback'), $sql);
316 $sql = str_replace('\\'', "\\'", $sql);
317 return '<pre style="color:#555" class="sql-dump">' . trim($sql) . "</pre>\n";
318 }
319
320
321 private static function _highlightCallback($match){
322
323 if(!empty($match[1]))
324 return '<em style="color:#999">' . $match[1] . '</em>';
325
326 if(!empty($match[2]))
327 return "\n" . '<strong style="color:#e71818">' . $match[2] . '</strong>';
328
329 if(!empty($match[3]))
330 return '<strong style="color:#d59401">' . $match[3] . '</strong>';
331
332 if(!empty($match[4]) || $match[4] === '0')
333 return '<em style="color:#008000">' . $match[4] . '</em>';
334 }
335
336
337 }
338
339
340
341 342 343 344 345
346 class NeevoLiteral {
347
348
349
350 public $value;
351
352
353 354 355 356 357
358 public function __construct($value) {
359 $this->value = $value;
360 }
361
362
363 }
364