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