PageRenderTime 57ms CodeModel.GetById 29ms RepoModel.GetById 0ms app.codeStats 0ms

/www/libs/dibi/dibi.php

https://github.com/bazo/Mokuji
PHP | 740 lines | 288 code | 185 blank | 267 comment | 26 complexity | 8b4dbe3d09e7d218192acf570abe582c MD5 | raw file
Possible License(s): BSD-3-Clause, MIT
  1. <?php
  2. /**
  3. * dibi - tiny'n'smart database abstraction layer
  4. * ----------------------------------------------
  5. *
  6. * Copyright (c) 2005, 2010 David Grudl (http://davidgrudl.com)
  7. *
  8. * This source file is subject to the "dibi license" that is bundled
  9. * with this package in the file license.txt, and/or GPL license.
  10. *
  11. * For more information please see http://dibiphp.com
  12. *
  13. * @copyright Copyright (c) 2005, 2010 David Grudl
  14. * @license http://dibiphp.com/license dibi license
  15. * @link http://dibiphp.com
  16. * @package dibi
  17. */
  18. /**
  19. * Check PHP configuration.
  20. */
  21. if (version_compare(PHP_VERSION, '5.2.0', '<')) {
  22. throw new Exception('dibi needs PHP 5.2.0 or newer.');
  23. }
  24. @set_magic_quotes_runtime(FALSE); // intentionally @
  25. /**
  26. * Compatibility with Nette
  27. */
  28. if (!class_exists('NotImplementedException', FALSE)) {
  29. /** @package exceptions */
  30. class NotImplementedException extends LogicException {}
  31. }
  32. if (!class_exists('NotSupportedException', FALSE)) {
  33. /** @package exceptions */
  34. class NotSupportedException extends LogicException {}
  35. }
  36. if (!class_exists('MemberAccessException', FALSE)) {
  37. /** @package exceptions */
  38. class MemberAccessException extends LogicException {}
  39. }
  40. if (!class_exists('InvalidStateException', FALSE)) {
  41. /** @package exceptions */
  42. class InvalidStateException extends RuntimeException {}
  43. }
  44. if (!class_exists('IOException', FALSE)) {
  45. /** @package exceptions */
  46. class IOException extends RuntimeException {}
  47. }
  48. if (!class_exists('FileNotFoundException', FALSE)) {
  49. /** @package exceptions */
  50. class FileNotFoundException extends IOException {}
  51. }
  52. if (!interface_exists(/*Nette\*/'IDebugPanel', FALSE)) {
  53. require_once dirname(__FILE__) . '/Nette/IDebugPanel.php';
  54. }
  55. if (!class_exists('DateTime53', FALSE)) {
  56. require_once dirname(__FILE__) . '/Nette/DateTime53.php';
  57. }
  58. /**
  59. * @deprecated
  60. */
  61. class DibiVariable extends DateTime53
  62. {
  63. function __construct($val)
  64. {
  65. parent::__construct($val);
  66. }
  67. }
  68. // dibi libraries
  69. require_once dirname(__FILE__) . '/libs/interfaces.php';
  70. require_once dirname(__FILE__) . '/libs/DibiObject.php';
  71. require_once dirname(__FILE__) . '/libs/DibiException.php';
  72. require_once dirname(__FILE__) . '/libs/DibiConnection.php';
  73. require_once dirname(__FILE__) . '/libs/DibiResult.php';
  74. require_once dirname(__FILE__) . '/libs/DibiResultIterator.php';
  75. require_once dirname(__FILE__) . '/libs/DibiRow.php';
  76. require_once dirname(__FILE__) . '/libs/DibiTranslator.php';
  77. require_once dirname(__FILE__) . '/libs/DibiDataSource.php';
  78. require_once dirname(__FILE__) . '/libs/DibiFluent.php';
  79. require_once dirname(__FILE__) . '/libs/DibiDatabaseInfo.php';
  80. require_once dirname(__FILE__) . '/libs/DibiProfiler.php';
  81. /**
  82. * Interface for database drivers.
  83. *
  84. * This class is static container class for creating DB objects and
  85. * store connections info.
  86. *
  87. * @copyright Copyright (c) 2005, 2010 David Grudl
  88. * @package dibi
  89. */
  90. class dibi
  91. {
  92. /**#@+
  93. * dibi data type
  94. */
  95. const TEXT = 's'; // as 'string'
  96. const BINARY = 'bin';
  97. const BOOL = 'b';
  98. const INTEGER = 'i';
  99. const FLOAT = 'f';
  100. const DATE = 'd';
  101. const DATETIME = 't';
  102. const TIME = 't';
  103. const IDENTIFIER = 'n';
  104. /**#@-*/
  105. /**#@+
  106. * @deprecated column types
  107. */
  108. const FIELD_TEXT = self::TEXT;
  109. const FIELD_BINARY = self::BINARY;
  110. const FIELD_BOOL = self::BOOL;
  111. const FIELD_INTEGER = self::INTEGER;
  112. const FIELD_FLOAT = self::FLOAT;
  113. const FIELD_DATE = self::DATE;
  114. const FIELD_DATETIME = self::DATETIME;
  115. const FIELD_TIME = self::TIME;
  116. /**#@-*/
  117. /**#@+
  118. * dibi version
  119. */
  120. const VERSION = '1.3-dev';
  121. const REVISION = '550be3b released on 2010-04-06';
  122. /**#@-*/
  123. /**#@+
  124. * Configuration options
  125. */
  126. const RESULT_DETECT_TYPES = 'resultDetectTypes';
  127. const RESULT_DATE_TIME = 'resultDateTime';
  128. const ASC = 'ASC', DESC = 'DESC';
  129. /**#@-*/
  130. /** @var DibiConnection[] Connection registry storage for DibiConnection objects */
  131. private static $registry = array();
  132. /** @var DibiConnection Current connection */
  133. private static $connection;
  134. /** @var array Substitutions for identifiers */
  135. public static $substs = array();
  136. /** @var callback Substitution fallback */
  137. public static $substFallBack = array(__CLASS__, 'defaultSubstFallback');
  138. /** @var array @see addHandler */
  139. private static $handlers = array();
  140. /** @var string Last SQL command @see dibi::query() */
  141. public static $sql;
  142. /** @var int Elapsed time for last query */
  143. public static $elapsedTime;
  144. /** @var int Elapsed time for all queries */
  145. public static $totalTime;
  146. /** @var int Number or queries */
  147. public static $numOfQueries = 0;
  148. /** @var string Default dibi driver */
  149. public static $defaultDriver = 'mysql';
  150. /**
  151. * Static class - cannot be instantiated.
  152. */
  153. final public function __construct()
  154. {
  155. throw new LogicException("Cannot instantiate static class " . get_class($this));
  156. }
  157. /********************* connections handling ****************d*g**/
  158. /**
  159. * Creates a new DibiConnection object and connects it to specified database.
  160. * @param array|string|ArrayObject connection parameters
  161. * @param string connection name
  162. * @return DibiConnection
  163. * @throws DibiException
  164. */
  165. public static function connect($config = array(), $name = 0)
  166. {
  167. return self::$connection = self::$registry[$name] = new DibiConnection($config, $name);
  168. }
  169. /**
  170. * Disconnects from database (doesn't destroy DibiConnection object).
  171. * @return void
  172. */
  173. public static function disconnect()
  174. {
  175. self::getConnection()->disconnect();
  176. }
  177. /**
  178. * Returns TRUE when connection was established.
  179. * @return bool
  180. */
  181. public static function isConnected()
  182. {
  183. return (self::$connection !== NULL) && self::$connection->isConnected();
  184. }
  185. /**
  186. * Retrieve active connection.
  187. * @param string connection registy name
  188. * @return DibiConnection
  189. * @throws DibiException
  190. */
  191. public static function getConnection($name = NULL)
  192. {
  193. if ($name === NULL) {
  194. if (self::$connection === NULL) {
  195. throw new DibiException('Dibi is not connected to database.');
  196. }
  197. return self::$connection;
  198. }
  199. if (!isset(self::$registry[$name])) {
  200. throw new DibiException("There is no connection named '$name'.");
  201. }
  202. return self::$registry[$name];
  203. }
  204. /**
  205. * Change active connection.
  206. * @param string connection registy name
  207. * @return void
  208. * @throws DibiException
  209. */
  210. public static function activate($name)
  211. {
  212. self::$connection = self::getConnection($name);
  213. }
  214. /**
  215. * Retrieve active connection profiler.
  216. * @return IDibiProfiler
  217. * @throws DibiException
  218. */
  219. public static function getProfiler()
  220. {
  221. return self::getConnection()->getProfiler();
  222. }
  223. /********************* monostate for active connection ****************d*g**/
  224. /**
  225. * Generates and executes SQL query - Monostate for DibiConnection::query().
  226. * @param array|mixed one or more arguments
  227. * @return DibiResult|int result set object (if any)
  228. * @throws DibiException
  229. */
  230. public static function query($args)
  231. {
  232. $args = func_get_args();
  233. return self::getConnection()->query($args);
  234. }
  235. /**
  236. * Executes the SQL query - Monostate for DibiConnection::nativeQuery().
  237. * @param string SQL statement.
  238. * @return DibiResult|int result set object (if any)
  239. */
  240. public static function nativeQuery($sql)
  241. {
  242. return self::getConnection()->nativeQuery($sql);
  243. }
  244. /**
  245. * Generates and prints SQL query - Monostate for DibiConnection::test().
  246. * @param array|mixed one or more arguments
  247. * @return bool
  248. */
  249. public static function test($args)
  250. {
  251. $args = func_get_args();
  252. return self::getConnection()->test($args);
  253. }
  254. /**
  255. * Generates and returns SQL query as DibiDataSource - Monostate for DibiConnection::test().
  256. * @param array|mixed one or more arguments
  257. * @return DibiDataSource
  258. */
  259. public static function dataSource($args)
  260. {
  261. $args = func_get_args();
  262. return self::getConnection()->dataSource($args);
  263. }
  264. /**
  265. * Executes SQL query and fetch result - Monostate for DibiConnection::query() & fetch().
  266. * @param array|mixed one or more arguments
  267. * @return DibiRow
  268. * @throws DibiException
  269. */
  270. public static function fetch($args)
  271. {
  272. $args = func_get_args();
  273. return self::getConnection()->query($args)->fetch();
  274. }
  275. /**
  276. * Executes SQL query and fetch results - Monostate for DibiConnection::query() & fetchAll().
  277. * @param array|mixed one or more arguments
  278. * @return array of DibiRow
  279. * @throws DibiException
  280. */
  281. public static function fetchAll($args)
  282. {
  283. $args = func_get_args();
  284. return self::getConnection()->query($args)->fetchAll();
  285. }
  286. /**
  287. * Executes SQL query and fetch first column - Monostate for DibiConnection::query() & fetchSingle().
  288. * @param array|mixed one or more arguments
  289. * @return string
  290. * @throws DibiException
  291. */
  292. public static function fetchSingle($args)
  293. {
  294. $args = func_get_args();
  295. return self::getConnection()->query($args)->fetchSingle();
  296. }
  297. /**
  298. * Executes SQL query and fetch pairs - Monostate for DibiConnection::query() & fetchPairs().
  299. * @param array|mixed one or more arguments
  300. * @return string
  301. * @throws DibiException
  302. */
  303. public static function fetchPairs($args)
  304. {
  305. $args = func_get_args();
  306. return self::getConnection()->query($args)->fetchPairs();
  307. }
  308. /**
  309. * Gets the number of affected rows.
  310. * Monostate for DibiConnection::getAffectedRows()
  311. * @return int number of rows
  312. * @throws DibiException
  313. */
  314. public static function getAffectedRows()
  315. {
  316. return self::getConnection()->getAffectedRows();
  317. }
  318. /**
  319. * Gets the number of affected rows. Alias for getAffectedRows().
  320. * @return int number of rows
  321. * @throws DibiException
  322. */
  323. public static function affectedRows()
  324. {
  325. return self::getConnection()->getAffectedRows();
  326. }
  327. /**
  328. * Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query.
  329. * Monostate for DibiConnection::getInsertId()
  330. * @param string optional sequence name
  331. * @return int
  332. * @throws DibiException
  333. */
  334. public static function getInsertId($sequence=NULL)
  335. {
  336. return self::getConnection()->getInsertId($sequence);
  337. }
  338. /**
  339. * Retrieves the ID generated for an AUTO_INCREMENT column. Alias for getInsertId().
  340. * @param string optional sequence name
  341. * @return int
  342. * @throws DibiException
  343. */
  344. public static function insertId($sequence=NULL)
  345. {
  346. return self::getConnection()->getInsertId($sequence);
  347. }
  348. /**
  349. * Begins a transaction - Monostate for DibiConnection::begin().
  350. * @param string optional savepoint name
  351. * @return void
  352. * @throws DibiException
  353. */
  354. public static function begin($savepoint = NULL)
  355. {
  356. self::getConnection()->begin($savepoint);
  357. }
  358. /**
  359. * Commits statements in a transaction - Monostate for DibiConnection::commit($savepoint = NULL).
  360. * @param string optional savepoint name
  361. * @return void
  362. * @throws DibiException
  363. */
  364. public static function commit($savepoint = NULL)
  365. {
  366. self::getConnection()->commit($savepoint);
  367. }
  368. /**
  369. * Rollback changes in a transaction - Monostate for DibiConnection::rollback().
  370. * @param string optional savepoint name
  371. * @return void
  372. * @throws DibiException
  373. */
  374. public static function rollback($savepoint = NULL)
  375. {
  376. self::getConnection()->rollback($savepoint);
  377. }
  378. /**
  379. * Gets a information about the current database - Monostate for DibiConnection::getDatabaseInfo().
  380. * @return DibiDatabaseInfo
  381. */
  382. public static function getDatabaseInfo()
  383. {
  384. return self::getConnection()->getDatabaseInfo();
  385. }
  386. /**
  387. * Import SQL dump from file - extreme fast!
  388. * @param string filename
  389. * @return int count of sql commands
  390. */
  391. public static function loadFile($file)
  392. {
  393. return self::getConnection()->loadFile($file);
  394. }
  395. /**
  396. * Replacement for majority of dibi::methods() in future.
  397. */
  398. public static function __callStatic($name, $args)
  399. {
  400. //if ($name = 'select', 'update', ...') {
  401. // return self::command()->$name($args);
  402. //}
  403. return call_user_func_array(array(self::getConnection(), $name), $args);
  404. }
  405. /********************* fluent SQL builders ****************d*g**/
  406. /**
  407. * @return DibiFluent
  408. */
  409. public static function command()
  410. {
  411. return self::getConnection()->command();
  412. }
  413. /**
  414. * @param string column name
  415. * @return DibiFluent
  416. */
  417. public static function select($args)
  418. {
  419. $args = func_get_args();
  420. return call_user_func_array(array(self::getConnection(), 'select'), $args);
  421. }
  422. /**
  423. * @param string table
  424. * @param array
  425. * @return DibiFluent
  426. */
  427. public static function update($table, $args)
  428. {
  429. return self::getConnection()->update($table, $args);
  430. }
  431. /**
  432. * @param string table
  433. * @param array
  434. * @return DibiFluent
  435. */
  436. public static function insert($table, $args)
  437. {
  438. return self::getConnection()->insert($table, $args);
  439. }
  440. /**
  441. * @param string table
  442. * @return DibiFluent
  443. */
  444. public static function delete($table)
  445. {
  446. return self::getConnection()->delete($table);
  447. }
  448. /********************* data types ****************d*g**/
  449. /**
  450. * @deprecated
  451. */
  452. public static function datetime($time = NULL)
  453. {
  454. return new DateTime53(is_numeric($time) ? date('Y-m-d H:i:s', $time) : $time);
  455. }
  456. /**
  457. * @deprecated
  458. */
  459. public static function date($date = NULL)
  460. {
  461. return new DateTime53(is_numeric($date) ? date('Y-m-d', $date) : $date);
  462. }
  463. /********************* substitutions ****************d*g**/
  464. /**
  465. * Create a new substitution pair for indentifiers.
  466. * @param string from
  467. * @param string to
  468. * @return void
  469. */
  470. public static function addSubst($expr, $subst)
  471. {
  472. self::$substs[$expr] = $subst;
  473. }
  474. /**
  475. * Remove substitution pair.
  476. * @param mixed from or TRUE
  477. * @return void
  478. */
  479. public static function removeSubst($expr)
  480. {
  481. if ($expr === TRUE) {
  482. self::$substs = array();
  483. } else {
  484. unset(self::$substs[':'.$expr.':']);
  485. }
  486. }
  487. /**
  488. * Sets substitution fallback handler.
  489. * @param callback
  490. * @return void
  491. */
  492. public static function setSubstFallback($callback)
  493. {
  494. if (!is_callable($callback)) {
  495. $able = is_callable($callback, TRUE, $textual);
  496. throw new InvalidArgumentException("Handler '$textual' is not " . ($able ? 'callable.' : 'valid PHP callback.'));
  497. }
  498. self::$substFallBack = $callback;
  499. }
  500. /**
  501. * Default substitution fallback handler.
  502. * @param string
  503. * @return mixed
  504. */
  505. public static function defaultSubstFallback($expr)
  506. {
  507. throw new InvalidStateException("Missing substitution for '$expr' expression.");
  508. }
  509. /********************* misc tools ****************d*g**/
  510. /**
  511. * Prints out a syntax highlighted version of the SQL command or DibiResult.
  512. * @param string|DibiResult
  513. * @param bool return output instead of printing it?
  514. * @return string
  515. */
  516. public static function dump($sql = NULL, $return = FALSE)
  517. {
  518. ob_start();
  519. if ($sql instanceof DibiResult) {
  520. $sql->dump();
  521. } else {
  522. if ($sql === NULL) $sql = self::$sql;
  523. static $keywords1 = 'SELECT|UPDATE|INSERT(?:\s+INTO)?|REPLACE(?:\s+INTO)?|DELETE|FROM|WHERE|HAVING|GROUP\s+BY|ORDER\s+BY|LIMIT|SET|VALUES|LEFT\s+JOIN|INNER\s+JOIN|TRUNCATE';
  524. static $keywords2 = 'ALL|DISTINCT|DISTINCTROW|AS|USING|ON|AND|OR|IN|IS|NOT|NULL|LIKE|TRUE|FALSE';
  525. // insert new lines
  526. $sql = " $sql ";
  527. $sql = preg_replace("#(?<=[\\s,(])($keywords1)(?=[\\s,)])#i", "\n\$1", $sql);
  528. // reduce spaces
  529. $sql = preg_replace('#[ \t]{2,}#', " ", $sql);
  530. $sql = wordwrap($sql, 100);
  531. $sql = htmlSpecialChars($sql);
  532. $sql = preg_replace("#([ \t]*\r?\n){2,}#", "\n", $sql);
  533. // syntax highlight
  534. $sql = preg_replace_callback("#(/\\*.+?\\*/)|(\\*\\*.+?\\*\\*)|(?<=[\\s,(])($keywords1)(?=[\\s,)])|(?<=[\\s,(=])($keywords2)(?=[\\s,)=])#is", array('dibi', 'highlightCallback'), $sql);
  535. $sql = trim($sql);
  536. echo '<pre class="dump">', $sql, "</pre>\n";
  537. }
  538. if ($return) {
  539. return ob_get_clean();
  540. } else {
  541. ob_end_flush();
  542. }
  543. }
  544. private static function highlightCallback($matches)
  545. {
  546. if (!empty($matches[1])) // comment
  547. return '<em style="color:gray">' . $matches[1] . '</em>';
  548. if (!empty($matches[2])) // error
  549. return '<strong style="color:red">' . $matches[2] . '</strong>';
  550. if (!empty($matches[3])) // most important keywords
  551. return '<strong style="color:blue">' . $matches[3] . '</strong>';
  552. if (!empty($matches[4])) // other keywords
  553. return '<strong style="color:green">' . $matches[4] . '</strong>';
  554. }
  555. }