drizzle-wrappers.lib.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435
  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. public function __construct(DrizzleCon $dcon)
  129. {
  130. $this->_dcon = $dcon;
  131. }
  132. /**
  133. * Executes given query. Opens database connection if not already done.
  134. *
  135. * @param string $query query to execute
  136. * @param int $bufferMode PMA_Drizzle::BUFFER_RESULT,PMA_Drizzle::BUFFER_ROW
  137. * @param int $fetchMode PMA_Drizzle::FETCH_ASSOC, PMA_Drizzle::FETCH_NUM
  138. * or PMA_Drizzle::FETCH_BOTH
  139. *
  140. * @return PMA_DrizzleResult
  141. */
  142. public function query($query, $bufferMode = PMA_Drizzle::BUFFER_RESULT,
  143. $fetchMode = PMA_Drizzle::FETCH_ASSOC
  144. ) {
  145. $result = $this->_dcon->query($query);
  146. if ($result instanceof DrizzleResult) {
  147. $this->_lastResult = new PMA_DrizzleResult(
  148. $result, $bufferMode, $fetchMode
  149. );
  150. return $this->_lastResult;
  151. }
  152. return $result;
  153. }
  154. /**
  155. * Returns the number of rows affected by last query
  156. *
  157. * @return int|false
  158. */
  159. public function affectedRows()
  160. {
  161. return $this->_lastResult
  162. ? $this->_lastResult->affectedRows()
  163. : false;
  164. }
  165. /**
  166. * Pass calls of undefined methods to DrizzleCon object
  167. *
  168. * @param string $method method name
  169. * @param mixed $args method parameters
  170. *
  171. * @return mixed
  172. */
  173. public function __call($method, $args)
  174. {
  175. return call_user_func_array(array($this->_dcon, $method), $args);
  176. }
  177. /**
  178. * Returns original Drizzle connection object
  179. *
  180. * @return DrizzleCon
  181. */
  182. public function getConnectionObject()
  183. {
  184. return $this->_dcon;
  185. }
  186. }
  187. /**
  188. * Wrapper around DrizzleResult.
  189. *
  190. * Allows for reading result rows as an associative array and hides complexity
  191. * behind buffering.
  192. *
  193. * @package PhpMyAdmin-DBI
  194. * @subpackage Drizzle
  195. */
  196. class PMA_DrizzleResult
  197. {
  198. /**
  199. * Instamce of DrizzleResult class
  200. * @var DrizzleResult
  201. */
  202. private $_dresult;
  203. /**
  204. * Fetch mode
  205. * @var int
  206. */
  207. private $_fetchMode;
  208. /**
  209. * Buffering mode
  210. * @var int
  211. */
  212. private $_bufferMode;
  213. /**
  214. * Cached column data
  215. * @var DrizzleColumn[]
  216. */
  217. private $_columns = null;
  218. /**
  219. * Cached column names
  220. * @var string[]
  221. */
  222. private $_columnNames = null;
  223. /**
  224. * Constructor
  225. *
  226. * @param DrizzleResult $dresult result handler
  227. * @param int $bufferMode buffering mode
  228. * @param int $fetchMode fetching mode
  229. */
  230. public function __construct(DrizzleResult $dresult, $bufferMode, $fetchMode)
  231. {
  232. $this->_dresult = $dresult;
  233. $this->_bufferMode = $bufferMode;
  234. $this->_fetchMode = $fetchMode;
  235. if ($this->_bufferMode == PMA_Drizzle::BUFFER_RESULT) {
  236. $this->_dresult->buffer();
  237. }
  238. }
  239. /**
  240. * Sets fetch mode
  241. *
  242. * @param int $fetchMode fetch mode
  243. *
  244. * @return void
  245. */
  246. public function setFetchMode($fetchMode)
  247. {
  248. $this->_fetchMode = $fetchMode;
  249. }
  250. /**
  251. * Reads information about columns contained in current result
  252. * set into {@see $_columns} and {@see $_columnNames} arrays
  253. *
  254. * @return void
  255. */
  256. private function _readColumns()
  257. {
  258. $this->_columns = array();
  259. $this->_columnNames = array();
  260. if ($this->_bufferMode == PMA_Drizzle::BUFFER_RESULT) {
  261. while (($column = $this->_dresult->columnNext()) !== null) {
  262. $this->_columns[] = $column;
  263. $this->_columnNames[] = $column->name();
  264. }
  265. } else {
  266. while (($column = $this->_dresult->columnRead()) !== null) {
  267. $this->_columns[] = $column;
  268. $this->_columnNames[] = $column->name();
  269. }
  270. }
  271. }
  272. /**
  273. * Returns columns in current result
  274. *
  275. * @return DrizzleColumn[]
  276. */
  277. public function getColumns()
  278. {
  279. if (! $this->_columns) {
  280. $this->_readColumns();
  281. }
  282. return $this->_columns;
  283. }
  284. /**
  285. * Returns number if columns in result
  286. *
  287. * @return int
  288. */
  289. public function numColumns()
  290. {
  291. return $this->_dresult->columnCount();
  292. }
  293. /**
  294. * Transforms result row to conform to current fetch mode
  295. *
  296. * @param mixed &$row row to process
  297. * @param int $fetchMode fetch mode
  298. *
  299. * @return void
  300. */
  301. private function _transformResultRow(&$row, $fetchMode)
  302. {
  303. if (! $row) {
  304. return;
  305. }
  306. switch ($fetchMode) {
  307. case PMA_Drizzle::FETCH_ASSOC:
  308. $row = array_combine($this->_columnNames, $row);
  309. break;
  310. case PMA_Drizzle::FETCH_BOTH:
  311. $length = count($row);
  312. for ($i = 0; $i < $length; $i++) {
  313. $row[$this->_columnNames[$i]] = $row[$i];
  314. }
  315. break;
  316. default:
  317. break;
  318. }
  319. }
  320. /**
  321. * Fetches next for from this result set
  322. *
  323. * @param int $fetchMode fetch mode to use, if not given the default one is used
  324. *
  325. * @return array|null
  326. */
  327. public function fetchRow($fetchMode = null)
  328. {
  329. // read column names on first fetch, only buffered results
  330. // allow for reading it later
  331. if (! $this->_columns) {
  332. $this->_readColumns();
  333. }
  334. if ($fetchMode === null) {
  335. $fetchMode = $this->_fetchMode;
  336. }
  337. $row = null;
  338. switch ($this->_bufferMode) {
  339. case PMA_Drizzle::BUFFER_RESULT:
  340. $row = $this->_dresult->rowNext();
  341. break;
  342. case PMA_Drizzle::BUFFER_ROW:
  343. $row = $this->_dresult->rowBuffer();
  344. break;
  345. }
  346. $this->_transformResultRow($row, $fetchMode);
  347. return $row;
  348. }
  349. /**
  350. * Adjusts the result pointer to an arbitrary row in buffered result
  351. *
  352. * @param integer $row_index where to seek
  353. *
  354. * @return bool
  355. */
  356. public function seek($row_index)
  357. {
  358. if ($this->_bufferMode != PMA_Drizzle::BUFFER_RESULT) {
  359. trigger_error(
  360. __("Can't seek in an unbuffered result set"), E_USER_WARNING
  361. );
  362. return false;
  363. }
  364. // rowSeek always returns NULL (drizzle extension v.0.5, API v.7)
  365. if ($row_index >= 0 && $row_index < $this->_dresult->rowCount()) {
  366. $this->_dresult->rowSeek($row_index);
  367. return true;
  368. }
  369. return false;
  370. }
  371. /**
  372. * Returns the number of rows in buffered result set
  373. *
  374. * @return int|false
  375. */
  376. public function numRows()
  377. {
  378. if ($this->_bufferMode != PMA_Drizzle::BUFFER_RESULT) {
  379. trigger_error(
  380. __("Can't count rows in an unbuffered result set"), E_USER_WARNING
  381. );
  382. return false;
  383. }
  384. return $this->_dresult->rowCount();
  385. }
  386. /**
  387. * Returns the number of rows affected by query
  388. *
  389. * @return int|false
  390. */
  391. public function affectedRows()
  392. {
  393. return $this->_dresult->affectedRows();
  394. }
  395. /**
  396. * Frees resources taken by this result
  397. *
  398. * @return void
  399. */
  400. public function free()
  401. {
  402. unset($this->_columns);
  403. unset($this->_columnNames);
  404. drizzle_result_free($this->_dresult);
  405. unset($this->_dresult);
  406. }
  407. }