Source for file dibi.php

Documentation is available at dibi.php

  1. 1: <?php
  2. 2:  
  3. 3: /**
  4. 4:  * dibi - tiny'n'smart database abstraction layer
  5. 5:  * ----------------------------------------------
  6. 6:  *
  7. 7:  * Copyright (c) 2005, 2010 David Grudl (http://davidgrudl.com)
  8. 8:  *
  9. 9:  * This source file is subject to the "dibi license" that is bundled
  10. 10:  * with this package in the file license.txt, and/or GPL license.
  11. 11:  *
  12. 12:  * For more information please see http://dibiphp.com
  13. 13:  *
  14. 14:  * @copyright  Copyright (c) 2005, 2010 David Grudl
  15. 15:  * @license    http://dibiphp.com/license  dibi license
  16. 16:  * @link       http://dibiphp.com
  17. 17:  * @package    dibi
  18. 18:  */
  19. 19:  
  20. 20:  
  21. 21: /**
  22. 22:  * Check PHP configuration.
  23. 23:  */
  24. 24: if (version_compare(PHP_VERSION'5.2.0''<')) {
  25. 25:     throw new Exception('dibi needs PHP 5.2.0 or newer.');
  26. 26: }
  27. 27:  
  28. 28: @set_magic_quotes_runtime(FALSE)// intentionally @
  29. 29:  
  30. 30:  
  31. 31:  
  32. 32: /**
  33. 33:  * Compatibility with Nette
  34. 34:  */
  35. 35: if (interface_exists('Nette\\IDebugPanel'FALSE)) {
  36. 36:     class_alias('Nette\\IDebugPanel''IDebugPanel');
  37. 37:  
  38. 38: elseif (!interface_exists('IDebugPanel'FALSE)) {
  39. 39:     interface IDebugPanel {}
  40. 40: }
  41. 41:  
  42. 42: if (!defined('NETTE')) {
  43. 43:     /**#@+ @package exceptions */
  44. 44:     class NotImplementedException extends LogicException {}
  45. 45:     class NotSupportedException extends LogicException {}
  46. 46:     class MemberAccessException extends LogicException {}
  47. 47:     class InvalidStateException extends RuntimeException {}
  48. 48:     class IOException extends RuntimeException {}
  49. 49:     class FileNotFoundException extends IOException {}
  50. 50:     /**#@-*/
  51. 51:  
  52. 52:     require_once dirname(__FILE__'/Nette/DateTime53.php';
  53. 53: }
  54. 54:  
  55. 55:  
  56. 56: /** @package exceptions */
  57. 57: class PcreException extends Exception {
  58. 58:  
  59. 59:     public function __construct($message '%msg.')
  60. 60:     {
  61. 61:         static $messages array(
  62. 62:             PREG_INTERNAL_ERROR => 'Internal error',
  63. 63:             PREG_BACKTRACK_LIMIT_ERROR => 'Backtrack limit was exhausted',
  64. 64:             PREG_RECURSION_LIMIT_ERROR => 'Recursion limit was exhausted',
  65. 65:             PREG_BAD_UTF8_ERROR => 'Malformed UTF-8 data',
  66. 66:             => 'Offset didn\'t correspond to the begin of a valid UTF-8 code point'// PREG_BAD_UTF8_OFFSET_ERROR
  67. 67:         );
  68. 68:         $code preg_last_error();
  69. 69:         parent::__construct(str_replace('%msg'isset($messages[$code]$messages[$code'Unknown error'$message)$code);
  70. 70:     }
  71. 71: }
  72. 72:  
  73. 73:  
  74. 74:  
  75. 75: /**
  76. 76:  * @deprecated
  77. 77:  */
  78. 78: class DibiVariable extends DateTime53
  79. 79: {
  80. 80:     function __construct($val)
  81. 81:     {
  82. 82:         parent::__construct($val);
  83. 83:     }
  84. 84: }
  85. 85:  
  86. 86:  
  87. 87:  
  88. 88: // dibi libraries
  89. 89: require_once dirname(__FILE__'/libs/interfaces.php';
  90. 90: require_once dirname(__FILE__'/libs/DibiObject.php';
  91. 91: require_once dirname(__FILE__'/libs/DibiLazyStorage.php';
  92. 92: require_once dirname(__FILE__'/libs/DibiException.php';
  93. 93: require_once dirname(__FILE__'/libs/DibiConnection.php';
  94. 94: require_once dirname(__FILE__'/libs/DibiResult.php';
  95. 95: require_once dirname(__FILE__'/libs/DibiResultIterator.php';
  96. 96: require_once dirname(__FILE__'/libs/DibiRow.php';
  97. 97: require_once dirname(__FILE__'/libs/DibiTranslator.php';
  98. 98: require_once dirname(__FILE__'/libs/DibiDataSource.php';
  99. 99: require_once dirname(__FILE__'/libs/DibiFluent.php';
  100. 100: require_once dirname(__FILE__'/libs/DibiDatabaseInfo.php';
  101. 101: require_once dirname(__FILE__'/libs/DibiProfiler.php';
  102. 102:  
  103. 103:  
  104. 104:  
  105. 105:  
  106. 106:  
  107. 107: /**
  108. 108:  * Interface for database drivers.
  109. 109:  *
  110. 110:  * This class is static container class for creating DB objects and
  111. 111:  * store connections info.
  112. 112:  *
  113. 113:  * @copyright  Copyright (c) 2005, 2010 David Grudl
  114. 114:  * @package    dibi
  115. 115:  */
  116. 116: class dibi
  117. 118:     /**#@+
  118. 119:      * dibi data type
  119. 120:      */
  120. 121:     const TEXT =       's'// as 'string'
  121. 122:     const BINARY =     'bin';
  122. 123:     const BOOL =       'b';
  123. 124:     const INTEGER =    'i';
  124. 125:     const FLOAT =      'f';
  125. 126:     const DATE =       'd';
  126. 127:     const DATETIME =   't';
  127. 128:     const TIME =       't';
  128. 129:     const IDENTIFIER = 'n';
  129. 130:     /**#@-*/
  130. 131:  
  131. 132:     /**#@+
  132. 133:      * @deprecated column types
  133. 134:      */
  134. 135:     const FIELD_TEXT = self::TEXT;
  135. 136:     const FIELD_BINARY = self::BINARY;
  136. 137:     const FIELD_BOOL = self::BOOL;
  137. 138:     const FIELD_INTEGER = self::INTEGER;
  138. 139:     const FIELD_FLOAT = self::FLOAT;
  139. 140:     const FIELD_DATE = self::DATE;
  140. 141:     const FIELD_DATETIME = self::DATETIME;
  141. 142:     const FIELD_TIME = self::TIME;
  142. 143:     /**#@-*/
  143. 144:  
  144. 145:     /**#@+
  145. 146:      * dibi version
  146. 147:      */
  147. 148:     const VERSION = '1.3-dev';
  148. 149:     const REVISION = 'b1156e5 released on 2010-08-27';
  149. 150:     /**#@-*/
  150. 151:  
  151. 152:     const ASC = 'ASC'DESC = 'DESC';
  152. 153:  
  153. 154:     /** @var DibiConnection[]  Connection registry storage for DibiConnection objects */
  154. 155:     private static $registry array();
  155. 156:  
  156. 157:     /** @var DibiConnection  Current connection */
  157. 158:     private static $connection;
  158. 159:  
  159. 160:     /** @var DibiLazyStorage  Substitutions for identifiers */
  160. 161:     public static $substs;
  161. 162:  
  162. 163:     /** @var array  @see addHandler */
  163. 164:     private static $handlers array();
  164. 165:  
  165. 166:     /** @var string  Last SQL command @see dibi::query() */
  166. 167:     public static $sql;
  167. 168:  
  168. 169:     /** @var int  Elapsed time for last query */
  169. 170:     public static $elapsedTime;
  170. 171:  
  171. 172:     /** @var int  Elapsed time for all queries */
  172. 173:     public static $totalTime;
  173. 174:  
  174. 175:     /** @var int  Number or queries */
  175. 176:     public static $numOfQueries 0;
  176. 177:  
  177. 178:     /** @var string  Default dibi driver */
  178. 179:     public static $defaultDriver 'mysql';
  179. 180:  
  180. 181:  
  181. 182:  
  182. 183:     /**
  183. 184:      * Static class - cannot be instantiated.
  184. 185:      */
  185. 186:     final public function __construct()
  186. 187:     {
  187. 188:         throw new LogicException("Cannot instantiate static class " get_class($this));
  188. 189:     }
  189. 190:  
  190. 191:  
  191. 192:  
  192. 193:     /********************* connections handling ****************d*g**/
  193. 194:  
  194. 195:  
  195. 196:  
  196. 197:     /**
  197. 198:      * Creates a new DibiConnection object and connects it to specified database.
  198. 199:      * @param  mixed   connection parameters
  199. 200:      * @param  string  connection name
  200. 201:      * @return DibiConnection 
  201. 202:      * @throws DibiException
  202. 203:      */
  203. 204:     public static function connect($config array()$name 0)
  204. 205:     {
  205. 206:         return self::$connection self::$registry[$namenew DibiConnection($config$name);
  206. 207:     }
  207. 208:  
  208. 209:  
  209. 210:  
  210. 211:     /**
  211. 212:      * Disconnects from database (doesn't destroy DibiConnection object).
  212. 213:      * @return void 
  213. 214:      */
  214. 215:     public static function disconnect()
  215. 216:     {
  216. 217:         self::getConnection()->disconnect();
  217. 218:     }
  218. 219:  
  219. 220:  
  220. 221:  
  221. 222:     /**
  222. 223:      * Returns TRUE when connection was established.
  223. 224:      * @return bool 
  224. 225:      */
  225. 226:     public static function isConnected()
  226. 227:     {
  227. 228:         return (self::$connection !== NULL&& self::$connection->isConnected();
  228. 229:     }
  229. 230:  
  230. 231:  
  231. 232:  
  232. 233:     /**
  233. 234:      * Retrieve active connection.
  234. 235:      * @param  string   connection registy name
  235. 236:      * @return DibiConnection 
  236. 237:      * @throws DibiException
  237. 238:      */
  238. 239:     public static function getConnection($name NULL)
  239. 240:     {
  240. 241:         if ($name === NULL{
  241. 242:             if (self::$connection === NULL{
  242. 243:                 throw new DibiException('Dibi is not connected to database.');
  243. 244:             }
  244. 245:  
  245. 246:             return self::$connection;
  246. 247:         }
  247. 248:  
  248. 249:         if (!isset(self::$registry[$name])) {
  249. 250:             throw new DibiException("There is no connection named '$name'.");
  250. 251:         }
  251. 252:  
  252. 253:         return self::$registry[$name];
  253. 254:     }
  254. 255:  
  255. 256:  
  256. 257:  
  257. 258:     /**
  258. 259:      * Change active connection.
  259. 260:      * @param  string   connection registy name
  260. 261:      * @return void 
  261. 262:      * @throws DibiException
  262. 263:      */
  263. 264:     public static function activate($name)
  264. 265:     {
  265. 266:         self::$connection self::getConnection($name);
  266. 267:     }
  267. 268:  
  268. 269:  
  269. 270:  
  270. 271:     /**
  271. 272:      * Retrieve active connection profiler.
  272. 273:      * @return IDibiProfiler 
  273. 274:      * @throws DibiException
  274. 275:      */
  275. 276:     public static function getProfiler()
  276. 277:     {
  277. 278:         return self::getConnection()->getProfiler();
  278. 279:     }
  279. 280:  
  280. 281:  
  281. 282:  
  282. 283:     /********************* monostate for active connection ****************d*g**/
  283. 284:  
  284. 285:  
  285. 286:  
  286. 287:     /**
  287. 288:      * Generates and executes SQL query - Monostate for DibiConnection::query().
  288. 289:      * @param  array|mixed     one or more arguments
  289. 290:      * @return DibiResult|int  result set object (if any)
  290. 291:      * @throws DibiException
  291. 292:      */
  292. 293:     public static function query($args)
  293. 294:     {
  294. 295:         $args func_get_args();
  295. 296:         return self::getConnection()->query($args);
  296. 297:     }
  297. 298:  
  298. 299:  
  299. 300:  
  300. 301:     /**
  301. 302:      * Executes the SQL query - Monostate for DibiConnection::nativeQuery().
  302. 303:      * @param  string           SQL statement.
  303. 304:      * @return DibiResult|int  result set object (if any)
  304. 305:      */
  305. 306:     public static function nativeQuery($sql)
  306. 307:     {
  307. 308:         return self::getConnection()->nativeQuery($sql);
  308. 309:     }
  309. 310:  
  310. 311:  
  311. 312:  
  312. 313:     /**
  313. 314:      * Generates and prints SQL query - Monostate for DibiConnection::test().
  314. 315:      * @param  array|mixed one or more arguments
  315. 316:      * @return bool 
  316. 317:      */
  317. 318:     public static function test($args)
  318. 319:     {
  319. 320:         $args func_get_args();
  320. 321:         return self::getConnection()->test($args);
  321. 322:     }
  322. 323:  
  323. 324:  
  324. 325:  
  325. 326:     /**
  326. 327:      * Generates and returns SQL query as DibiDataSource - Monostate for DibiConnection::test().
  327. 328:      * @param  array|mixed     one or more arguments
  328. 329:      * @return DibiDataSource 
  329. 330:      */
  330. 331:     public static function dataSource($args)
  331. 332:     {
  332. 333:         $args func_get_args();
  333. 334:         return self::getConnection()->dataSource($args);
  334. 335:     }
  335. 336:  
  336. 337:  
  337. 338:  
  338. 339:     /**
  339. 340:      * Executes SQL query and fetch result - Monostate for DibiConnection::query() & fetch().
  340. 341:      * @param  array|mixed   one or more arguments
  341. 342:      * @return DibiRow 
  342. 343:      * @throws DibiException
  343. 344:      */
  344. 345:     public static function fetch($args)
  345. 346:     {
  346. 347:         $args func_get_args();
  347. 348:         return self::getConnection()->query($args)->fetch();
  348. 349:     }
  349. 350:  
  350. 351:  
  351. 352:  
  352. 353:     /**
  353. 354:      * Executes SQL query and fetch results - Monostate for DibiConnection::query() & fetchAll().
  354. 355:      * @param  array|mixed   one or more arguments
  355. 356:      * @return array of DibiRow
  356. 357:      * @throws DibiException
  357. 358:      */
  358. 359:     public static function fetchAll($args)
  359. 360:     {
  360. 361:         $args func_get_args();
  361. 362:         return self::getConnection()->query($args)->fetchAll();
  362. 363:     }
  363. 364:  
  364. 365:  
  365. 366:  
  366. 367:     /**
  367. 368:      * Executes SQL query and fetch first column - Monostate for DibiConnection::query() & fetchSingle().
  368. 369:      * @param  array|mixed   one or more arguments
  369. 370:      * @return string 
  370. 371:      * @throws DibiException
  371. 372:      */
  372. 373:     public static function fetchSingle($args)
  373. 374:     {
  374. 375:         $args func_get_args();
  375. 376:         return self::getConnection()->query($args)->fetchSingle();
  376. 377:     }
  377. 378:  
  378. 379:  
  379. 380:  
  380. 381:     /**
  381. 382:      * Executes SQL query and fetch pairs - Monostate for DibiConnection::query() & fetchPairs().
  382. 383:      * @param  array|mixed   one or more arguments
  383. 384:      * @return string 
  384. 385:      * @throws DibiException
  385. 386:      */
  386. 387:     public static function fetchPairs($args)
  387. 388:     {
  388. 389:         $args func_get_args();
  389. 390:         return self::getConnection()->query($args)->fetchPairs();
  390. 391:     }
  391. 392:  
  392. 393:  
  393. 394:  
  394. 395:     /**
  395. 396:      * Gets the number of affected rows.
  396. 397:      * Monostate for DibiConnection::getAffectedRows()
  397. 398:      * @return int  number of rows
  398. 399:      * @throws DibiException
  399. 400:      */
  400. 401:     public static function getAffectedRows()
  401. 402:     {
  402. 403:         return self::getConnection()->getAffectedRows();
  403. 404:     }
  404. 405:  
  405. 406:  
  406. 407:  
  407. 408:     /**
  408. 409:      * Gets the number of affected rows. Alias for getAffectedRows().
  409. 410:      * @return int  number of rows
  410. 411:      * @throws DibiException
  411. 412:      */
  412. 413:     public static function affectedRows()
  413. 414:     {
  414. 415:         return self::getConnection()->getAffectedRows();
  415. 416:     }
  416. 417:  
  417. 418:  
  418. 419:  
  419. 420:     /**
  420. 421:      * Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query.
  421. 422:      * Monostate for DibiConnection::getInsertId()
  422. 423:      * @param  string     optional sequence name
  423. 424:      * @return int 
  424. 425:      * @throws DibiException
  425. 426:      */
  426. 427:     public static function getInsertId($sequence=NULL)
  427. 428:     {
  428. 429:         return self::getConnection()->getInsertId($sequence);
  429. 430:     }
  430. 431:  
  431. 432:  
  432. 433:  
  433. 434:     /**
  434. 435:      * Retrieves the ID generated for an AUTO_INCREMENT column. Alias for getInsertId().
  435. 436:      * @param  string     optional sequence name
  436. 437:      * @return int 
  437. 438:      * @throws DibiException
  438. 439:      */
  439. 440:     public static function insertId($sequence=NULL)
  440. 441:     {
  441. 442:         return self::getConnection()->getInsertId($sequence);
  442. 443:     }
  443. 444:  
  444. 445:  
  445. 446:  
  446. 447:     /**
  447. 448:      * Begins a transaction - Monostate for DibiConnection::begin().
  448. 449:      * @param  string  optional savepoint name
  449. 450:      * @return void 
  450. 451:      * @throws DibiException
  451. 452:      */
  452. 453:     public static function begin($savepoint NULL)
  453. 454:     {
  454. 455:         self::getConnection()->begin($savepoint);
  455. 456:     }
  456. 457:  
  457. 458:  
  458. 459:  
  459. 460:     /**
  460. 461:      * Commits statements in a transaction - Monostate for DibiConnection::commit($savepoint = NULL).
  461. 462:      * @param  string  optional savepoint name
  462. 463:      * @return void 
  463. 464:      * @throws DibiException
  464. 465:      */
  465. 466:     public static function commit($savepoint NULL)
  466. 467:     {
  467. 468:         self::getConnection()->commit($savepoint);
  468. 469:     }
  469. 470:  
  470. 471:  
  471. 472:  
  472. 473:     /**
  473. 474:      * Rollback changes in a transaction - Monostate for DibiConnection::rollback().
  474. 475:      * @param  string  optional savepoint name
  475. 476:      * @return void 
  476. 477:      * @throws DibiException
  477. 478:      */
  478. 479:     public static function rollback($savepoint NULL)
  479. 480:     {
  480. 481:         self::getConnection()->rollback($savepoint);
  481. 482:     }
  482. 483:  
  483. 484:  
  484. 485:  
  485. 486:     /**
  486. 487:      * Gets a information about the current database - Monostate for DibiConnection::getDatabaseInfo().
  487. 488:      * @return DibiDatabaseInfo 
  488. 489:      */
  489. 490:     public static function getDatabaseInfo()
  490. 491:     {
  491. 492:         return self::getConnection()->getDatabaseInfo();
  492. 493:     }
  493. 494:  
  494. 495:  
  495. 496:  
  496. 497:     /**
  497. 498:      * Import SQL dump from file - extreme fast!
  498. 499:      * @param  string  filename
  499. 500:      * @return int  count of sql commands
  500. 501:      */
  501. 502:     public static function loadFile($file)
  502. 503:     {
  503. 504:         return self::getConnection()->loadFile($file);
  504. 505:     }
  505. 506:  
  506. 507:  
  507. 508:  
  508. 509:     /**
  509. 510:      * Replacement for majority of dibi::methods() in future.
  510. 511:      */
  511. 512:     public static function __callStatic($name$args)
  512. 513:     {
  513. 514:         //if ($name = 'select', 'update', ...') {
  514. 515:         //    return self::command()->$name($args);
  515. 516:         //}
  516. 517:         return call_user_func_array(array(self::getConnection()$name)$args);
  517. 518:     }
  518. 519:  
  519. 520:  
  520. 521:  
  521. 522:     /********************* fluent SQL builders ****************d*g**/
  522. 523:  
  523. 524:  
  524. 525:  
  525. 526:     /**
  526. 527:      * @return DibiFluent 
  527. 528:      */
  528. 529:     public static function command()
  529. 530:     {
  530. 531:         return self::getConnection()->command();
  531. 532:     }
  532. 533:  
  533. 534:  
  534. 535:  
  535. 536:     /**
  536. 537:      * @param  string    column name
  537. 538:      * @return DibiFluent 
  538. 539:      */
  539. 540:     public static function select($args)
  540. 541:     {
  541. 542:         $args func_get_args();
  542. 543:         return call_user_func_array(array(self::getConnection()'select')$args);
  543. 544:     }
  544. 545:  
  545. 546:  
  546. 547:  
  547. 548:     /**
  548. 549:      * @param  string   table
  549. 550:      * @param  array 
  550. 551:      * @return DibiFluent 
  551. 552:      */
  552. 553:     public static function update($table$args)
  553. 554:     {
  554. 555:         return self::getConnection()->update($table$args);
  555. 556:     }
  556. 557:  
  557. 558:  
  558. 559:  
  559. 560:     /**
  560. 561:      * @param  string   table
  561. 562:      * @param  array 
  562. 563:      * @return DibiFluent 
  563. 564:      */
  564. 565:     public static function insert($table$args)
  565. 566:     {
  566. 567:         return self::getConnection()->insert($table$args);
  567. 568:     }
  568. 569:  
  569. 570:  
  570. 571:  
  571. 572:     /**
  572. 573:      * @param  string   table
  573. 574:      * @return DibiFluent 
  574. 575:      */
  575. 576:     public static function delete($table)
  576. 577:     {
  577. 578:         return self::getConnection()->delete($table);
  578. 579:     }
  579. 580:  
  580. 581:  
  581. 582:  
  582. 583:     /********************* data types ****************d*g**/
  583. 584:  
  584. 585:  
  585. 586:  
  586. 587:     /**
  587. 588:      * @deprecated
  588. 589:      */
  589. 590:     public static function datetime($time NULL)
  590. 591:     {
  591. 592:         return new DateTime53(is_numeric($timedate('Y-m-d H:i:s'$time$time);
  592. 593:     }
  593. 594:  
  594. 595:  
  595. 596:  
  596. 597:     /**
  597. 598:      * @deprecated
  598. 599:      */
  599. 600:     public static function date($date NULL)
  600. 601:     {
  601. 602:         return new DateTime53(is_numeric($datedate('Y-m-d'$date$date);
  602. 603:     }
  603. 604:  
  604. 605:  
  605. 606:  
  606. 607:     /********************* substitutions ****************d*g**/
  607. 608:  
  608. 609:  
  609. 610:  
  610. 611:     /**
  611. 612:      * Create a new substitution pair for indentifiers.
  612. 613:      * @param  string from
  613. 614:      * @param  string to
  614. 615:      * @return void 
  615. 616:      */
  616. 617:     public static function addSubst($expr$subst)
  617. 618:     {
  618. 619:         self::$substs->$expr $subst;
  619. 620:     }
  620. 621:  
  621. 622:  
  622. 623:  
  623. 624:     /**
  624. 625:      * Remove substitution pair.
  625. 626:      * @param  mixed from or TRUE
  626. 627:      * @return void 
  627. 628:      */
  628. 629:     public static function removeSubst($expr)
  629. 630:     {
  630. 631:         if ($expr === TRUE{
  631. 632:             self::$substs new DibiLazyStorage(self::$substs->getCallback());
  632. 633:         else {
  633. 634:             unset(self::$substs->$expr);
  634. 635:         }
  635. 636:     }
  636. 637:  
  637. 638:  
  638. 639:  
  639. 640:     /**
  640. 641:      * Sets substitution fallback handler.
  641. 642:      * @param  callback 
  642. 643:      * @return void 
  643. 644:      */
  644. 645:     public static function setSubstFallback($callback)
  645. 646:     {
  646. 647:         self::$substs->setCallback($callback);
  647. 648:     }
  648. 649:  
  649. 650:  
  650. 651:  
  651. 652:     /**
  652. 653:      * Default substitution fallback handler.
  653. 654:      * @param  string 
  654. 655:      * @return mixed 
  655. 656:      */
  656. 657:     public static function defaultSubstFallback($expr)
  657. 658:     {
  658. 659:         return ":$expr:";
  659. 660:     }
  660. 661:  
  661. 662:  
  662. 663:  
  663. 664:     /********************* misc tools ****************d*g**/
  664. 665:  
  665. 666:  
  666. 667:  
  667. 668:     /**
  668. 669:      * Prints out a syntax highlighted version of the SQL command or DibiResult.
  669. 670:      * @param  string|DibiResult
  670. 671:      * @param  bool  return output instead of printing it?
  671. 672:      * @return string 
  672. 673:      */
  673. 674:     public static function dump($sql NULL$return FALSE)
  674. 675:     {
  675. 676:         ob_start();
  676. 677:         if ($sql instanceof DibiResult{
  677. 678:             $sql->dump();
  678. 679:  
  679. 680:         else {
  680. 681:             if ($sql === NULL$sql self::$sql;
  681. 682:  
  682. 683:             static $keywords1 'SELECT|UPDATE|INSERT(?:\s+INTO)?|REPLACE(?:\s+INTO)?|DELETE|FROM|WHERE|HAVING|GROUP\s+BY|ORDER\s+BY|LIMIT|OFFSET|SET|VALUES|LEFT\s+JOIN|INNER\s+JOIN|TRUNCATE';
  683. 684:             static $keywords2 'ALL|DISTINCT|DISTINCTROW|AS|USING|ON|AND|OR|IN|IS|NOT|NULL|LIKE|TRUE|FALSE';
  684. 685:  
  685. 686:             // insert new lines
  686. 687:             $sql " $sql ";
  687. 688:             $sql preg_replace("#(?<=[\\s,(])($keywords1)(?=[\\s,)])#i""\n\$1"$sql);
  688. 689:  
  689. 690:             // reduce spaces
  690. 691:             $sql preg_replace('#[ \t]{2,}#'" "$sql);
  691. 692:  
  692. 693:             $sql wordwrap($sql100);
  693. 694:             $sql preg_replace("#([ \t]*\r?\n){2,}#""\n"$sql);
  694. 695:  
  695. 696:             if (PHP_SAPI === 'cli'{
  696. 697:                 echo trim($sql"\n\n";
  697. 698:             else {
  698. 699:                 // syntax highlight
  699. 700:                 $sql htmlSpecialChars($sql);
  700. 701:                 $sql preg_replace_callback("#(/\\*.+?\\*/)|(\\*\\*.+?\\*\\*)|(?<=[\\s,(])($keywords1)(?=[\\s,)])|(?<=[\\s,(=])($keywords2)(?=[\\s,)=])#is"array('dibi''highlightCallback')$sql);
  701. 702:                 echo '<pre class="dump">'trim($sql)"</pre>\n";
  702. 703:             }
  703. 704:         }
  704. 705:  
  705. 706:         if ($return{
  706. 707:             return ob_get_clean();
  707. 708:         else {
  708. 709:             ob_end_flush();
  709. 710:         }
  710. 711:     }
  711. 712:  
  712. 713:  
  713. 714:  
  714. 715:     private static function highlightCallback($matches)
  715. 716:     {
  716. 717:         if (!empty($matches[1])) // comment
  717. 718:             return '<em style="color:gray">' $matches[1'</em>';
  718. 719:  
  719. 720:         if (!empty($matches[2])) // error
  720. 721:             return '<strong style="color:red">' $matches[2'</strong>';
  721. 722:  
  722. 723:         if (!empty($matches[3])) // most important keywords
  723. 724:             return '<strong style="color:blue">' $matches[3'</strong>';
  724. 725:  
  725. 726:         if (!empty($matches[4])) // other keywords
  726. 727:             return '<strong style="color:green">' $matches[4'</strong>';
  727. 728:     }
  728. 729:  
  729. 731:  
  730. 732:  
  731. 733:  
  732. 734: // static constructor
  733. 735: dibi::$substs new DibiLazyStorage(array('dibi''defaultSubstFallback'));