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