drizzle-wrappers.lib.php 11 KB

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