2 /* vim: set expandtab sw=4 ts=4 sts=4: */
4 * Wrappers for Drizzle extension classes
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.
10 * @package phpMyAdmin-DBI-Drizzle
13 // TODO: drizzle module segfaults while freeing resources, often. This allows at least for some development
14 function _drizzle_shutdown_flush() {
17 register_shutdown_function('_drizzle_shutdown_flush');
19 function _dlog_argstr($args)
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)) {
33 return implode(', ', $r);
36 function _dlog($end = false)
42 $fp = fopen('./drizzle_log.log', 'a');
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");
50 fwrite($fp, '[' . date('H:i:s') . "]\tok\r\n");
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]);
58 $args = _dlog_argstr($bt[1]['args']);
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])) {
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");
74 * Wrapper for Drizzle class
76 class PMA_Drizzle
extends Drizzle
79 * Fetch mode: result rows contain column names
81 const FETCH_ASSOC
= 1;
83 * Fetch mode: result rows contain only numeric indices
87 * Fetch mode: result rows have both column names and numeric indices
92 * Result buffering: entire result set is buffered upon execution
94 const BUFFER_RESULT
= 1;
96 * Result buffering: buffering occurs only on row level
103 public function __construct()
105 parent
::__construct();
109 * Creates a new database conection using TCP
117 * @return PMA_DrizzleCon
119 public function addTcp($host, $port, $user, $password, $db, $options)
121 $dcon = parent
::addTcp($host, $port, $user, $password, $db, $options);
122 return $dcon instanceof DrizzleCon
123 ?
new PMA_DrizzleCon($dcon)
128 * Creates a new connection using unix domain socket
135 * @return PMA_DrizzleCon
137 public function addUds($uds, $user, $password, $db, $options)
139 $dcon = parent
::addUds($uds, $user, $password, $db, $options);
140 return $dcon instanceof DrizzleCon
141 ?
new PMA_DrizzleCon($dcon)
147 * Wrapper around DrizzleCon class
149 * Its main task is to wrap results with PMA_DrizzleResult class
154 * Instance of DrizzleCon class
160 * Result of the most recent query
161 * @var PMA_DrizzleResult
168 * @param DrizzleCon $dcon
170 public function __construct(DrizzleCon
$dcon)
176 * Executes given query. Opens database connection if not already done.
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
183 public function query($query, $bufferMode = PMA_Drizzle
::BUFFER_RESULT
, $fetchMode = PMA_Drizzle
::FETCH_ASSOC
)
185 $result = $this->dcon
->query($query);
186 if ($result instanceof DrizzleResult
) {
188 $this->lastResult
= new PMA_DrizzleResult($result, $bufferMode, $fetchMode);
189 return $this->lastResult
;
195 * Returns the number of rows affected by last query
199 public function affectedRows()
201 return $this->lastResult
202 ?
$this->lastResult
->affectedRows()
207 * Pass calls of undefined methods to DrizzleCon object
213 public function __call($method, $args)
215 return call_user_func_array(array($this->dcon
, $method), $args);
219 * Returns original Drizzle connection object
223 public function getConnectionObject()
230 * Wrapper around DrizzleResult. Allows for reading result rows as an associative array
231 * and hides complexity behind buffering.
233 class PMA_DrizzleResult
236 * Instamce of DrizzleResult class
253 * @var DrizzleColumn[]
255 private $columns = null;
257 * Cached column names
260 private $columnNames = null;
265 * @param DrizzleResult $dresult
266 * @param int $bufferMode
267 * @param int $fetchMode
269 public function __construct(DrizzleResult
$dresult, $bufferMode, $fetchMode)
271 $this->dresult
= $dresult;
272 $this->bufferMode
= $bufferMode;
273 $this->fetchMode
= $fetchMode;
275 if ($this->bufferMode
== PMA_Drizzle
::BUFFER_RESULT
) {
276 $this->dresult
->buffer();
283 * @param int $fetchMode
285 public function setFetchMode($fetchMode)
287 $this->fetchMode
= $fetchMode;
291 * Reads information about columns contained in current result set into {@see $columns} and {@see $columnNames} arrays
293 private function _readColumns()
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();
303 while (($column = $this->dresult
->columnRead()) !== null) {
304 $this->columns
[] = $column;
305 $this->columnNames
[] = $column->name();
311 * Returns columns in current result
313 * @return DrizzleColumn[]
315 public function getColumns()
317 if (!$this->columns
) {
318 $this->_readColumns();
320 return $this->columns
;
324 * Returns number if columns in result
328 public function numColumns()
330 return $this->dresult
->columnCount();
334 * Transforms result row to conform to current fetch mode
337 * @param int $fetchMode
339 private function _transformResultRow(&$row, $fetchMode)
345 switch ($fetchMode) {
346 case PMA_Drizzle
::FETCH_ASSOC
:
347 $row = array_combine($this->columnNames
, $row);
349 case PMA_Drizzle
::FETCH_BOTH
:
350 $length = count($row);
351 for ($i = 0; $i < $length; $i++
) {
352 $row[$this->columnNames
[$i]] = $row[$i];
361 * Fetches next for from this result set
363 * @param int $fetchMode fetch mode to use, if none given the default one is used
366 public function fetchRow($fetchMode = null)
368 // read column names on first fetch, only buffered results allow for reading it later
369 if (!$this->columns
) {
370 $this->_readColumns();
372 if ($fetchMode === null) {
373 $fetchMode = $this->fetchMode
;
376 switch ($this->bufferMode
) {
377 case PMA_Drizzle
::BUFFER_RESULT
:
378 $row = $this->dresult
->rowNext();
380 case PMA_Drizzle
::BUFFER_ROW
:
381 $row = $this->dresult
->rowBuffer();
384 $this->_transformResultRow($row, $fetchMode);
389 * Adjusts the result pointer to an arbitrary row in buffered result
394 public function seek($row_index)
396 if ($this->bufferMode
!= PMA_Drizzle
::BUFFER_RESULT
) {
397 trigger_error("Can't seek in an unbuffered result set", E_USER_WARNING
);
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);
409 * Returns the number of rows in buffered result set
413 public function numRows()
415 if ($this->bufferMode
!= PMA_Drizzle
::BUFFER_RESULT
) {
416 trigger_error("Can't count rows in an unbuffered result set", E_USER_WARNING
);
419 return $this->dresult
->rowCount();
423 * Returns the number of rows affected by query
427 public function affectedRows()
429 return $this->dresult
->affectedRows();
433 * Frees resources taken by this result
435 public function free()
437 unset($this->columns
);
438 unset($this->columnNames
);
439 drizzle_result_free($this->dresult
);
440 unset($this->dresult
);