Overview

Packages

  • Core
    • Authentication
    • Backend
    • Cache
    • CEC
    • Chain
    • ContentType
    • Database
    • Datatype
    • Debug
    • Exception
    • Frontend
      • Search
      • URI
      • Util
    • GenericDB
      • Model
    • GUI
      • HTML
    • I18N
    • LayoutHandler
    • Log
    • Security
    • Session
    • Util
    • Validation
    • Versioning
    • XML
  • Module
    • ContentSitemapHtml
    • ContentSitemapXml
    • ContentUserForum
    • NavigationTop
  • mpAutoloaderClassMap
  • None
  • Plugin
    • ContentAllocation
    • CronjobOverview
    • FormAssistant
    • FrontendLogic
    • FrontendUsers
    • Linkchecker
    • ModRewrite
    • Newsletter
    • Repository
      • FrontendNavigation
      • KeywordDensity
    • SearchSolr
    • SmartyWrapper
    • UrlShortener
    • UserForum
    • Workflow
  • PluginManager
  • Setup
    • Form
    • GUI
    • Helper
      • Environment
      • Filesystem
      • MySQL
      • PHP
    • UpgradeJob

Classes

  • cDb
  • cDbDriverAbstract
  • cDbDriverHandler
  • cDbDriverMysql
  • cDbDriverMysqli

Exceptions

  • cDbException
  • Overview
  • Package
  • Class
  • Tree
  • Deprecated
  • Todo
   1: <?php
   2: /**
   3:  * This file contains the database driver handler class.
   4:  *
   5:  * @package    Core
   6:  * @subpackage Database
   7:  * @version    SVN Revision $Rev:$
   8:  *
   9:  * @author     Dominik Ziegler
  10:  * @copyright  four for business AG <www.4fb.de>
  11:  * @license    http://www.contenido.org/license/LIZENZ.txt
  12:  * @link       http://www.4fb.de
  13:  * @link       http://www.contenido.org
  14:  */
  15: 
  16: defined('CON_FRAMEWORK') || die('Illegal call: Missing framework initialization - request aborted.');
  17: 
  18: /**
  19:  * This class contains functions for database driver handling in CONTENIDO.
  20:  *
  21:  * @package    Core
  22:  * @subpackage Database
  23:  */
  24: abstract class cDbDriverHandler {
  25: 
  26:     /**
  27:      *
  28:      * @var string
  29:      */
  30:     const HALT_YES = 'yes';
  31: 
  32:     /**
  33:      *
  34:      * @var string
  35:      */
  36:     const HALT_NO = 'no';
  37: 
  38:     /**
  39:      *
  40:      * @var string
  41:      */
  42:     const HALT_REPORT = 'report';
  43: 
  44:     /**
  45:      *
  46:      * @var string
  47:      */
  48:     const FETCH_NUMERIC = 'numeric';
  49: 
  50:     /**
  51:      *
  52:      * @var string
  53:      */
  54:     const FETCH_ASSOC = 'assoc';
  55: 
  56:     /**
  57:      *
  58:      * @var string
  59:      */
  60:     const FETCH_BOTH = 'both';
  61: 
  62:     /**
  63:      * Loader database driver.
  64:      *
  65:      * @var cDbDriverAbstract
  66:      */
  67:     protected $_driver = NULL;
  68: 
  69:     /**
  70:      * Driver type
  71:      *
  72:      * @var string
  73:      */
  74:     protected $_driverType = '';
  75: 
  76:     /**
  77:      * Default database connection for all instances
  78:      *
  79:      * @var array
  80:      */
  81:     protected static $_defaultDbCfg = array();
  82: 
  83:     /**
  84:      * Assoziative list of database connections
  85:      * @var array
  86:      */
  87:     protected static $_connectionCache = array();
  88: 
  89:     /**
  90:      * Assoziative list of database tables metadata
  91:      * @var array
  92:      */
  93:     protected static $_metaCache = array();
  94: 
  95:     /**
  96:      * Database connection configuration for current instance
  97:      *
  98:      * @var array
  99:      */
 100:     protected $_dbCfg = array();
 101: 
 102:     /**
 103:      * Halt status during occured errors.
 104:      * Feasible values are
 105:      * - "yes" (halt with message)
 106:      * - "no" (ignore errors quietly)
 107:      * - "report" (ignore errror, but spit a warning)
 108:      *
 109:      * @var string
 110:      */
 111:     protected $_haltBehaviour = 'no';
 112: 
 113:     /**
 114:      * Text to prepend to the halt message
 115:      *
 116:      * @var string
 117:      */
 118:     protected $_haltMsgPrefix = '';
 119: 
 120:     /**
 121:      * Profile data array
 122:      *
 123:      * @var array
 124:      */
 125:     protected static $_profileData = array();
 126: 
 127:     /**
 128:      * Constructor, sets passed options and connects to the DBMS, if not done
 129:      * before.
 130:      *
 131:      * Uses default connection settings, passed $options['connection'] settings
 132:      * will overwrite connection settings for current instance.
 133:      *
 134:      * @param array $options Assoziative options as follows:
 135:      *        - $options['haltBehavior'] (string) Optional, halt behavior on
 136:      *                       occured errors
 137:      *        - $options['haltMsgPrefix'] (string) Optional, Text to prepend to
 138:      *                       the halt message
 139:      *        - $options['enableProfiling'] (bool) Optional, flag to enable
 140:      *                       profiling
 141:      *        - $options['connection'] (array) Optional, assoziative connection
 142:      *                       settings
 143:      *        - $options['connection']['host'] (string) Hostname or ip
 144:      *        - $options['connection']['database'] (string) Database name
 145:      *        - $options['connection']['user'] (string) User name
 146:      *        - $options['connection']['password'] (string) User password
 147:      * @throws cDbException
 148:      */
 149:     public function __construct($options = array()) {
 150:         // use default connection configuration, but overwrite it by passed
 151:         // options
 152:         $this->_dbCfg = array_merge(self::$_defaultDbCfg, $options);
 153: 
 154:             // in case we do not have any configuration for database, try to load it from configuration
 155:         if (count($this->_dbCfg) == 0) {
 156:             $cfg = cRegistry::getConfig();
 157:             if (isset($cfg['db']) && count($cfg['db']) > 0) {
 158:                 $this->_dbCfg = $cfg['db'];
 159:             } else {
 160:                 throw new cDbException("Unable to establish a database connection without options!");
 161:             }
 162:         }
 163: 
 164:         if (isset($this->_dbCfg['haltBehavior'])) {
 165:             switch ($this->_dbCfg['haltBehavior']) {
 166:                 case self::HALT_YES:
 167:                     $this->_haltBehaviour = self::HALT_YES;
 168:                     break;
 169:                 case self::HALT_NO:
 170:                     $this->_haltBehaviour = self::HALT_NO;
 171:                     break;
 172:                 case self::HALT_REPORT:
 173:                     $this->_haltBehaviour = self::HALT_REPORT;
 174:                     break;
 175:             }
 176:         }
 177: 
 178:         if (isset($this->_dbCfg['haltMsgPrefix']) && is_string($this->_dbCfg['haltMsgPrefix'])) {
 179:             $this->_haltMsgPrefix = $this->_dbCfg['haltMsgPrefix'];
 180:         }
 181: 
 182:         $cfg = cRegistry::getConfig();
 183:         $this->_driverType = $cfg['database_extension'];
 184: 
 185:         $this->loadDriver();
 186: 
 187:         if ($this->connect() == NULL) {
 188:             $this->setErrorNumber(1);
 189:             $this->setErrorMessage("Could not connect to database");
 190: 
 191:             throw new cDbException($this->getErrorMessage());
 192:         }
 193:     }
 194: 
 195:     /**
 196:      * Checks if profiling was enabled via configuration.
 197:      *
 198:      * @return bool
 199:      */
 200:     public function isProfilingEnabled() {
 201:         return (bool)$this->_dbCfg['enableProfiling'];
 202:     }
 203: 
 204:     /**
 205:      * Returns the halt behaviour setting.
 206:      *
 207:      * @return string
 208:      */
 209:     public function getHaltBehaviour() {
 210:         return $this->_haltBehaviour;
 211:     }
 212: 
 213:     /**
 214:      * Loads the database driver and checks its base functionality.
 215:      *
 216:      * @throws cDbException
 217:      */
 218:     public function loadDriver() {
 219:         if ($this->_driver != NULL) {
 220:             return;
 221:         }
 222: 
 223:         $classNameSuffix = ucfirst($this->_driverType);
 224: 
 225:         $driverName = 'cDbDriver' . $classNameSuffix;
 226: 
 227:         if (class_exists($driverName) === false) {
 228:             throw new cDbException("Database driver was not found.");
 229:         }
 230: 
 231:         $this->_driver = new $driverName($this->_dbCfg);
 232: 
 233:         if (($this->getDriver() instanceof cDbDriverAbstract) === false) {
 234:             $this->_driver = NULL;
 235:             throw new cDbException("Database driver must extend cDbDriverAbstract");
 236:         }
 237: 
 238:         $this->getDriver()->setHandler($this);
 239: 
 240:         if ($this->getDriver()->check() === false) {
 241:             throw new cDbException("Database driver check failed.");
 242:         }
 243:     }
 244: 
 245:     /**
 246:      * Returns the database driver instance.
 247:      *
 248:      * @return cDbDriverAbstract
 249:      */
 250:     public function getDriver() {
 251:         return $this->_driver;
 252:     }
 253: 
 254:     /**
 255:      * Setter for default database configuration, the connection values.
 256:      *
 257:      * @param array $defaultDbCfg
 258:      */
 259:     public static function setDefaultConfiguration(array $defaultDbCfg) {
 260:         self::$_defaultDbCfg = $defaultDbCfg;
 261:     }
 262: 
 263:     /**
 264:      * Returns connection from connection cache
 265:      *
 266:      * @param mixed $data Connection data array or variable
 267:      *
 268:      * @return mixed Either The connection (object, resource, integer) or NULL
 269:      */
 270:     protected function _getConnection($data) {
 271:         $hash = md5($this->_driverType . '-' . (is_array($data) ? implode('-', $data) : (string)$data));
 272: 
 273:         return (isset(self::$_connectionCache[$hash])) ? self::$_connectionCache[$hash] : NULL;
 274:     }
 275: 
 276:     /**
 277:      * Stores connection in connection cache
 278:      *
 279:      * @param mixed $data       Connection data array
 280:      * @param mixed $connection The connection to store in cache
 281:      */
 282:     protected function _setConnection($data, $connection) {
 283:         $hash = md5($this->_driverType . '-' . (is_array($data) ? implode('-', $data) : (string)$data));
 284:         self::$_connectionCache[$hash] = $connection;
 285:     }
 286: 
 287:     /**
 288:      * Removes connection from cache
 289:      *
 290:      * @param mixed $connection The connection to remove in cache
 291:      */
 292:     protected function _removeConnection($connection) {
 293:         foreach (self::$_connectionCache as $hash => $res) {
 294:             if ($res == $connection) {
 295:                 unset(self::$_connectionCache[$hash]);
 296: 
 297:                 return;
 298:             }
 299:         }
 300:     }
 301: 
 302:     /**
 303:      * Adds a entry to the profile data.
 304:      *
 305:      * @param float  $timeStart
 306:      * @param float  $timeEnd
 307:      * @param string $statement
 308:      */
 309:     protected static function _addProfileData($timeStart, $timeEnd, $statement) {
 310:         self::$_profileData[] = array(
 311:             'time' => $timeEnd - $timeStart, 'query' => $statement
 312:         );
 313:     }
 314: 
 315:     /**
 316:      * Returns collected profile data.
 317:      *
 318:      * @return array Profile data array like:
 319:      *         - $arr[$i]['time'] (float) Elapsed time to execute the query
 320:      *         - $arr[$i]['query'] (string) The query itself
 321:      */
 322:     public static function getProfileData() {
 323:         return self::$_profileData;
 324:     }
 325: 
 326:     /**
 327:      * Prepares the statement for execution and returns it back.
 328:      * Accepts multiple parameter, where the first parameter should be the query
 329:      * and any additional parameter should be the values to replace in format
 330:      * definitions.
 331:      * As an alternative the second parameter cound be also a indexed array with
 332:      * values to replace in format definitions.
 333:      *
 334:      * Other option is to call this function with the statement containing named
 335:      * parameter
 336:      * and the second parameter as a assoziative array with key/value pairs to
 337:      * set in statement.
 338:      *
 339:      * Examples:
 340:      * <pre>
 341:      * // multiple parameter
 342:      * $sql = $obj->prepare('SELECT * FROM `%s` WHERE id = %d', 'tablename',
 343:      * 123);
 344:      *
 345:      * // 2 parameter where the first is the statement with formatting signs and
 346:      * the second the entries array
 347:      * $sql = $obj->prepare('SELECT * FROM `%s` WHERE id = %d',
 348:      * array('tablename', 123));
 349:      *
 350:      * // 2 parameter where the first is the statement with named parameter and
 351:      * the second the assoziative entries array
 352:      * $sql = $obj->prepare('SELECT * FROM `:mytab` WHERE id = :myid',
 353:      * array('mytab' => 'tablename', 'myid' => 123));
 354:      * </pre>
 355:      *
 356:      * Accepts additional unlimited parameter, where the parameter will be
 357:      * replaced against formatting sign in query.
 358:      *
 359:      * @param string $statement The sql statement to prepare.
 360:      *
 361:      * @return string The prepared sql statement
 362:      * @throws Exception If statement is empty or function is called with less
 363:      *         than 2 parameters
 364:      */
 365:     public function prepare($statement) {
 366:         // No empty queries
 367:         if (empty($statement)) {
 368:             throw new cDbException('Empty statement!');
 369:         }
 370: 
 371:         $arguments = func_get_args();
 372:         if (count($arguments) <= 1) {
 373:             throw new cDbException('Wrong number of parameter!');
 374:         }
 375: 
 376:         array_shift($arguments);
 377:         $statement = $this->_prepareStatement($statement, $arguments);
 378: 
 379:         return $statement;
 380:     }
 381: 
 382:     /**
 383:      * Prepares the passed statement.
 384:      *
 385:      * @param string $statement
 386:      * @param array  $arguments
 387:      *
 388:      * @return string
 389:      */
 390:     protected function _prepareStatement($statement, array $arguments) {
 391:         if (count($arguments) == 1 && is_array($arguments[0])) {
 392:             $arguments = $arguments[0];
 393:             if (count(array_filter(array_keys($arguments), 'is_string')) > 0) {
 394:                 // we have at least one key being string, it is an assoc array
 395:                 $statement = $this->_prepareStatementA($statement, $arguments);
 396:             } else {
 397:                 // it is an indexed array
 398:                 $statement = $this->_prepareStatementF($statement, $arguments);
 399:             }
 400:         } else {
 401:             $statement = $this->_prepareStatementF($statement, $arguments);
 402:         }
 403: 
 404:         return $statement;
 405:     }
 406: 
 407:     /**
 408:      * Prepares a statement with parameter for execution.
 409:      *
 410:      * Examples:
 411:      * <pre>
 412:      * $obj->_prepareStatementF('SELECT * FROM `%s` WHERE id = %d', 'tablename',
 413:      * 123);
 414:      * $obj->_prepareStatementF('SELECT * FROM `%s` WHERE id = %d AND user =
 415:      * %d', 'tablename', 123, 3);
 416:      * </pre>
 417:      *
 418:      * @param string $statement
 419:      * @param array  $arguments Arguments array containing the query with
 420:      *                          formatting
 421:      *                          signs and the entries.
 422:      *
 423:      * @return string
 424:      */
 425:     protected function _prepareStatementF($statement, array $arguments) {
 426:         if (count($arguments) > 0) {
 427:             $arguments = array_map(array(
 428:                 $this, 'escape'
 429:             ), $arguments);
 430:             array_unshift($arguments, $statement);
 431:             $statement = call_user_func_array('sprintf', $arguments);
 432:         }
 433: 
 434:         return $statement;
 435:     }
 436: 
 437:     /**
 438:      * Prepares a statement with named parameter for execution.
 439:      *
 440:      * Examples:
 441:      * <pre>
 442:      * // named parameter and assoziative entries array
 443:      * $sql = $obj->_prepareStatementA('SELECT * FROM `:mytab` WHERE id =
 444:      * :myid', array('mytab' => 'tablename', 'myid' => 123));
 445:      * $sql = $obj->_prepareStatementA('SELECT * FROM `:mytab` WHERE id = :myid
 446:      * AND user = :myuser', array('mytab' => 'tablename', 'myid' => 123,
 447:      * 'myuser' => 3));
 448:      * </pre>
 449:      *
 450:      * @param string $statement
 451:      * @param array  $arguments Arguments array containing the query with named
 452:      *                          parameter and assoziative entries array
 453:      *
 454:      * @return string
 455:      */
 456:     protected function _prepareStatementA($statement, array $arguments) {
 457:         if (count($arguments) > 0) {
 458:             foreach ($arguments as $key => $value) {
 459:                 $param = ':' . $key;
 460:                 if (cSecurity::isInteger($value)) {
 461:                     $statement = preg_replace('/' . $param . '/', cSecurity::toInteger($value), $statement);
 462:                     $statement = preg_replace('/\'' . $param . '\'/', '\'' . cSecurity::toInteger($value) . '\'', $statement);
 463:                 } else {
 464:                     $param = cSecurity::toString($param);
 465:                     $statement = preg_replace('/' . $param . '/', cSecurity::escapeString($value), $statement);
 466:                     $statement = preg_replace('/\'' . $param . '\'/', '\'' . cSecurity::escapeString($value) . '\'', $statement);
 467:                     $statement = preg_replace('/`' . $param . '`/', '`' . cSecurity::escapeString($value) . '`', $statement);
 468:                 }
 469:             }
 470:         }
 471: 
 472:         return $statement;
 473:     }
 474: 
 475:     /**
 476:      * Establishes a connection to the database server.
 477:      *
 478:      * @return object resource int NULL value depends on
 479:      *         used driver and is NULL in case of an error.
 480:      */
 481:     public function connect() {
 482:         if (isset($this->_dbCfg['connection']) && $this->_linkId = $this->_getConnection($this->_dbCfg['connection'])) {
 483:             return $this->_linkId;
 484:         } else {
 485:             if ($this->_linkId = $this->getDriver()->connect()) {
 486:                 $this->_setConnection($this->_dbCfg['connection'], $this->_linkId);
 487: 
 488:                 return $this->_linkId;
 489:             }
 490:         }
 491: 
 492:         return NULL;
 493:     }
 494: 
 495:     /**
 496:      * Builds and executes a insert query.
 497:      * String values in passed aFields
 498:      * parameter will be escaped automatically.
 499:      *
 500:      * Example:
 501:      * <pre>
 502:      * $db = cRegistry::getDb();
 503:      * $fields = array(
 504:      * 'idcatart' => $idcatart,
 505:      * 'idlang' => $lang,
 506:      * 'idclient' => $client,
 507:      * 'code' => "<html>... code n' fun ...</html>",
 508:      * );
 509:      * $result = $db->insert($cfg['tab']['code'], $fields);
 510:      * </pre>
 511:      *
 512:      * @param string $tableName The table name
 513:      * @param array  $fields    Assoziative array of fields to insert
 514:      *
 515:      * @return bool
 516:      */
 517:     public function insert($tableName, array $fields) {
 518:         $statement = $this->buildInsert($tableName, $fields);
 519: 
 520:         return $this->query($statement);
 521:     }
 522: 
 523:     /**
 524:      * Builds and returns a insert query.
 525:      * String values in passed fields
 526:      * parameter will be escaped automatically.
 527:      *
 528:      * Example:
 529:      * <pre>
 530:      * $db = cRegistry::getDb();
 531:      * $fields = array(
 532:      * 'idcode' => $idcode,
 533:      * 'idcatart' => $idcatart,
 534:      * 'idlang' => $lang,
 535:      * 'idclient' => $client,
 536:      * 'code' => "<html>... code n' fun ...</html>",
 537:      * );
 538:      * $statement = $db->buildInsert($cfg['tab']['code'], $fields);
 539:      * $db->query($statement);
 540:      * </pre>
 541:      *
 542:      * @param string $tableName The table name
 543:      * @param array  $fields    Assoziative array of fields to insert
 544:      *
 545:      * @return string
 546:      */
 547:     public function buildInsert($tableName, array $fields) {
 548:         return $this->getDriver()->buildInsert($tableName, $fields);
 549:     }
 550: 
 551:     /**
 552:      * Builds and executes a update query.
 553:      * String values in passed fields
 554:      * and whereClauses parameter will be escaped automatically.
 555:      *
 556:      * Example:
 557:      * <pre>
 558:      * $db = cRegistry::getDb();
 559:      * $fields = array('code' => "<html>... some new code n' fun ...</html>");
 560:      * $whereClauses = array('idcode' => 123);
 561:      * $result = $db->update($cfg['tab']['code'], $fields, $whereClauses);
 562:      * </pre>
 563:      *
 564:      * @param string $tableName    The table name
 565:      * @param array  $fields       Assoziative array of fields to update
 566:      * @param array  $whereClauses Assoziative array of field in where clause.
 567:      *                             Multiple entries will be concatenated with AND
 568:      *
 569:      * @return bool
 570:      */
 571:     public function update($tableName, array $fields, array $whereClauses) {
 572:         $statement = $this->buildUpdate($tableName, $fields, $whereClauses);
 573: 
 574:         return $this->query($statement);
 575:     }
 576: 
 577:     /**
 578:      * Builds and returns a update query.
 579:      * String values in passed aFields
 580:      * and aWhere parameter will be escaped automatically.
 581:      *
 582:      * Example:
 583:      * <pre>
 584:      * $db = cRegistry::getDb();
 585:      * $fields = array('code' => "<html>... some new code n' fun ...</html>");
 586:      * $whereClauses = array('idcode' => 123);
 587:      * $statement = $db->buildUpdate($cfg['tab']['code'], $fields,
 588:      * $whereClauses);
 589:      * $db->query($statement);
 590:      * </pre>
 591:      *
 592:      * @param string $tableName    The table name
 593:      * @param array  $fields       Assoziative array of fields to update
 594:      * @param array  $whereClauses Assoziative array of field in where clause.
 595:      *                             Multiple entries will be concatenated with AND
 596:      *
 597:      * @return string
 598:      */
 599:     public function buildUpdate($tableName, array $fields, array $whereClauses) {
 600:         return $this->getDriver()->buildUpdate($tableName, $fields, $whereClauses);
 601:     }
 602: 
 603:     /**
 604:      * Executes the statement.
 605:      * If called with one parameter, it executes the statement directly.
 606:      *
 607:      * Accepts multiple parameter, where the first parameter should be the query
 608:      * and any additional parameter should be the values to replace in format
 609:      * definitions.
 610:      * As an alternative the second parameter cound be also a indexed array with
 611:      * values to replace in format definitions.
 612:      *
 613:      * Other option is to call this function with the statement containing named
 614:      * parameter
 615:      * and the second parameter as a assoziative array with key/value pairs to
 616:      * set in statement.
 617:      *
 618:      * Examples:
 619:      * <pre>
 620:      * // call with one parameter
 621:      * $obj->query('SELECT * FROM `tablename` WHERE id = 123');
 622:      *
 623:      * // call with multiple parameter
 624:      * $obj->query('SELECT * FROM `%s` WHERE id = %d', 'tablename', 123);
 625:      *
 626:      * // 2 parameter where the first is the statement with formatting signs and
 627:      * the second the entries array
 628:      * $obj->query('SELECT * FROM `%s` WHERE id = %d', array('tablename', 123));
 629:      *
 630:      * // 2 parameter where the first is the statement with named parameter and
 631:      * the second the assoziative entries array
 632:      * $obj->query('SELECT * FROM `:mytab` WHERE id = :myid', array('mytab' =>
 633:      * 'tablename', 'myid' => 123));
 634:      * </pre>
 635:      *
 636:      * Accepts additional unlimited parameter, where the parameter will be
 637:      * replaced against formatting sign in query.
 638:      *
 639:      * @param string $statement The SQL statement to execute.
 640:      *
 641:      * @return resource int object bool database driver, false on error
 642:      */
 643:     public function query($statement) {
 644:         // No empty queries, please, since PHP4 chokes on them
 645:         if ($statement == '') {
 646:             // The empty query string is passed on from the constructor, when
 647:             // calling
 648:             // the class without a query, e.g. in situations '$db = new
 649:             // DB_Sql_Subclass;'
 650:             return false;
 651:         }
 652: 
 653:         $arguments = func_get_args();
 654:         if (count($arguments) > 1) {
 655:             array_shift($arguments);
 656:             $statement = $this->_prepareStatement($statement, $arguments);
 657:         }
 658: 
 659:         if (!$this->connect()) {
 660:             return false;
 661:         }
 662: 
 663:         // new query, discard previous result
 664:         if ($this->getQueryId()) {
 665:             $this->free();
 666:         }
 667: 
 668:         if ($this->isProfilingEnabled() === true) {
 669:             $timeStart = microtime(true);
 670:         }
 671: 
 672:         $this->getDriver()->query($statement);
 673: 
 674:         if ($this->isProfilingEnabled() === true) {
 675:             $timeEnd = microtime(true);
 676:             $this->_addProfileData($timeStart, $timeEnd, $statement);
 677:         }
 678: 
 679:         if (!$this->getQueryId()) {
 680:             $this->halt($statement);
 681:         }
 682: 
 683:         // Will return nada if it fails. That's fine.
 684:         return $this->getQueryId();
 685:     }
 686: 
 687:     /**
 688:      * Fetches the next record set from result set
 689:      *
 690:      * @return bool
 691:      */
 692:     public function nextRecord() {
 693:         if (!$this->getQueryId()) {
 694:             $currentModule = cRegistry::getCurrentModuleId();
 695:             if ($currentModule > 0) {
 696:                 $this->halt('next_record called with no query pending in Module ID ' . $currentModule . '.');
 697:             } else {
 698:                 $this->halt('next_record called with no query pending.');
 699:             }
 700: 
 701:             return false;
 702:         }
 703: 
 704:         return $this->getDriver()->nextRecord();
 705:     }
 706: 
 707:     /**
 708:      * This method returns the current result set as object or NULL if no result
 709:      * set is left.
 710:      * If optional param $className is set, the result object is an instance of
 711:      * class $className.
 712:      *
 713:      * @param string $className
 714:      * @return object
 715:      */
 716:     public function getResultObject($className = NULL) {
 717:         return $this->getDriver()->getResultObject($className);
 718:     }
 719: 
 720:     /**
 721:      * Returns number of affected rows from last executed query (update, delete)
 722:      *
 723:      * @return int Number of affected rows
 724:      */
 725:     public function affectedRows() {
 726:         return $this->getDriver()->affectedRows();
 727:     }
 728: 
 729:     /**
 730:      * Returns the number of rows from last executed select query.
 731:      *
 732:      * @return int The number of rows from last select query result
 733:      */
 734:     public function numRows() {
 735:         return $this->getDriver()->numRows();
 736:     }
 737: 
 738:     /**
 739:      * Returns the number of fields (columns) from current record set
 740:      *
 741:      * @return int Number of fields
 742:      */
 743:     public function numFields() {
 744:         return $this->getDriver()->numFields();
 745:     }
 746: 
 747:     /**
 748:      * Discard the query result
 749:      *
 750:      * @return int
 751:      */
 752:     public function free() {
 753:         return $this->getDriver()->free();
 754:     }
 755: 
 756:     /**
 757:      * Escape string for using in SQL-Statement.
 758:      *
 759:      * @param string $string The string to escape
 760:      *
 761:      * @return string Escaped string
 762:      */
 763:     public function escape($string) {
 764:         if (!$this->getLinkId()) {
 765:             $this->connect();
 766:         }
 767: 
 768:         return $this->getDriver()->escape($string);
 769:     }
 770: 
 771:     /**
 772:      * Moves the cursor (position inside current result sets).
 773:      *
 774:      * @param int $iPos The positon to move to inside the current result set
 775:      * @return int
 776:      */
 777:     public function seek($pos) {
 778:         $status = $this->getDriver()->seek($pos);
 779:         if ($status == 0) {
 780:             $this->halt("seek($pos) failed: result has " . $this->numRows() . " rows.");
 781:         }
 782: 
 783:         return $status;
 784:     }
 785: 
 786:     /**
 787:      * Get last inserted id of given table name
 788:      *
 789:      * @return int NULL id of table
 790:      */
 791:     public function getLastInsertedId() {
 792:         $lastId = NULL;
 793: 
 794:         $this->query('SELECT LAST_INSERT_ID() as last_id');
 795:         if ($this->nextRecord()) {
 796:             $lastId = $this->f('last_id');
 797:         }
 798: 
 799:         return $lastId;
 800:     }
 801: 
 802:     /**
 803:      * Parses te table structure and generates a metadata from it.
 804:      *
 805:      * @param string $tableName The table to get metadata or empty string to
 806:      *                          retrieve
 807:      *                          metadata of all tables
 808:      * @param bool   $full      Flag to load full metadata
 809:      *
 810:      * @return array Depends on used database and on parameter $full
 811:      */
 812:     public function getMetaData($tableName = '', $full = false) {
 813:         $databaseName = '';
 814:         $key = (string)$databaseName . '_' . $tableName . '_' . (($full) ? '1' : '0');
 815: 
 816:         if (!isset(self::$_metaCache[$key])) {
 817:             // get meta data
 818:             self::$_metaCache[$key] = $this->getDriver()->getMetaData($tableName, $full);
 819:         }
 820: 
 821:         return self::$_metaCache[$key];
 822:     }
 823: 
 824:     /**
 825:      * Returns names of existing tables.
 826:      *
 827:      * @return array NULL array containing assoziative table data as
 828:      *         follows or NULL:
 829:      *         - $info[$i]['table_name']
 830:      *         - $info[$i]['tablespace_name']
 831:      *         - $info[$i]['database']
 832:      */
 833:     public function getTableNames() {
 834:         if (!$this->connect()) {
 835:             return NULL;
 836:         }
 837: 
 838:         return $this->getDriver()->getTableNames();
 839:     }
 840: 
 841:     /**
 842:      * Returns information about DB server.
 843:      * The return value depends always on
 844:      * used DBMS.
 845:      *
 846:      * @return array NULL array as follows or NULL:
 847:      *         - $arr['description'] (string) Optional, server description
 848:      *         - $arr['version'] (string) Optional, server version
 849:      */
 850:     public function getServerInfo() {
 851:         if (!$this->connect()) {
 852:             return NULL;
 853:         }
 854: 
 855:         return $this->getDriver()->getServerInfo();
 856:     }
 857: 
 858:     /**
 859:      * Closes the connection and frees the query id.
 860:      */
 861:     public function disconnect() {
 862:         $linkId = $this->getLinkId();
 863: 
 864:         if (is_resource($linkId)) {
 865:             $this->getDriver()->disconnect();
 866:             $this->_removeConnection($linkId);
 867:         }
 868: 
 869:         $this->setLinkId(0);
 870:         $this->setQueryId(0);
 871:     }
 872: 
 873:     /**
 874:      * Returns the desired field value from current record set.
 875:      *
 876:      * @param mixed $name    The field name or index position
 877:      * @param mixed $default The default value to return
 878:      *
 879:      * @return mixed The value of field
 880:      */
 881:     public function f($name, $default = NULL) {
 882:         $record = $this->getRecord();
 883: 
 884:         return (isset($record[$name])) ? $record[$name] : $default;
 885:     }
 886: 
 887:     /**
 888:      * Returns current record set as a associative and/or indexed array.
 889:      *
 890:      * @param string $fetchMode One of cDbDriverHandler::FETCH_* constants
 891:      *
 892:      * @return array
 893:      */
 894:     public function toArray($fetchMode = self::FETCH_ASSOC) {
 895:         switch ($fetchMode) {
 896:             case self::FETCH_NUMERIC:
 897:             case self::FETCH_ASSOC:
 898:             case self::FETCH_BOTH:
 899:                 // donut
 900:                 break;
 901:             default:
 902:                 $fetchMode = self::FETCH_ASSOC;
 903:                 break;
 904:         }
 905: 
 906:         $result = array();
 907:         if (is_array($this->getRecord())) {
 908:             foreach ($this->getRecord() as $key => $value) {
 909:                 if ($fetchMode == self::FETCH_ASSOC && !is_numeric($key)) {
 910:                     $result[$key] = $value;
 911:                 } elseif ($fetchMode == self::FETCH_NUMERIC && is_numeric($key)) {
 912:                     $result[$key] = $value;
 913:                 } elseif ($fetchMode == self::FETCH_BOTH) {
 914:                     $result[$key] = $value;
 915:                 }
 916:             }
 917:         }
 918: 
 919:         return $result;
 920:     }
 921: 
 922:     /**
 923:      * Returns current record set as a object
 924:      *
 925:      * @return stdClass
 926:      */
 927:     public function toObject() {
 928:         return (object)$this->toArray(self::FETCH_ASSOC);
 929:     }
 930: 
 931:     /**
 932:      * Error handling
 933:      *
 934:      * Error handler function, delegates passed message to the function
 935:      * reportHalt() if property
 936:      * $this->_haltBehaviour is not set to self::HALT_REPORT.
 937:      *
 938:      * Terminates further script execution if $this->_haltBehaviour is set to
 939:      * self::HALT_YES
 940:      *
 941:      * @param string $message The message to use for error handling
 942:      * @throws cDbException
 943:      */
 944:     public function halt($message) {
 945:         if ($this->_haltBehaviour == self::HALT_REPORT) {
 946:             $this->reportHalt($this->_haltMsgPrefix . $message);
 947:         }
 948: 
 949:         if ($this->_haltBehaviour == self::HALT_YES) {
 950:             throw new cDbException($message);
 951:         }
 952:     }
 953: 
 954:     /**
 955:      * Logs passed message, basically the last db error to the error log.
 956:      * Concatenates a detailed error message and invoke PHP's error_log()
 957:      * method.
 958:      *
 959:      * @param string $message
 960:      */
 961:     public function reportHalt($message) {
 962:         $errorNumber = $this->getErrorNumber();
 963:         $errorMessage = $this->getErrorMessage();
 964: 
 965:         if (!$errorMessage) {
 966:             $errorMessage = $this->getDriver()->getErrorMessage();
 967:         }
 968: 
 969:         if (!$errorNumber) {
 970:             $errorNumber = $this->getDriver()->getErrorNumber();
 971:         }
 972: 
 973:         $message = sprintf("Database failure: %s (%s) - %s\n", $errorNumber, $errorMessage, $message);
 974:         cWarning(__FILE__, __LINE__, $message);
 975:     }
 976: 
 977:     /**
 978:      * Returns the number of rows from last executed select query.
 979:      *
 980:      * @return int The number of rows from last select query result
 981:      * @see cDbDriverHandler::numRows
 982:      */
 983:     public function num_rows() {
 984:         return $this->numRows();
 985:     }
 986: 
 987:     /**
 988:      * Returns number of affected rows from last executed query (update, delete)
 989:      *
 990:      * @return int Number of affected rows
 991:      * @see cDbDriverHandler::affectedRows
 992:      */
 993:     public function affected_rows() {
 994:         return $this->affectedRows();
 995:     }
 996: 
 997:     /**
 998:      * Returns the number of fields (columns) from current record set
 999:      *
1000:      * @return int Number of fields
1001:      * @see cDbDriverHandler::numFields
1002:      */
1003:     public function num_fields() {
1004:         return $this->numFields();
1005:     }
1006: 
1007:     /**
1008:      * Fetches the next record set from result set
1009:      *
1010:      * @return bool
1011:      * @see cDbDriverHandler::nextRecord
1012:      */
1013:     public function next_record() {
1014:         return $this->nextRecord();
1015:     }
1016: }
CMS CONTENIDO 4.9.5 API documentation generated by ApiGen 2.8.0