PageRenderTime 30ms CodeModel.GetById 14ms app.highlight 11ms RepoModel.GetById 1ms app.codeStats 1ms

/phpmyadmin/libraries/dbi/drizzle-wrappers.lib.php

https://bitbucket.org/adarshj/convenient_website
PHP | 442 lines | 208 code | 29 blank | 205 comment | 19 complexity | 39b20081100b008253179e9d9eee08f1 MD5 | raw file
  1<?php
  2/* vim: set expandtab sw=4 ts=4 sts=4: */
  3/**
  4 * Wrappers for Drizzle extension classes
  5 *
  6 * Drizzle extension exposes libdrizzle functions and requires user to have it in mind while using them.
  7 * This wrapper is not complete and hides a lot of original functionality, but allows for easy usage
  8 * of the drizzle PHP extension.
  9 *
 10 * @package PhpMyAdmin-DBI-Drizzle
 11 */
 12
 13// TODO: drizzle module segfaults while freeing resources, often. This allows at least for some development
 14function _drizzle_shutdown_flush() {
 15    flush();
 16}
 17register_shutdown_function('_drizzle_shutdown_flush');
 18
 19function _dlog_argstr($args)
 20{
 21    $r = array();
 22    foreach ($args as $arg) {
 23        if (is_object($arg)) {
 24            $r[] = get_class($arg);
 25        } elseif (is_bool($arg)) {
 26            $r[] = $arg ? 'true' : 'false';
 27        } elseif (is_null($arg)) {
 28            $r[] = 'null';
 29        } else {
 30            $r[] = $arg;
 31        }
 32    }
 33    return implode(', ', $r);
 34}
 35
 36function _dlog($end = false)
 37{
 38    /*
 39    static $fp = null;
 40
 41    if (!$fp) {
 42        $fp = fopen('./drizzle_log.log', 'a');
 43        flock($fp, LOCK_EX);
 44        fwrite($fp, "\r\n[" . date('H:i:s') . "]\t" . $_SERVER['REQUEST_URI'] . "\r\n");
 45        register_shutdown_function(function() use ($fp) {
 46            fwrite($fp, '[' . date('H:i:s') . "]\tEND\r\n\r\n");
 47        });
 48    }
 49    if ($end) {
 50        fwrite($fp, '[' . date('H:i:s') . "]\tok\r\n");
 51    } else {
 52        $bt = debug_backtrace(true);
 53        $caller = (isset($bt[1]['class']) ? $bt[1]['class'] . '::' : '') . $bt[1]['function'];
 54        if ($bt[1]['function'] == '__call') {
 55            $caller .= '^' . $bt[1]['args'][0];
 56            $args = _dlog_argstr($bt[1]['args'][1]);
 57        } else {
 58            $args = _dlog_argstr($bt[1]['args']);
 59        }
 60        fwrite($fp, '[' . date('H:i:s') . "]\t" . $caller . "\t" . $args . "\r\n");
 61        for ($i = 2; $i <= count($bt)-1; $i++) {
 62            if (!isset($bt[$i])) {
 63                break;
 64            }
 65            $caller = (isset($bt[$i]['class']) ? $bt[$i]['class'] . '::' : '') . $bt[$i]['function'];
 66            $caller .= ' (' . $bt[$i]['file'] . ':' . $bt[$i]['line'] .  ')';
 67            fwrite($fp, str_repeat(' ', 20) . $caller . "\r\n");
 68        }
 69    }
 70    //*/
 71}
 72
 73/**
 74 * Wrapper for Drizzle class
 75 */
 76class PMA_Drizzle extends Drizzle
 77{
 78    /**
 79     * Fetch mode: result rows contain column names
 80     */
 81    const FETCH_ASSOC = 1;
 82    /**
 83     * Fetch mode: result rows contain only numeric indices
 84     */
 85    const FETCH_NUM = 2;
 86    /**
 87     * Fetch mode: result rows have both column names and numeric indices
 88     */
 89    const FETCH_BOTH = 3;
 90
 91    /**
 92     * Result buffering: entire result set is buffered upon execution
 93     */
 94    const BUFFER_RESULT = 1;
 95    /**
 96     * Result buffering: buffering occurs only on row level
 97     */
 98    const BUFFER_ROW = 2;
 99
100    /**
101     * Constructor
102     */
103    public function __construct()
104    {_dlog();
105        parent::__construct();
106    }
107
108    /**
109     * Creates a new database conection using TCP
110     *
111     * @param $host
112     * @param $port
113     * @param $user
114     * @param $password
115     * @param $db
116     * @param $options
117     * @return PMA_DrizzleCon
118     */
119    public function addTcp($host, $port, $user, $password, $db, $options)
120    {_dlog();
121        $dcon = parent::addTcp($host, $port, $user, $password, $db, $options);
122        return $dcon instanceof DrizzleCon
123            ? new PMA_DrizzleCon($dcon)
124            : $dcon;
125    }
126
127    /**
128     * Creates a new connection using unix domain socket
129     * 
130     * @param $uds
131     * @param $user
132     * @param $password
133     * @param $db
134     * @param $options
135     * @return PMA_DrizzleCon
136     */
137    public function addUds($uds, $user, $password, $db, $options)
138    {_dlog();
139        $dcon = parent::addUds($uds, $user, $password, $db, $options);
140        return $dcon instanceof DrizzleCon
141            ? new PMA_DrizzleCon($dcon)
142            : $dcon;
143    }
144}
145
146/**
147 * Wrapper around DrizzleCon class
148 *
149 * Its main task is to wrap results with PMA_DrizzleResult class
150 */
151class PMA_DrizzleCon
152{
153    /**
154     * Instance of DrizzleCon class
155     * @var DrizzleCon
156     */
157    private $dcon;
158
159    /**
160     * Result of the most recent query
161     * @var PMA_DrizzleResult
162     */
163    private $lastResult;
164
165    /**
166     * Constructor
167     *
168     * @param DrizzleCon $dcon
169     */
170    public function __construct(DrizzleCon $dcon)
171    {_dlog();
172        $this->dcon = $dcon;
173    }
174
175    /**
176     * Executes given query. Opens database connection if not already done.
177     *
178     * @param string $query
179     * @param int    $bufferMode  PMA_Drizzle::BUFFER_RESULT, PMA_Drizzle::BUFFER_ROW
180     * @param int    $fetchMode   PMA_Drizzle::FETCH_ASSOC, PMA_Drizzle::FETCH_NUM or PMA_Drizzle::FETCH_BOTH
181     * @return PMA_DrizzleResult
182     */
183    public function query($query, $bufferMode = PMA_Drizzle::BUFFER_RESULT, $fetchMode = PMA_Drizzle::FETCH_ASSOC)
184    {_dlog();
185        $result = $this->dcon->query($query);
186        if ($result instanceof DrizzleResult) {
187    _dlog(true);
188            $this->lastResult = new PMA_DrizzleResult($result, $bufferMode, $fetchMode);
189            return $this->lastResult;
190        }
191        return $result;
192    }
193
194    /**
195     * Returns the number of rows affected by last query
196     *
197     * @return int|false
198     */
199    public function affectedRows()
200    {
201        return $this->lastResult
202            ? $this->lastResult->affectedRows()
203            : false;
204    }
205
206    /**
207     * Pass calls of undefined methods to DrizzleCon object
208     * 
209     * @param $method
210     * @param $args
211     * @return mixed
212     */
213    public function __call($method, $args)
214    {_dlog();
215        return call_user_func_array(array($this->dcon, $method), $args);
216    }
217
218    /**
219     * Returns original Drizzle connection object
220     *
221     * @return DrizzleCon
222     */
223    public function getConnectionObject()
224    {_dlog();
225        return $this->dcon;
226    }
227}
228
229/**
230 * Wrapper around DrizzleResult. Allows for reading result rows as an associative array
231 * and hides complexity behind buffering.
232 */
233class PMA_DrizzleResult
234{
235    /**
236     * Instamce of DrizzleResult class
237     * @var DrizzleResult
238     */
239    private $dresult;
240    /**
241     * Fetch mode
242     * @var int
243     */
244    private $fetchMode;
245    /**
246     * Buffering mode
247     * @var int
248     */
249    private $bufferMode;
250
251    /**
252     * Cached column data
253     * @var DrizzleColumn[]
254     */
255    private $columns = null;
256    /**
257     * Cached column names
258     * @var string[]
259     */
260    private $columnNames = null;
261
262    /**
263     * Constructor
264     *
265     * @param DrizzleResult $dresult
266     * @param int           $bufferMode
267     * @param int           $fetchMode
268     */
269    public function __construct(DrizzleResult $dresult, $bufferMode, $fetchMode)
270    {_dlog();
271        $this->dresult = $dresult;
272        $this->bufferMode = $bufferMode;
273        $this->fetchMode = $fetchMode;
274
275        if ($this->bufferMode == PMA_Drizzle::BUFFER_RESULT) {
276            $this->dresult->buffer();
277        }
278    }
279
280    /**
281     * Sets fetch mode
282     *
283     * @param int $fetchMode
284     */
285    public function setFetchMode($fetchMode)
286    {_dlog();
287        $this->fetchMode = $fetchMode;
288    }
289
290    /**
291     * Reads information about columns contained in current result set into {@see $columns} and {@see $columnNames} arrays
292     */
293    private function _readColumns()
294    {_dlog();
295        $this->columns = array();
296        $this->columnNames = array();
297        if ($this->bufferMode == PMA_Drizzle::BUFFER_RESULT) {
298            while (($column = $this->dresult->columnNext()) !== null) {
299                $this->columns[] = $column;
300                $this->columnNames[] = $column->name();
301            }
302        } else {
303            while (($column = $this->dresult->columnRead()) !== null) {
304                $this->columns[] = $column;
305                $this->columnNames[] = $column->name();
306            }
307        }
308    }
309
310    /**
311     * Returns columns in current result
312     *
313     * @return DrizzleColumn[]
314     */
315    public function getColumns()
316    {_dlog();
317        if (!$this->columns) {
318            $this->_readColumns();
319        }
320        return $this->columns;
321    }
322
323    /**
324     * Returns number if columns in result
325     *
326     * @return int
327     */
328    public function numColumns()
329    {_dlog();
330        return $this->dresult->columnCount();
331    }
332
333    /**
334     * Transforms result row to conform to current fetch mode
335     *
336     * @param mixed &$row
337     * @param int   $fetchMode
338     */
339    private function _transformResultRow(&$row, $fetchMode)
340    {
341        if (!$row) {
342            return;
343        }
344
345        switch ($fetchMode) {
346            case PMA_Drizzle::FETCH_ASSOC:
347                $row = array_combine($this->columnNames, $row);
348                break;
349            case PMA_Drizzle::FETCH_BOTH:
350                $length = count($row);
351                for ($i = 0; $i < $length; $i++) {
352                    $row[$this->columnNames[$i]] = $row[$i];
353                }
354                break;
355            default:
356                break;
357        }
358    }
359
360    /**
361     * Fetches next for from this result set
362     *
363     * @param int $fetchMode  fetch mode to use, if none given the default one is used
364     * @return array|null
365     */
366    public function fetchRow($fetchMode = null)
367    {_dlog();
368        // read column names on first fetch, only buffered results allow for reading it later
369        if (!$this->columns) {
370            $this->_readColumns();
371        }
372        if ($fetchMode === null) {
373            $fetchMode = $this->fetchMode;
374        }
375        $row = null;
376        switch ($this->bufferMode) {
377            case PMA_Drizzle::BUFFER_RESULT:
378                $row = $this->dresult->rowNext();
379                break;
380            case PMA_Drizzle::BUFFER_ROW:
381                $row = $this->dresult->rowBuffer();
382                break;
383        }
384        $this->_transformResultRow($row, $fetchMode);
385        return $row;
386    }
387
388    /**
389     * Adjusts the result pointer to an arbitrary row in buffered result
390     *
391     * @param $row_index
392     * @return bool
393     */
394    public function seek($row_index)
395    {_dlog();
396        if ($this->bufferMode != PMA_Drizzle::BUFFER_RESULT) {
397            trigger_error("Can't seek in an unbuffered result set", E_USER_WARNING);
398            return false;
399        }
400        // rowSeek always returns NULL (drizzle extension v.0.5, API v.7)
401        if ($row_index >= 0 && $row_index < $this->dresult->rowCount()) {
402            $this->dresult->rowSeek($row_index);
403            return true;
404        }
405        return false;
406    }
407
408    /**
409     * Returns the number of rows in buffered result set
410     *
411     * @return int|false
412     */
413    public function numRows()
414    {_dlog();
415        if ($this->bufferMode != PMA_Drizzle::BUFFER_RESULT) {
416            trigger_error("Can't count rows in an unbuffered result set", E_USER_WARNING);
417            return false;
418        }
419        return $this->dresult->rowCount();
420    }
421
422    /**
423     * Returns the number of rows affected by query
424     *
425     * @return int|false
426     */
427    public function affectedRows()
428    {_dlog();
429        return $this->dresult->affectedRows();
430    }
431
432    /**
433     * Frees resources taken by this result
434     */
435    public function free()
436    {_dlog();
437        unset($this->columns);
438        unset($this->columnNames);
439        drizzle_result_free($this->dresult);
440        unset($this->dresult);
441    }
442}