/** * A method to return a singleton database connection resource. * * Example usage: * $oDbh = OA_DB::singleton(); * * Warning: In order to work correctly, the singleton method must * be instantiated statically and by reference, as in the above * example. * * @static * @param string $dsn Optional database DSN details - connects to the * database defined by the configuration file otherwise. * See {@link OA_DB::getDsn()} for format. * * @param array $aDriverOptions An optional array of driver options. Currently * supported options are: * - For MySQL: * ['ssl'] = false|true Perform connection over SSL? * ['ca'] = Name of CA file, if "ssl" true * ['capath'] = Path to CA file above, is "ssl" true * ['compress'] = false|true Use client compression? * * @return MDB2_Driver_Common An MDB2 connection resource, or PEAR_Error * on failure to connect. */ static function singleton($dsn = null, $aDriverOptions = array()) { $aConf = $GLOBALS['_MAX']['CONF']; // Get the driver options, if not set if (!is_array($aDriverOptions) || is_null($dsn) && empty($aDriverOptions)) { $aDriverOptions = OA_DB::getDsnOptions(); } // Get the DSN, if not set $dsn = is_null($dsn) ? OA_DB::getDsn() : $dsn; // Check that the parameter is a string, not an array if (is_array($dsn)) { return Max::raiseError('Bad argument: DSN should be a string', MAX_ERROR_INVALIDARGS); } // A hack to allow for installation on pgsql // If the configuration hasn't been defined prevent // loading mysql MDB2 driver. if (strpos($dsn, '//:@') !== false) { // Return a silent error return new PEAR_Error('Bad argument: Empty DSN'); } // Get the database type in use from the DNS, not from the // configuration file $aDSN = MDB2::parseDSN($dsn); $databaseType = $aDSN['phptype']; // Is this a MySQL database connection that should happen via SSL? if (strcasecmp($databaseType, 'mysql') === 0 && @$aDriverOptions['ssl']) { // Modify the DSN string to include the required CA and CAPATH options if (!empty($aDriverOptions['ca']) && !empty($aDriverOptions['capath'])) { $dsn .= "?ca={$aDriverOptions['ca']}&capth={$aDriverOptions['capath']}"; } } // Create an MD5 checksum of the DSN $dsnMd5 = md5($dsn); // Does this database connection already exist? if (isset($GLOBALS['_OA']['CONNECTIONS'])) { $aConnections = array_keys($GLOBALS['_OA']['CONNECTIONS']); } else { $aConnections = array(); } if (!(count($aConnections) > 0) || !in_array($dsnMd5, $aConnections)) { // Prepare options for a new database connection $aOptions = array(); // Sequence column name $aOptions['seqcol_name'] = 'id'; // Set the index name format $aOptions['idxname_format'] = '%s'; // Use 4 decimal places in DECIMAL nativetypes $aOptions['decimal_places'] = 4; // Set the portability options $aOptions['portability'] = OA_DB_MDB2_DEFAULT_OPTIONS; // Set the default table type for MySQL, if appropriate if (strcasecmp($databaseType, 'mysql') === 0) { if (!empty($aConf['table']['type'])) { $aOptions['default_table_type'] = $aConf['table']['type']; // Enable transaction support when using InnoDB tables if (strcasecmp($aOptions['default_table_type'], 'innodb') === 0) { // Enable transaction support $aOptions['use_transactions'] = true; } } } elseif (strcasecmp($databaseType, 'pgsql') === 0) { $aOptions['quote_identifier'] = true; } // Add default charset - custom OpenX if (defined('OA_DB_MDB2_DEFAULT_CHARSET')) { $aOptions['default_charset'] = OA_DB_MDB2_DEFAULT_CHARSET; } else { $aOptions['default_charset'] = 'utf8'; } // this will log select queries to a var/sql.log // currently used for analysis purposes if (isset($aConf['debug']['logSQL']) && $aConf['debug']['logSQL']) { $aOptions['log_statements'] = explode('|', $aConf['debug']['logSQL']); $aOptions['debug'] = true; $aOptions['debug_handler'] = 'logSQL'; } $aOptions += OA_DB::getDatatypeMapOptions(); // Is this a MySQL database connection? if (strcasecmp($databaseType, 'mysql') === 0) { // Should this connection happen over SSL? if (@$aDriverOptions['ssl']) { $aOptions['ssl'] = true; } } // Create the new database connection OA::disableErrorHandling(); $oDbh = MDB2::singleton($dsn, $aOptions); OA::enableErrorHandling(); if (PEAR::isError($oDbh)) { return $oDbh; } // Is this a MySQL database connection? if (strcasecmp($databaseType, 'mysql') === 0) { $client_flags = 0; // Should this connection happen over SSL? if (@$aDriverOptions['ssl']) { $client_flags = $client_flags | MYSQL_CLIENT_SSL; } // Should this connection use compression? if (@$aDriverOptions['compress']) { $client_flags = $client_flags | MYSQL_CLIENT_COMPRESS; } // Are there any MySQL connection flags to set? if ($client_flags != 0) { $oDbh->dsn['client_flags'] = $client_flags; } } OA::disableErrorHandling(); $success = $oDbh->connect(); OA::enableErrorHandling(); if (PEAR::isError($success)) { return $success; } // Set charset if needed $success = OA_DB::setCharset($oDbh); if (PEAR::isError($success)) { return $success; } // Set schema if needed $success = OA_DB::setSchema($oDbh); if (PEAR::isError($success)) { return $success; } // Set the fetchmode to be use used $oDbh->setFetchMode(MDB2_FETCHMODE_ASSOC); // Load modules that are likely to be needed $oDbh->loadModule('Extended'); $oDbh->loadModule('Datatype'); $oDbh->loadModule('Manager'); // Store the database connection $GLOBALS['_OA']['CONNECTIONS'][$dsnMd5] = $oDbh; // Set MySQL 4 compatibility if needed if (strcasecmp($databaseType, 'mysql') === 0 && !empty($aConf['database']['mysql4_compatibility'])) { $oDbh->exec("SET SESSION sql_mode='MYSQL40'"); } } return $GLOBALS['_OA']['CONNECTIONS'][$dsnMd5]; }
setupConfigVariables(); @set_time_limit(600); OX_increaseMemoryLimit(OX_getMinimumRequiredMemory('cache')); error_reporting(E_ALL & ~(E_NOTICE | E_WARNING | E_DEPRECATED | E_STRICT)); if (!is_writable(RV_PATH . '/etc/xmlcache')) { die("=> The directory " . RV_PATH . '/etc/xmlcache' . " is not writable\n"); } require RV_PATH . '/lib/OA/DB/Table.php'; // Create a database mock so we will not have to connect to database itself require_once RV_PATH . '/lib/simpletest/mock_objects.php'; require_once 'MDB2/Driver/mysql.php'; Mock::generatePartial('MDB2_Driver_mysql', 'MDB2_Mock', array()); $oDbh = new MDB2_Mock(); $oDbh->__construct(); // add datatype mapping $aDatatypeOptions = OA_DB::getDatatypeMapOptions(); MDB2::setOptions($oDbh, $aDatatypeOptions); $oCache = new OA_DB_XmlCache(); $aOptions = array('force_defaults' => false); $aSkipFiles = array(); clean_up(); // Generate XML caches generateXmlCache(glob(RV_PATH . '/etc/tables_*.xml')); generateXmlCache(glob(RV_PATH . '/etc/changes/schema_tables_*.xml')); generateXmlCache(glob(RV_PATH . '/etc/changes/changes_tables_*.xml'), 'parseChangesetDefinitionFile'); echo "=> FINISHED REFRESHING THE MDB2 SCHEMA XML FILE CACHE\n\n"; function generateXmlCache($xmlFiles, $callback = 'parseDatabaseDefinitionFile') { global $aSkipFiles, $aOptions, $oDbh, $oCache; foreach ($xmlFiles as $fileName) { if (!in_array(baseName($fileName), $aSkipFiles)) {