Overview

Packages

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