* @link http://www.pradosoft.com/ * @copyright Copyright © 2005 PradoSoft * @license http://www.pradosoft.com/license/ * @version $Id$ * @package System.DataAccess */ /** * Include the database provider base class. */ Prado::using('System.DataAccess.TDatabaseProvider'); /** * TAdodb database connection module. * * The TAdodb module class allows the database connection details to be * specified in the application.xml or config.xml, the later are directory level * configurations. * * ... * * ... * * ... * * ... * * Where mysql is the driver name, username and * password are the required credentials to connection to the database, * localhost is the database resource and mydatabase is the * name of database to connect to. * * The Adodb library supports many database drivers. The drivers included are * # mysql MySQL without transactions. * # mysqlt MySQL 3.23 or later with transaction support. * # mysqli MySQLi extension, does not support transactions. * # pdo_mysql PDO driver for MysSQL. * * # oracle Oracle 7. * # oci8po Portable version of oci8 driver. * # oci8 Oracle (oci8). * # oci805 Oracle 8.0.5 driver. * # pdo_oci PDO driver for Oracle. * # odbc_oracle Oracle support via ODBC. * * # postgres7 Postgres 7, 8. * # pdo_pgsql PDO driver for postgres. * # postgres64 Postgress 6.4. * * # pdo_mssql PDO driver for MSSQL. * # odbc_mssql MSSQL support via ODBC. * # mssqlpo Portable MSSQL Driver that supports || instead of +. * # ado_mssql Microsoft SQL Server ADO data driver. * # mssql Native mssql driver. * * # ldap LDAP. * # sqlite SQLite database. * * For other database drivers and detail documentation regarding indiviual * drivers visit {@link http://adodb.sourceforge. net/} * * When using an sqlite database it is easier to specify the {@link setDriver * Driver} as "sqlite" and {@link setHost Host} as the path to the sqlite * database file. For example: * * * * Note that the database file should not contain no dots. The path can * be use namespace or a fullpath (but no dots). * * To access the database from a TPage or other TApplicationComponent classes * use the {@link TApplication::getModule getModule} method of TApplication. * * $db = $this->getApplication()->getModule('my_db1'); * //similarly * $db = $this->Application->Modules['my_db1']; * * * For classes that are not instance of TApplicationComponent (such as * TUserManager) use the static {@link PradoBase::getApplication getApplication} * method first. * * $db = Prado::getApplication()->getModule('my_db1'); * * * If you wish to use a Adodb connections without module configuration, see the * TAdodbConnection class. * * @author Wei Zhuo * @version $Id$ * @package System.DataAccess * @since 3.0 */ class TAdodb extends TDatabaseProvider { /** * @var string Adodb associative fetch mode. */ const FETCH_ASSOCIATIVE='associative'; /** * @var string Adodb numeric fetch mode. */ const FETCH_NUMERIC='numeric'; /** * @var string Adodb fetch mode using both associative and numeric. */ const FETCH_BOTH='both'; /** * @var string Adodb default fetch mode. */ const FETCH_DEFAULT='default'; /** * @var TAdodbConnection database connection. */ private $_connection = null; /** * @var string Adodb record set cache directory. */ private $_cachedir=''; /** * @var string current fetch mode. */ private $_fetchMode = 'associative'; /** * @var boolean whether to enable the active recors. */ private $_enableActiveRecords = false; /** * @return TAdodbConnection connects to the database and returns the * connection resource. */ public function getConnection() { $this->init(null); return $this->_connection; } /** * Initialize the module configurations. */ public function init($config) { parent::init($config); if(!class_exists('ADOConnection', false)) $this->importAdodbLibrary(); if(is_null($this->_connection)) { if($config instanceof TAdodbConnection) $this->_connection = $config; else $this->_connection = new TAdodbConnection($this); if($this->getEnableActiveRecords()) $this->initializeActiveRecords(); } } /** * Enabling Adodb to retrieve results as active records, and active record * object to save changes. Once set to true and the connection is * initialized, setting EnableActiveRecords to false has no effect. * @param boolean true to allow active records. */ public function setEnableActiveRecords($value) { $this->_enableActiveRecords = TPropertyValue::ensureBoolean($value); } /** * @param boolean whether to enable active records. */ public function getEnableActiveRecords() { return $this->_enableActiveRecords; } /** * Initialize the active records by setting the active records database * adpater to the current database connection. */ public function initializeActiveRecords() { $conn = $this->_connection; if(!is_null($conn->getInternalConnection()) || $conn->open()) { Prado::using('System.DataAccess.TActiveRecord'); TActiveRecord::setDatabaseAdapter($conn->getInternalConnection()); $this->_enableActiveRecords = true; } } /** * @return string the adodb library path. */ protected function getAdodbLibrary() { return Prado::getPathOfNamespace('System.3rdParty.adodb'); } /** * Import the necessary adodb library files. */ protected function importAdodbLibrary() { $path = $this->getAdodbLibrary(); require($path.'/adodb-exceptions.inc.php'); require($path.'/adodb.inc.php'); } /** * @return string the cache directory for Adodb to save cached queries. */ public function getCacheDir() { return $this->_cachedir; } /** * The cache directory for Adodb to save cached queries. The path can be * specified using a namespace or the fullpath. * @param string the cache directory for adodb module */ public function setCacheDir($value) { $this->_cachedir=Prado::getPathOfNamespace($value); } /** * @return string fetch mode of queried data */ public function getFetchMode() { return $this->_fetchMode; } /** * Sets the fetch mode of query data, valid modes are Associative, * Numeric, Both or Default. The mode names are * case insensitive. * @param string the fetch mode of query data */ public function setFetchMode($value) { $value = strtolower($value); if($value===self::FETCH_ASSOCIATIVE || $value===self::FETCH_NUMERIC || $value===self::FETCH_BOTH) $this->_fetchMode=$value; else $this->_fetchMode=self::FETCH_DEFAULT; } } /** * TAdodbConnection provides access to the ADODB ADOConnection class. For detail * documentation regarding indiviual drivers visit {@link http://adodb.sourceforge.net/} * * You can call any method implemented in ADOConnection class via TAdodbConnection, * such as TAdodbConnection::FetchRow(), and so on. The method calls * will be passed an ADOConnection instance. * * To use TAdodbConnection without the TAdodb database connection provider pass * a DSN style connection string to the TAdodbConnection constructor. * * $dsn = "mysql://username:password@localhost/mydb"; * $db = new TAdodbConnection($dsn); * $resultSet = $db->execute('...'); * * * @author Wei Zhuo * @version $Id$ * @package System.DataAccess * @since 3.0 */ class TAdodbConnection extends TDbConnection { /** * @var ADOConnection database connection. */ private $_connection; /** * Gets the internal connection. Should only be used by framework * developers. */ public function getInternalConnection() { return $this->_connection; } /** * Constructor, initialize a new Adodb connection. * @param string|TAdodb DSN connection string or a TAdodb */ public function __construct($provider=null) { if(is_string($provider)) $this->initProvider($provider); else parent::__construct($provider); } /** * Create a new provider for this connection using the DSN string. * @param string DSN connection string. */ protected function initProvider($connectionString) { $provider = new TAdodb(); $provider->setConnectionString($connectionString); $this->setProvider($provider); } /** * Cleanup work before serializing. * This is a PHP defined magic method. * @return array the names of instance-variables to serialize. */ public function __sleep() { //close any open connections before serializing. $this->close(); $this->_connection = null; } /** * This method will be automatically called when unserialization happens. * This is a PHP defined magic method. */ public function __wakeup() { } /** * PHP magic function. * This method will pass all method calls to ADOConnection class * provided in the ADODB library. * @param mixed method name * @param mixed method call parameters * @param mixed return value of the method call */ public function __call($method, $params) { if(is_null($this->_connection) || !$this->_connection->IsConnected()) $this->open(); return call_user_func_array(array($this->_connection,$method),$params); } /** * @return boolean true if the database is connected. */ public function getIsClosed() { return is_null($this->_connection) || !$this->_connection->IsConnected(); } /** * Prepares (compiles) an SQL query for repeated execution. Bind parameters * are denoted by ?, except for the oci8 driver, which uses the traditional * Oracle :varname convention. If there is an error, or we are emulating * Prepare( ), we return the original $sql string. * * Prepare( ) cannot be used with functions that use SQL query rewriting * techniques, e.g. PageExecute( ) and SelectLimit( ). * * @param string sql statement. * @return array an array containing the original sql statement in the first * array element; */ public function prepare($statement) { return $this->_connection->prepare($statement); } /** * Execute SQL statement $sql and return derived class of ADORecordSet if * successful. Note that a record set is always returned on success, even if * we are executing an insert or update statement. You can also pass in $sql * a statement prepared in {@link prepare}. */ public function execute($sql, $parameters=array()) { return $this->_connection->execute($sql, $parameters); } /** * Start a transaction on this connection. */ public function beginTransaction() { return $this->_connection->StartTrans(); } /** * End a transaction successfully. * @return true if successful. If the database does not support * transactions, will return true also as data is always committed. */ public function commit() { return $this->_connection->CommitTrans(); } /** * End a transaction, rollback all changes. * @return true if successful. If the database does not support * transactions, will return false as data is never rollbacked. */ public function rollback() { return $this->_connection->RollbackTrans(); } /** * Establishes a DB connection. * An ADOConnection instance will be created if none. */ public function open() { if($this->getIsClosed()) { $provider = $this->getProvider(); $provider->init($this); if(strlen($provider->getConnectionString()) < 1) { if(strlen($provider->getDriver()) < 1) throw new TDbConnectionException('db_driver_required'); $this->_connection=ADONewConnection($provider->getDriver()); $this->initConnection(); } else $this->_connection=ADONewConnection($provider->getConnectionString()); $this->initFetchMode(); $this->initCacheDir(); } return $this->_connection->IsConnected(); } /** * Creates the database connection using host, username, password and * database name properties. */ protected function initConnection() { $provider = $this->getProvider(); if(is_int(strpos($provider->getConnectionOptions(), 'persist'))) { $this->_connection->PConnect($provider->getHost(), $provider->getUsername(),$provider->getPassword(), $provider->getDatabase()); } else { $this->_connection->Connect($provider->getHost(), $provider->getUsername(),$provider->getPassword(), $provider->getDatabase()); } } /** * Initialize the fetch mode. */ protected function initFetchMode() { global $ADODB_FETCH_MODE; $provider = $this->getProvider(); if($provider->getFetchMode()===TAdodb::FETCH_ASSOCIATIVE) $ADODB_FETCH_MODE=ADODB_FETCH_ASSOC; else if($provider->fetchMode===TAdodb::FETCH_NUMERIC) $ADODB_FETCH_MODE=ADODB_FETCH_NUM; else if($provider->fetchMode===TAdodb::FETCH_BOTH) $ADODB_FETCH_MODE=ADODB_FETCH_BOTH; else $ADODB_FETCH_MODE=ADODB_FETCH_DEFAULT; } /** * Initialize the cache directory. */ protected function initCacheDir() { global $ADODB_CACHE_DIR; $provider = $this->getProvider(); if($provider->getCacheDir()!=='') $ADODB_CACHE_DIR=$provider->getCacheDir(); } /** * Closes the DB connection. * You are not required to call this method as PHP will automatically * to close any DB connections when exiting a script. */ public function close() { if(!is_null($this->_connection) && $this->_connection->IsConnected()) $this->_connection->Close(); } /** * @param string quote a string to be sent to the database. * @param boolean if true it ensure that the variable is not quoted twice, * once by quote and once by the magic_quotes_gpc. * @return string database specified quoted string */ public function quote($string, $magic_quotes=false) { return $this->_connection->qstr($string, $magic_quotes); } } ?>