Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for Oracle ETL DataEndpoint (readonly) #34

Merged
merged 19 commits into from
Jan 23, 2017
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
151 changes: 85 additions & 66 deletions classes/CCR/DB.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,75 +19,94 @@
namespace CCR;

use xd_utilities;
use \Exception;
use Exception;
use CCR\DB\iDatabase;

class DB
{
// An array (pool) of database connection handles, one per configuration file section

private static $instancePool = array();

// Ensure that this class is a singleton

private function __construct() {}

// ================================================================================
// Cleanup
// ================================================================================

public function __destruct() {}

// ================================================================================
// Create an instance of the database singleton. A single argument is
// required, which is configuration file section identifier (e.g. [datawarehouse]).
// The database connection parameters in that section will be used to create the
// instance, which will be cached for re-use by subsequent requests targeting the
// same section.
//
// @throws Exception if there is an invalid number of arguments
//
// @returns An instance of the database class
// ================================================================================

public static function factory($section, $autoConnect = true)
{
// If this section has been used before in creating a database instance (handle), then
// it will have been cached. In this case, the cached handle will be returned.

if ( array_key_exists($section, self::$instancePool) ) {
return self::$instancePool[$section];
}

$engine = xd_utilities\getConfiguration($section, 'db_engine');
$host = xd_utilities\getConfiguration($section, 'host');
$database = xd_utilities\getConfiguration($section, 'database');
$user = xd_utilities\getConfiguration($section, 'user');
$passwd = xd_utilities\getConfiguration($section, 'pass');
$port = xd_utilities\getConfiguration($section, 'port');

$engine = "CCR\\DB\\$engine";

// Ensure that the class exists before we attempt to instantiate it

if ( class_exists($engine) ) {
$db = new $engine($host, $port, $database, $user, $passwd);
} else {
$msg = "Error creating database '" . $options->name . "', class '$className' not found";
throw new Exception($msg);
}

// All database interfaces must implement iDatabase

if ( ! $db instanceof iDatabase ) {
throw new Exception("$engine does not implenment interface iDatabase");
}

self::$instancePool[$section] = $db;
if ($autoConnect) self::$instancePool[$section]->connect();

return self::$instancePool[$section];

} // factory()
// An array (pool) of database connection handles, one per configuration file section

private static $instancePool = array();

// Ensure that this class is a singleton

private function __construct() {}

// ================================================================================
// Cleanup
// ================================================================================

public function __destruct() {}

// ================================================================================
// Create an instance of the database singleton. A single argument is
// required, which is configuration file section identifier (e.g. [datawarehouse]).
// The database connection parameters in that section will be used to create the
// instance, which will be cached for re-use by subsequent requests targeting the
// same section.
//
// @param $sectionName Name of the configuration section containing database parameters
// @param $autoConnect If TRUE, connect to the database after creating the object
//
// @throws Exception if there is an invalid number of arguments
//
// @returns An instance of the database class
// ================================================================================

public static function factory($sectionName, $autoConnect = true)
{
// If this section has been used before in creating a database instance (handle), then
// it will have been cached. In this case, the cached handle will be returned.

if ( array_key_exists($sectionName, self::$instancePool) ) {
return self::$instancePool[$sectionName];
}

try {
$iniSection = xd_utilities\getConfigurationSection($sectionName, 'db_engine');
} catch (Exception $e) {
$msg = "Unable to get database configuration options: " . $e->getMessage();
throw new Exception ($msg);
}

// Not all engines are required to specify all configuration options (e.g., Oracle) so
// allow NULL (empty) options. Specific engines may enforce additional requirements.

$engine = ( array_key_exists('db_engine', $iniSection) ? $iniSection['db_engine'] : null);
$database = ( array_key_exists('database', $iniSection) ? $iniSection['database'] : null);
$user = ( array_key_exists('user', $iniSection) ? $iniSection['user'] : null );

if ( null === $engine || null === $database || null === $user ) {
$msg = "Configuration section '$sectionName' missing required options (db_engine, database, user)";
throw new Exception($msg);
}

$password = ( array_key_exists('pass', $iniSection) ? $iniSection['pass'] : null );
$host = ( array_key_exists('host', $iniSection) ? $iniSection['host'] : null );
$port = ( array_key_exists('port', $iniSection) ? $iniSection['port'] : null );

$engine = "CCR\\DB\\$engine";

// Ensure that the class exists before we attempt to instantiate it

if ( class_exists($engine) ) {
$db = new $engine($host, $port, $database, $user, $password);
} else {
$msg = "Error creating database defined in section '$sectionName', class '$engine' not found";
throw new Exception($msg);
}

// All database interfaces must implement iDatabase

if ( ! $db instanceof iDatabase ) {
throw new Exception("$engine does not implenment interface iDatabase");
}

self::$instancePool[$sectionName] = $db;
if ($autoConnect) self::$instancePool[$sectionName]->connect();

return self::$instancePool[$sectionName];

} // factory()

} // class DB
26 changes: 15 additions & 11 deletions classes/CCR/DB/MySQLDB.php
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
<?php
/*
/*
* @author Amin Ghadersohi
* @date 2010-Jul-07
*
* The top interface for mysql dbs using pdo driver
*
*
* Changelog
*
* 2015-12-15 Steve Gallo <smgallo@buffalo.edu>
Expand All @@ -13,18 +13,22 @@

namespace CCR\DB;

use Exception;

class MySQLDB
extends PDODB
implements iDatabase
{
function __construct($db_host,$db_port,$db_name,$db_username,$db_password)
// ------------------------------------------------------------------------------------------
// @see iDatabase::__construct()
// ------------------------------------------------------------------------------------------

function __construct($db_host, $db_port, $db_name, $db_username, $db_password, $dsn_extra = null)
{
$dsn = 'mysql:host=' . $db_host . ';port=' . $db_port . ';dbname=' . $db_name . ';charset=utf8';
parent::__construct("mysql",$db_host,$db_port,$db_name,$db_username,$db_password, $dsn);
if ( null == $db_host || null === $db_name || null === $db_username ) {
$msg = "Database engine " . __CLASS__ . " requires (host, database, username)";
throw new Exception($msg);
}
parent::__construct("mysql", $db_host, $db_port, $db_name, $db_username, $db_password, 'charset=utf8');
}
function __destruct()
{
parent::__destruct();
}

}
} // class MySQLDB
136 changes: 119 additions & 17 deletions classes/CCR/DB/OracleDB.php
Original file line number Diff line number Diff line change
@@ -1,22 +1,124 @@
<?php
/*
* @author Amin Ghadersohi
* @date 2013-Jul-08
*
* The top interface for oracle dbs using pdo driver
*
*/
/* ==========================================================================================
* XDMoD driver for accessing the Oracle database. PHP built-in support for Oracle (OCI8)
* must be built against Oracle client libraries. The PDO_OCI PECL module is deprecated
* and internal PDO_OCI support must be compiled from source (and is also out of date) so
* we are using the PDOOCI wrapper from https://github.com/taq/pdooci.
*
* Support for both Easy Connect Naming and Local Naming (via tnsnames.ora) is
* supported. Note that in order to use Local Naming, the TNS_ADMIN environment variable
* must be set (this is used by the OCI driver).
*
* @author Steve Gallo
* @date 2017-01-17
* ==========================================================================================
*/

namespace CCR\DB;

use Exception;

class OracleDB extends PDODB
{
function __construct($db_host,$db_port,$db_name,$db_username,$db_password)
{
parent::__construct("oci",$db_host,$db_port,$db_name,$db_username,$db_password, "oci:dbname=$db_name");
}
function __destruct()
{
parent::__destruct();
}
}
?>
/* ------------------------------------------------------------------------------------------
* Set up the machinery. Oracle requires at minimum a database name (local naming,
* this resolves to an entry in tnsnames.org) or a name, host, and optionally a port
* (easy connect naming).
*
* Note: We do not support the $dsn_override that PDODB supports.
*
* @see PDODB::__construct()
*
* @throw Exception If minimum parameters were not provided.
*
* @see iDatabase::__construct()
* ------------------------------------------------------------------------------------------
*/

public function __construct($db_host, $db_port, $db_name, $db_username, $db_password, $dsn_extra = null)
{
// At a minimum we must have either the (db_name) or the (db_host, db_name)

if ( null === $db_name ) {
$msg = __CLASS__
. ' requires at a minimum (db_name) for Local Naming '
. ' or (db_host, db_name[, db_port]) for Easy Connect Naming';
throw new Exception($msg);
}

parent::__construct(
"oci",
$db_host,
$db_port,
$db_name,
$db_username,
$db_password
);

} // __construct()

/* ------------------------------------------------------------------------------------------
* Clean up after ourselves and close the connection. Unlike standard PDO setting the
* connection to NULL OCI has an oci_close() function.
* ------------------------------------------------------------------------------------------
*/

public function __destruct()
{
if ( null !== $this->_dbh) {
$this->_dbh->close();
}
} // __destruct()

/* ------------------------------------------------------------------------------------------
* Connect to the server.
*
* @return The database connection handle
*
* @throw Exception If there was a connection error
* ------------------------------------------------------------------------------------------
*/

public function connect()
{
if ( null !== $this->_dbh ) {
return $this->_dbh;
}

$namingMethod = null;

// If the host is not set then assume we are using Easy Connect
// https://docs.oracle.com/database/121/NETAG/naming.htm#NETAG008
// For example oci:dbname=//localhost:1521/mydb
//
// Otherwise assume Local Naming (via tnsnames.ora)
// https://docs.oracle.com/database/121/NETAG/naming.htm#NETAG081
// For example oci:dbname=mydb

if ( null === $this->_db_host ) {
$this->_dsn = 'oci:dbname=' . $this->_db_name;
$namingMethod = "Local";
} else {
$this->_dsn = 'oci:dbname=//'
. $this->_db_host
. ( null !== $this->_db_port ? ':' . $this->_db_port : '' )
. '/' . $this->_db_name;
$namingMethod = "Easy Connect";
}


try {
$this->_dbh = @new \PDOOCI\PDO($this->_dsn, $this->_db_username, $this->_db_password);
$this->_dbh->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);

} catch (\PDOException $e) {
$msg = __CLASS__
. " Error connecting to database '" . $this->_dsn . "' using $namingMethod Naming. "
. $e->getMessage();
throw new Exception($msg);
}

return $this->_dbh;

} // connect()
} // class OracleDB
Loading