Merge branch 'pdo'

Conflicts:
	CHANGELOG
pull/18/head
Aleksander Machniak 12 years ago
commit de56ea1909

@ -1,6 +1,8 @@
CHANGELOG Roundcube Webmail
===========================
- Add new DB abstraction layer based on PHP PDO, supporting SQLite3 (#1488332)
- Removed PEAR::MDB2 package
- Removed users.alias column, added option ('user_aliases')
to use email address from identities as username (#1488581)
- Removed redundant cache.cache_id column (#1488528)
@ -1387,7 +1389,3 @@ RELEASE 0.1-RC1
Now based on the message structure delivered by the IMAP server.
- Fixed some XSS and SQL injection issues
- Fixed charset problems with folder renaming

@ -12,11 +12,10 @@ REQUIREMENTS
* The Apache, Lighttpd, Cherokee or Hiawatha web server
* .htaccess support allowing overrides for DirectoryIndex
* PHP Version 5.2.1 or greater including
- PCRE, DOM, JSON, XML, Session, Sockets (required)
- PDO, PCRE, DOM, JSON, XML, Session, Sockets (required)
- libiconv (recommended)
- mbstring, fileinfo, mcrypt (optional)
* PEAR packages distributed with Roundcube or external:
- MDB2 2.5.0 or newer
- Mail_Mime 1.8.1 or newer
- Mail_mimeDecode 1.5.5 or newer
- Net_SMTP 1.4.2 or newer
@ -34,7 +33,7 @@ REQUIREMENTS
- magic_quotes_sybase disabled
* PHP compiled with OpenSSL to connect to IMAPS and to use the spell checker
* A MySQL (4.0.8 or newer), PostgreSQL, MSSQL database engine
or the SQLite extension for PHP
or SQLite support in PHP
* One of the above databases with permission to create tables
* An SMTP server (recommended) or PHP configured for mail delivery

@ -143,7 +143,7 @@ if ($RCI->configured) {
// check database schema
if ($RCI->config['db_dsnw']) {
$DB = new rcube_mdb2($RCI->config['db_dsnw'], '', false);
$DB = rcube_db::factory($RCI->config['db_dsnw'], '', false);
$DB->db_connect('w');
if ($db_error_msg = $DB->is_error()) {
echo "Error connecting to database: $db_error_msg\n";

@ -6,7 +6,8 @@ $required_php_exts = array(
'DOM' => 'dom',
'Session' => 'session',
'XML' => 'xml',
'JSON' => 'json'
'JSON' => 'json',
'PDO' => 'PDO',
);
$optional_php_exts = array(
@ -21,19 +22,11 @@ $optional_php_exts = array(
$required_libs = array(
'PEAR' => 'PEAR.php',
'MDB2' => 'MDB2.php',
'Net_SMTP' => 'Net/SMTP.php',
'Net_IDNA2' => 'Net/IDNA2.php',
'Mail_mime' => 'Mail/mime.php',
);
$supported_dbs = array(
'MySQL' => 'mysql',
'MySQLi' => 'mysqli',
'PostgreSQL' => 'pgsql',
'SQLite (v2)' => 'sqlite',
);
$ini_checks = array(
'file_uploads' => 1,
'session.auto_start' => 0,
@ -63,8 +56,14 @@ $source_urls = array(
'DOM' => 'http://www.php.net/manual/en/book.dom.php',
'Intl' => 'http://www.php.net/manual/en/book.intl.php',
'Exif' => 'http://www.php.net/manual/en/book.exif.php',
'PDO' => 'http://www.php.net/manual/en/book.pdo.php',
'pdo_mysql' => 'http://www.php.net/manual/en/book.pdo-mysql.php',
'pdo_pgsql' => 'http://www.php.net/manual/en/book.pdo-pgsql.php',
'pdo_sqlite' => 'http://www.php.net/manual/en/book.pdo-sqlite.php',
'pdo_sqlite2' => 'http://www.php.net/manual/en/book.pdo-sqlite.php',
'pdo_sqlsrv' => 'http://www.php.net/manual/en/book.pdo-sqlsrv.php',
'pdo_dblib' => 'http://www.php.net/manual/en/book.pdo-dblib.php',
'PEAR' => 'http://pear.php.net',
'MDB2' => 'http://pear.php.net/package/MDB2',
'Net_SMTP' => 'http://pear.php.net/package/Net_SMTP',
'Mail_mime' => 'http://pear.php.net/package/Mail_mime',
'Net_IDNA2' => 'http://pear.php.net/package/Net_IDNA2',
@ -129,14 +128,14 @@ foreach ($optional_php_exts as $name => $ext) {
<?php
$prefix = (PHP_SHLIB_SUFFIX === 'dll') ? 'php_' : '';
foreach ($supported_dbs as $database => $ext) {
foreach ($RCI->supported_dbs as $database => $ext) {
if (extension_loaded($ext)) {
$RCI->pass($database);
}
else {
$_ext = $ext_dir . '/' . $prefix . $ext . '.' . PHP_SHLIB_SUFFIX;
$msg = @is_readable($_ext) ? 'Could be loaded. Please add in php.ini' : 'Not installed';
$RCI->na($database, $msg, $source_urls[$database]);
$msg = @is_readable($_ext) ? 'Could be loaded. Please add in php.ini' : '';
$RCI->na($database, $msg, $source_urls[$ext]);
}
echo '<br />';
}

@ -267,13 +267,8 @@ echo $input_syslogfacility->show($RCI->getprop('syslog_facility'), LOG_USER);
<p>Database settings for read/write operations:</p>
<?php
require_once 'MDB2.php';
$supported_dbs = array('MySQL' => 'mysql', 'MySQLi' => 'mysqli',
'PgSQL' => 'pgsql', 'SQLite' => 'sqlite');
$select_dbtype = new html_select(array('name' => '_dbtype', 'id' => "cfgdbtype"));
foreach ($supported_dbs AS $database => $ext) {
foreach ($RCI->supported_dbs as $database => $ext) {
if (extension_loaded($ext)) {
$select_dbtype->add($database, $ext);
}
@ -284,7 +279,7 @@ $input_dbname = new html_inputfield(array('name' => '_dbname', 'size' => 20, 'id
$input_dbuser = new html_inputfield(array('name' => '_dbuser', 'size' => 20, 'id' => "cfgdbuser"));
$input_dbpass = new html_passwordfield(array('name' => '_dbpass', 'size' => 20, 'id' => "cfgdbpass"));
$dsnw = MDB2::parseDSN($RCI->getprop('db_dsnw'));
$dsnw = rcube_db::parse_dsn($RCI->getprop('db_dsnw'));
echo $select_dbtype->show($RCI->is_post ? $_POST['_dbtype'] : $dsnw['phptype']);
echo '<label for="cfgdbtype">Database type</label><br />';

@ -50,6 +50,17 @@ class rcube_install
'des_key', 'session_lifetime', 'support_url',
);
// list of supported database drivers
var $supported_dbs = array(
'MySQL' => 'pdo_mysql',
'PostgreSQL' => 'pdo_pgsql',
'SQLite' => 'pdo_sqlite',
'SQLite (v2)' => 'pdo_sqlite2',
'SQL Server (SQLSRV)' => 'pdo_sqlsrv',
'SQL Server (DBLIB)' => 'pdo_dblib',
);
/**
* Constructor
*/
@ -371,7 +382,7 @@ class rcube_install
$errors[] = "Missing columns in table '$table': " . join(',', $diff);
}
}
return !empty($errors) ? $errors : false;
}
@ -394,87 +405,8 @@ class rcube_install
}
}
}
return $schema;
}
/**
* Compare the local database schema with the reference schema
* required for this version of Roundcube
*
* @param boolean True if the schema schould be updated
* @return boolean True if the schema is up-to-date, false if not or an error occured
*/
function mdb2_schema_check($update = false)
{
if (!$this->configured)
return false;
$options = array(
'use_transactions' => false,
'log_line_break' => "\n",
'idxname_format' => '%s',
'debug' => false,
'quote_identifier' => true,
'force_defaults' => false,
'portability' => true
);
$dsnw = $this->config['db_dsnw'];
$schema = MDB2_Schema::factory($dsnw, $options);
$schema->db->supported['transactions'] = false;
if (PEAR::isError($schema)) {
$this->raise_error(array('code' => $schema->getCode(), 'message' => $schema->getMessage() . ' ' . $schema->getUserInfo()));
return false;
}
else {
$definition = $schema->getDefinitionFromDatabase();
$definition['charset'] = 'utf8';
if (PEAR::isError($definition)) {
$this->raise_error(array('code' => $definition->getCode(), 'message' => $definition->getMessage() . ' ' . $definition->getUserInfo()));
return false;
}
// load reference schema
$dsn_arr = MDB2::parseDSN($this->config['db_dsnw']);
$ref_schema = INSTALL_PATH . 'SQL/' . $dsn_arr['phptype'] . '.schema.xml';
if (is_readable($ref_schema)) {
$reference = $schema->parseDatabaseDefinition($ref_schema, false, array(), $schema->options['fail_on_invalid_names']);
if (PEAR::isError($reference)) {
$this->raise_error(array('code' => $reference->getCode(), 'message' => $reference->getMessage() . ' ' . $reference->getUserInfo()));
}
else {
$diff = $schema->compareDefinitions($reference, $definition);
if (empty($diff)) {
return true;
}
else if ($update) {
// update database schema with the diff from the above check
$success = $schema->alterDatabase($reference, $definition, $diff);
if (PEAR::isError($success)) {
$this->raise_error(array('code' => $success->getCode(), 'message' => $success->getMessage() . ' ' . $success->getUserInfo()));
}
else
return true;
}
echo '<pre>'; var_dump($diff); echo '</pre>';
return false;
}
}
else
$this->raise_error(array('message' => "Could not find reference schema file ($ref_schema)"));
return false;
}
return false;
return $schema;
}

@ -125,9 +125,9 @@ else {
$db_working = false;
if ($RCI->configured) {
if (!empty($RCI->config['db_dsnw'])) {
$DB = new rcube_mdb2($RCI->config['db_dsnw'], '', false);
$DB = rcube_db::factory($RCI->config['db_dsnw'], '', false);
$DB->db_connect('w');
if (!($db_error_msg = $DB->is_error())) {
$RCI->pass('DSN (write)');
echo '<br />';
@ -167,7 +167,7 @@ else if ($db_working && $_POST['updatedb']) {
// test database
if ($db_working) {
$db_read = $DB->query("SELECT count(*) FROM {$RCI->config['db_table_users']}");
if ($DB->db_error) {
if ($DB->is_error()) {
$RCI->fail('DB Schema', "Database not initialized");
echo '<p><input type="submit" name="initdb" value="Initialize database" /></p>';
$db_working = false;

@ -23,7 +23,6 @@ function __autoload($classname)
{
$filename = preg_replace(
array(
'/MDB2_(.+)/',
'/Mail_(.+)/',
'/Net_(.+)/',
'/Auth_(.+)/',
@ -31,7 +30,6 @@ function __autoload($classname)
'/^utf8$/'
),
array(
'MDB2/\\1',
'Mail/\\1',
'Net/\\1',
'Auth/\\1',

@ -26,7 +26,7 @@ class rcube_sql_password
else if (!is_array($dsn) && !preg_match('/\?new_link=true/', $dsn))
$dsn .= '?new_link=true';
$db = new rcube_mdb2($dsn, '', FALSE);
$db = rcube_db::factory($dsn, '', false);
$db->set_debug((bool)$rcmail->config->get('sql_debug'));
$db->db_connect('w');
}

@ -151,10 +151,10 @@ class squirrelmail_usercopy extends rcube_plugin
$this->prefs = array();
/* connect to squirrelmail database */
$db = new rcube_mdb2($rcmail->config->get('squirrelmail_dsn'));
$db->db_connect('r'); // connect in read mode
$db = rcube_db::factory($rcmail->config->get('squirrelmail_dsn'));
// $db->set_debug(true);
$db->set_debug($rcmail->config->get('sql_debug'));
$db->db_connect('r'); // connect in read mode
/* retrieve prefs */
$userprefs_table = $rcmail->config->get('squirrelmail_userprefs_table');

@ -49,14 +49,14 @@ class rcube
/**
* Instace of database class.
*
* @var rcube_mdb2
* @var rcube_pdo
*/
public $db;
/**
* Instace of Memcache class.
*
* @var rcube_mdb2
* @var Memcache
*/
public $memcache;
@ -160,15 +160,13 @@ class rcube
/**
* Get the current database connection
*
* @return rcube_mdb2 Database connection object
* @return rcube_pdo Database connection object
*/
public function get_dbh()
{
if (!$this->db) {
$config_all = $this->config->all();
$this->db = new rcube_mdb2($config_all['db_dsnw'], $config_all['db_dsnr'], $config_all['db_persistent']);
$this->db->sqlite_initials = INSTALL_PATH . 'SQL/sqlite.initial.sql';
$this->db = rcube_db::factory($config_all['db_dsnw'], $config_all['db_dsnr'], $config_all['db_persistent']);
$this->db->set_debug((bool)$config_all['sql_debug']);
}

@ -33,9 +33,9 @@
class rcube_cache
{
/**
* Instance of rcube_mdb2 or Memcache class
* Instance of database handler
*
* @var rcube_mdb2/Memcache
* @var rcube_db|Memcache|bool
*/
private $db;
private $type;

@ -36,7 +36,7 @@ class rcube_contacts extends rcube_addressbook
/**
* Store database connection.
*
* @var rcube_mdb2
* @var rcube_db
*/
private $db = null;
private $user_id = 0;
@ -934,8 +934,8 @@ class rcube_contacts extends rcube_addressbook
$contact_id
);
if ($this->db->db_error)
$this->set_error(self::ERROR_SAVING, $this->db->db_error_msg);
if ($error = $this->db->is_error())
$this->set_error(self::ERROR_SAVING, $error);
else
$added++;
}
@ -990,9 +990,10 @@ class rcube_contacts extends rcube_addressbook
$checkname);
// append number to make name unique
if ($hit = $this->db->num_rows($sql_result))
if ($hit = $this->db->fetch_array($sql_result)) {
$checkname = $name . ' ' . $num++;
} while ($hit > 0);
}
} while ($hit);
return $checkname;
}

@ -0,0 +1,992 @@
<?php
/**
+-----------------------------------------------------------------------+
| program/include/rcube_db.php |
| |
| This file is part of the Roundcube Webmail client |
| Copyright (C) 2005-2012, The Roundcube Dev Team |
| |
| Licensed under the GNU General Public License version 3 or |
| any later version with exceptions for skins & plugins. |
| See the README file for a full license statement. |
| |
| PURPOSE: |
| Database wrapper class that implements PHP PDO functions |
| |
+-----------------------------------------------------------------------+
| Author: Aleksander Machniak <alec@alec.pl> |
+-----------------------------------------------------------------------+
*/
/**
* Database independent query interface
*
* This is a wrapper for the PHP PDO
*
* @package Database
* @version 1.0
*/
class rcube_db
{
protected $db_dsnw; // DSN for write operations
protected $db_dsnr; // DSN for read operations
protected $db_connected = false; // Already connected ?
protected $db_mode; // Connection mode
protected $dbh; // Connection handle
protected $db_error = false;
protected $db_error_msg = '';
protected $conn_failure = false;
protected $a_query_results = array('dummy');
protected $last_res_id = 0;
protected $db_index = 0;
protected $tables;
protected $variables;
protected $options = array(
// column/table quotes
'identifier_start' => '"',
'identifier_end' => '"',
);
/**
* Factory, returns driver-specific instance of the class
*
* @param string $db_dsnw DSN for read/write operations
* @param string $db_dsnr Optional DSN for read only operations
* @param bool $pconn Enables persistent connections
*
* @return rcube_db Object instance
*/
public static function factory($db_dsnw, $db_dsnr = '', $pconn = false)
{
$driver = strtolower(substr($db_dsnw, 0, strpos($db_dsnw, ':')));
$driver_map = array(
'sqlite2' => 'sqlite',
'sybase' => 'mssql',
'dblib' => 'mssql',
'mysqli' => 'mysql',
);
$driver = isset($driver_map[$driver]) ? $driver_map[$driver] : $driver;
$class = "rcube_db_$driver";
if (!class_exists($class)) {
rcube::raise_error(array('code' => 600, 'type' => 'db',
'line' => __LINE__, 'file' => __FILE__,
'message' => "Configuration error. Unsupported database driver: $driver"),
true, true);
}
return new $class($db_dsnw, $db_dsnr, $pconn);
}
/**
* Object constructor
*
* @param string $db_dsnw DSN for read/write operations
* @param string $db_dsnr Optional DSN for read only operations
* @param bool $pconn Enables persistent connections
*/
public function __construct($db_dsnw, $db_dsnr = '', $pconn = false)
{
if (empty($db_dsnr)) {
$db_dsnr = $db_dsnw;
}
$this->db_dsnw = $db_dsnw;
$this->db_dsnr = $db_dsnr;
$this->db_pconn = $pconn;
$this->db_dsnw_array = self::parse_dsn($db_dsnw);
$this->db_dsnr_array = self::parse_dsn($db_dsnr);
// Initialize driver class
$this->init();
}
/**
* Initialization of the object with driver specific code
*/
protected function init()
{
// To be used by driver classes
}
/**
* Connect to specific database
*
* @param array $dsn DSN for DB connections
*
* @return PDO database handle
*/
protected function dsn_connect($dsn)
{
$this->db_error = false;
$this->db_error_msg = null;
// Get database specific connection options
$dsn_string = $this->dsn_string($dsn);
$dsn_options = $this->dsn_options($dsn);
if ($db_pconn) {
$dsn_options[PDO::ATTR_PERSISTENT] = true;
}
// Connect
try {
// with this check we skip fatal error on PDO object creation
if (!class_exists('PDO', false)) {
throw new Exception('PDO extension not loaded. See http://php.net/manual/en/intro.pdo.php');
}
$this->conn_prepare($dsn);
$dbh = new PDO($dsn_string, $dsn['username'], $dsn['password'], $dsn_options);
// don't throw exceptions or warnings
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT);
}
catch (Exception $e) {
$this->db_error = true;
$this->db_error_msg = $e->getMessage();
rcube::raise_error(array('code' => 500, 'type' => 'db',
'line' => __LINE__, 'file' => __FILE__,
'message' => $this->db_error_msg), true, false);
return null;
}
$this->conn_configure($dsn, $dbh);
return $dbh;
}
/**
* Driver-specific preparation of database connection
*
* @param array $dsn DSN for DB connections
*/
protected function conn_prepare($dsn)
{
}
/**
* Driver-specific configuration of database connection
*
* @param array $dsn DSN for DB connections
* @param PDO $dbh Connection handler
*/
protected function conn_configure($dsn, $dbh)
{
}
/**
* Driver-specific database character set setting
*
* @param string $charset Character set name
*/
protected function set_charset($charset)
{
$this->query("SET NAMES 'utf8'");
}
/**
* Connect to appropiate database depending on the operation
*
* @param string $mode Connection mode (r|w)
*/
public function db_connect($mode)
{
// previous connection failed, don't attempt to connect again
if ($this->conn_failure) {
return;
}
// no replication
if ($this->db_dsnw == $this->db_dsnr) {
$mode = 'w';
}
// Already connected
if ($this->db_connected) {
// connected to db with the same or "higher" mode
if ($this->db_mode == 'w' || $this->db_mode == $mode) {
return;
}
}
$dsn = ($mode == 'r') ? $this->db_dsnr_array : $this->db_dsnw_array;
$this->dbh = $this->dsn_connect($dsn);
$this->db_connected = is_object($this->dbh);
// use write-master when read-only fails
if (!$this->db_connected && $mode == 'r') {
$mode = 'w';
$this->dbh = $this->dsn_connect($this->db_dsnw_array);
$this->db_connected = is_object($this->dbh);
}
if ($this->db_connected) {
$this->db_mode = $mode;
$this->set_charset('utf8');
}
else {
$this->conn_failure = true;
}
}
/**
* Activate/deactivate debug mode
*
* @param boolean $dbg True if SQL queries should be logged
*/
public function set_debug($dbg = true)
{
$this->options['debug_mode'] = $dbg;
}
/**
* Writes debug information/query to 'sql' log file
*
* @param string $query SQL query
*/
protected function debug($query)
{
if ($this->options['debug_mode']) {
rcube::write_log('sql', '[' . (++$this->db_index) . '] ' . $query . ';');
}
}
/**
* Getter for error state
*
* @return boolean True on error
*/
public function is_error()
{
return $this->db_error ? $this->db_error_msg : false;
}
/**
* Connection state checker
*
* @return boolean True if in connected state
*/
public function is_connected()
{
return !is_object($this->dbh) ? false : $this->db_connected;
}
/**
* Is database replication configured?
*
* @return bool Returns true if dsnw != dsnr
*/
public function is_replicated()
{
return !empty($this->db_dsnr) && $this->db_dsnw != $this->db_dsnr;
}
/**
* Get database runtime variables
*
* @param string $varname Variable name
* @param mixed $default Default value if variable is not set
*
* @return mixed Variable value or default
*/
public function get_variable($varname, $default = null)
{
// to be implemented by driver class
return $default;
}
/**
* Execute a SQL query
*
* @param string SQL query to execute
* @param mixed Values to be inserted in query
*
* @return number Query handle identifier
*/
public function query()
{
$params = func_get_args();
$query = array_shift($params);
// Support one argument of type array, instead of n arguments
if (count($params) == 1 && is_array($params[0])) {
$params = $params[0];
}
return $this->_query($query, 0, 0, $params);
}
/**
* Execute a SQL query with limits
*
* @param string SQL query to execute
* @param int Offset for LIMIT statement
* @param int Number of rows for LIMIT statement
* @param mixed Values to be inserted in query
*
* @return int Query handle identifier
*/
public function limitquery()
{
$params = func_get_args();
$query = array_shift($params);
$offset = array_shift($params);
$numrows = array_shift($params);
return $this->_query($query, $offset, $numrows, $params);
}
/**
* Execute a SQL query with limits
*
* @param string $query SQL query to execute
* @param int $offset Offset for LIMIT statement
* @param int $numrows Number of rows for LIMIT statement
* @param array $params Values to be inserted in query
*
* @return int Query handle identifier
*/
protected function _query($query, $offset, $numrows, $params)
{
// Read or write ?
$mode = preg_match('/^(select|show)/i', ltrim($query)) ? 'r' : 'w';
$this->db_connect($mode);
// check connection before proceeding
if (!$this->is_connected()) {
return null;
}
if ($numrows || $offset) {
$query = $this->set_limit($query, $numrows, $offset);
}
$params = (array) $params;
// Because in Roundcube we mostly use queries that are
// executed only once, we will not use prepared queries
$pos = 0;
$idx = 0;
while ($pos = strpos($query, '?', $pos)) {
$val = $this->quote($params[$idx++]);
unset($params[$idx-1]);
$query = substr_replace($query, $val, $pos, 1);
$pos += strlen($val);
}
$query = rtrim($query, ';');
$this->debug($query);
$query = $this->dbh->query($query);
if ($query === false) {
$error = $this->dbh->errorInfo();
$this->db_error = true;
$this->db_error_msg = sprintf('[%s] %s', $error[1], $error[2]);
rcube::raise_error(array('code' => 500, 'type' => 'db',
'line' => __LINE__, 'file' => __FILE__,
'message' => $this->db_error_msg), true, false);
}
// add result, even if it's an error
return $this->_add_result($query);
}
/**
* Get number of affected rows for the last query
*
* @param number $res_id Optional query handle identifier
*
* @return int Number of rows or false on failure
*/
public function affected_rows($res_id = null)
{
if ($result = $this->_get_result($res_id)) {
return $result->rowCount();
}
return 0;
}
/**
* Get last inserted record ID
*
* @param string $table Table name (to find the incremented sequence)
*
* @return mixed ID or false on failure
*/
public function insert_id($table = '')
{
if (!$this->db_connected || $this->db_mode == 'r') {
return false;
}
if ($table) {
// resolve table name
$table = $this->table_name($table);
}
$id = $this->dbh->lastInsertId($table);
return $id;
}
/**
* Get an associative array for one row
* If no query handle is specified, the last query will be taken as reference
*
* @param int $res_id Optional query handle identifier
*
* @return mixed Array with col values or false on failure
*/
public function fetch_assoc($res_id = null)
{
$result = $this->_get_result($res_id);
return $this->_fetch_row($result, PDO::FETCH_ASSOC);
}
/**
* Get an index array for one row
* If no query handle is specified, the last query will be taken as reference
*
* @param int $res_id Optional query handle identifier
*
* @return mixed Array with col values or false on failure
*/
public function fetch_array($res_id = null)
{
$result = $this->_get_result($res_id);
return $this->_fetch_row($result, PDO::FETCH_NUM);
}
/**
* Get col values for a result row
*
* @param PDOStatement $result Result handle
* @param int $mode Fetch mode identifier
*
* @return mixed Array with col values or false on failure
*/
protected function _fetch_row($result, $mode)
{
if (!is_object($result) || !$this->is_connected()) {
return false;
}
return $result->fetch($mode);
}
/**
* Adds LIMIT,OFFSET clauses to the query
*
* @param string $query SQL query
* @param int $limit Number of rows
* @param int $offset Offset
*
* @return string SQL query
*/
protected function set_limit($query, $limit = 0, $offset = 0)
{
if ($limit) {
$query .= ' LIMIT ' . intval($limit);
}
if ($offset) {
$query .= ' OFFSET ' . intval($offset);
}
return $query;
}
/**
* Returns list of tables in a database
*
* @return array List of all tables of the current database
*/
public function list_tables()
{
// get tables if not cached
if ($this->tables === null) {
$q = $this->query('SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES ORDER BY TABLE_NAME');
if ($res = $this->_get_result($q)) {
$this->tables = $res->fetchAll(PDO::FETCH_COLUMN, 0);
}
else {
$this->tables = array();
}
}
return $this->tables;
}
/**
* Returns list of columns in database table
*
* @param string $table Table name
*
* @return array List of table cols
*/
public function list_cols($table)
{
$q = $this->query('SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = ?',
array($table));
if ($res = $this->_get_result($q)) {
return $res->fetchAll(PDO::FETCH_COLUMN, 0);
}
return array();
}
/**
* Formats input so it can be safely used in a query
*
* @param mixed $input Value to quote
* @param string $type Type of data
*
* @return string Quoted/converted string for use in query
*/
public function quote($input, $type = null)
{
// handle int directly for better performance
if ($type == 'integer' || $type == 'int') {
return intval($input);
}
// create DB handle if not available
if (!$this->dbh) {
$this->db_connect('r');
}
if ($this->dbh) {
$map = array(
'bool' => PDO::PARAM_BOOL,
'integer' => PDO::PARAM_INT,
);
$type = isset($map[$type]) ? $map[$type] : PDO::PARAM_STR;
return $this->dbh->quote($input, $type);
}
return 'NULL';
}
/**
* Quotes a string so it can be safely used as a table or column name
*
* @param string $str Value to quote
*
* @return string Quoted string for use in query
* @deprecated Replaced by rcube_db::quote_identifier
* @see rcube_db::quote_identifier
*/
public function quoteIdentifier($str)
{
return $this->quote_identifier($str);
}
/**
* Quotes a string so it can be safely used as a table or column name
*
* @param string $str Value to quote
*
* @return string Quoted string for use in query
*/
public function quote_identifier($str)
{
$start = $this->options['identifier_start'];
$end = $this->options['identifier_end'];
$name = array();
foreach (explode('.', $str) as $elem) {
$elem = str_replace(array($start, $end), '', $elem);
$name[] = $start . $elem . $end;
}
return implode($name, '.');
}
/**
* Return SQL function for current time and date
*
* @return string SQL function to use in query
*/
public function now()
{
return "now()";
}
/**
* Return list of elements for use with SQL's IN clause
*
* @param array $arr Input array
* @param string $type Type of data
*
* @return string Comma-separated list of quoted values for use in query
*/
public function array2list($arr, $type = null)
{
if (!is_array($arr)) {
return $this->quote($arr, $type);
}
foreach ($arr as $idx => $item) {
$arr[$idx] = $this->quote($item, $type);
}
return implode(',', $arr);
}
/**
* Return SQL statement to convert a field value into a unix timestamp
*
* This method is deprecated and should not be used anymore due to limitations
* of timestamp functions in Mysql (year 2038 problem)
*
* @param string $field Field name
*
* @return string SQL statement to use in query
* @deprecated
*/
public function unixtimestamp($field)
{
return "UNIX_TIMESTAMP($field)";
}
/**
* Return SQL statement to convert from a unix timestamp
*
* @param int $timestamp Unix timestamp
*
* @return string Date string in db-specific format
*/
public function fromunixtime($timestamp)
{
return date("'Y-m-d H:i:s'", $timestamp);
}
/**
* Return SQL statement for case insensitive LIKE
*
* @param string $column Field name
* @param string $value Search value
*
* @return string SQL statement to use in query
*/
public function ilike($column, $value)
{
return $this->quote_identifier($column).' LIKE '.$this->quote($value);
}
/**
* Abstract SQL statement for value concatenation
*
* @return string SQL statement to be used in query
*/
public function concat(/* col1, col2, ... */)
{
$args = func_get_args();
if (is_array($args[0])) {
$args = $args[0];
}
return '(' . join(' || ', $args) . ')';
}
/**
* Encodes non-UTF-8 characters in string/array/object (recursive)
*
* @param mixed $input Data to fix
*
* @return mixed Properly UTF-8 encoded data
*/
public static function encode($input)
{
if (is_object($input)) {
foreach (get_object_vars($input) as $idx => $value) {
$input->$idx = self::encode($value);
}
return $input;
}
else if (is_array($input)) {
foreach ($input as $idx => $value) {
$input[$idx] = self::encode($value);
}
return $input;
}
return utf8_encode($input);
}
/**
* Decodes encoded UTF-8 string/object/array (recursive)
*
* @param mixed $input Input data
*
* @return mixed Decoded data
*/
public static function decode($input)
{
if (is_object($input)) {
foreach (get_object_vars($input) as $idx => $value) {
$input->$idx = self::decode($value);
}
return $input;
}
else if (is_array($input)) {
foreach ($input as $idx => $value) {
$input[$idx] = self::decode($value);
}
return $input;
}
return utf8_decode($input);
}
/**
* Adds a query result and returns a handle ID
*
* @param object $res Query handle
*
* @return int Handle ID
*/
protected function _add_result($res)
{
$this->last_res_id = sizeof($this->a_query_results);
$this->a_query_results[$this->last_res_id] = $res;
return $this->last_res_id;
}
/**
* Resolves a given handle ID and returns the according query handle
* If no ID is specified, the last resource handle will be returned
*
* @param int $res_id Handle ID
*
* @return mixed Resource handle or false on failure
*/
protected function _get_result($res_id = null)
{
if ($res_id == null) {
$res_id = $this->last_res_id;
}
if (!empty($this->a_query_results[$res_id])) {
return $this->a_query_results[$res_id];
}
return false;
}
/**
* Return correct name for a specific database table
*
* @param string $table Table name
*
* @return string Translated table name
*/
public function table_name($table)
{
$rcube = rcube::get_instance();
// return table name if configured
$config_key = 'db_table_'.$table;
if ($name = $rcube->config->get($config_key)) {
return $name;
}
return $table;
}
/**
* MDB2 DSN string parser
*
* @param string $sequence Secuence name
*
* @return array DSN parameters
*/
public static function parse_dsn($dsn)
{
if (empty($dsn)) {
return null;
}
// Find phptype and dbsyntax
if (($pos = strpos($dsn, '://')) !== false) {
$str = substr($dsn, 0, $pos);
$dsn = substr($dsn, $pos + 3);
}
else {
$str = $dsn;
$dsn = null;
}
// Get phptype and dbsyntax
// $str => phptype(dbsyntax)
if (preg_match('|^(.+?)\((.*?)\)$|', $str, $arr)) {
$parsed['phptype'] = $arr[1];
$parsed['dbsyntax'] = !$arr[2] ? $arr[1] : $arr[2];
}
else {
$parsed['phptype'] = $str;
$parsed['dbsyntax'] = $str;
}
if (empty($dsn)) {
return $parsed;
}
// Get (if found): username and password
// $dsn => username:password@protocol+hostspec/database
if (($at = strrpos($dsn,'@')) !== false) {
$str = substr($dsn, 0, $at);
$dsn = substr($dsn, $at + 1);
if (($pos = strpos($str, ':')) !== false) {
$parsed['username'] = rawurldecode(substr($str, 0, $pos));
$parsed['password'] = rawurldecode(substr($str, $pos + 1));
}
else {
$parsed['username'] = rawurldecode($str);
}
}
// Find protocol and hostspec
// $dsn => proto(proto_opts)/database
if (preg_match('|^([^(]+)\((.*?)\)/?(.*?)$|', $dsn, $match)) {
$proto = $match[1];
$proto_opts = $match[2] ? $match[2] : false;
$dsn = $match[3];
}
// $dsn => protocol+hostspec/database (old format)
else {
if (strpos($dsn, '+') !== false) {
list($proto, $dsn) = explode('+', $dsn, 2);
}
if ( strpos($dsn, '//') === 0
&& strpos($dsn, '/', 2) !== false
&& $parsed['phptype'] == 'oci8'
) {
//oracle's "Easy Connect" syntax:
//"username/password@[//]host[:port][/service_name]"
//e.g. "scott/tiger@//mymachine:1521/oracle"
$proto_opts = $dsn;
$pos = strrpos($proto_opts, '/');
$dsn = substr($proto_opts, $pos + 1);
$proto_opts = substr($proto_opts, 0, $pos);
}
else if (strpos($dsn, '/') !== false) {
list($proto_opts, $dsn) = explode('/', $dsn, 2);
}
else {
$proto_opts = $dsn;
$dsn = null;
}
}
// process the different protocol options
$parsed['protocol'] = (!empty($proto)) ? $proto : 'tcp';
$proto_opts = rawurldecode($proto_opts);
if (strpos($proto_opts, ':') !== false) {
list($proto_opts, $parsed['port']) = explode(':', $proto_opts);
}
if ($parsed['protocol'] == 'tcp') {
$parsed['hostspec'] = $proto_opts;
}
else if ($parsed['protocol'] == 'unix') {
$parsed['socket'] = $proto_opts;
}
// Get dabase if any
// $dsn => database
if ($dsn) {
// /database
if (($pos = strpos($dsn, '?')) === false) {
$parsed['database'] = rawurldecode($dsn);
// /database?param1=value1&param2=value2
}
else {
$parsed['database'] = rawurldecode(substr($dsn, 0, $pos));
$dsn = substr($dsn, $pos + 1);
if (strpos($dsn, '&') !== false) {
$opts = explode('&', $dsn);
}
else { // database?param1=value1
$opts = array($dsn);
}
foreach ($opts as $opt) {
list($key, $value) = explode('=', $opt);
if (!array_key_exists($key, $parsed) || false === $parsed[$key]) {
// don't allow params overwrite
$parsed[$key] = rawurldecode($value);
}
}
}
}
return $parsed;
}
/**
* Returns PDO DSN string from DSN array
*
* @param array $dsn DSN parameters
*
* @return string DSN string
*/
protected function dsn_string($dsn)
{
$params = array();
$result = $dsn['phptype'] . ':';
if ($dsn['hostspec']) {
$params[] = 'host=' . $dsn['hostspec'];
}
if ($dsn['port']) {
$params[] = 'port=' . $dsn['port'];
}
if ($dsn['database']) {
$params[] = 'dbname=' . $dsn['database'];
}
if (!empty($params)) {
$result .= implode(';', $params);
}
return $result;
}
/**
* Returns driver-specific connection options
*
* @param array $dsn DSN parameters
*
* @return array Connection options
*/
protected function dsn_options($dsn)
{
$result = array();
return $result;
}
}

@ -0,0 +1,155 @@
<?php
/**
+-----------------------------------------------------------------------+
| program/include/rcube_db_mssql.php |
| |
| This file is part of the Roundcube Webmail client |
| Copyright (C) 2005-2012, The Roundcube Dev Team |
| |
| Licensed under the GNU General Public License version 3 or |
| any later version with exceptions for skins & plugins. |
| See the README file for a full license statement. |
| |
| PURPOSE: |
| Database wrapper class that implements PHP PDO functions |
| for MS SQL Server database |
| |
+-----------------------------------------------------------------------+
| Author: Aleksander Machniak <alec@alec.pl> |
+-----------------------------------------------------------------------+
*/
/**
* Database independent query interface
*
* This is a wrapper for the PHP PDO
*
* @package Database
* @version 1.0
*/
class rcube_db_mssql extends rcube_db
{
/**
* Driver initialization
*/
protected function init()
{
$this->options['identifier_start'] = '[';
$this->options['identifier_end'] = ']';
}
/**
* Character setting
*/
protected function set_charset($charset)
{
// UTF-8 is default
}
/**
* Return SQL function for current time and date
*
* @return string SQL function to use in query
*/
public function now()
{
return "getdate()";
}
/**
* Return SQL statement to convert a field value into a unix timestamp
*
* This method is deprecated and should not be used anymore due to limitations
* of timestamp functions in Mysql (year 2038 problem)
*
* @param string $field Field name
*
* @return string SQL statement to use in query
* @deprecated
*/
public function unixtimestamp($field)
{
return "DATEDIFF(second, '19700101', $field) + DATEDIFF(second, GETDATE(), GETUTCDATE())";
}
/**
* Abstract SQL statement for value concatenation
*
* @return string SQL statement to be used in query
*/
public function concat(/* col1, col2, ... */)
{
$args = func_get_args();
if (is_array($args[0])) {
$args = $args[0];
}
return '(' . join('+', $args) . ')';
}
/**
* Adds TOP (LIMIT,OFFSET) clause to the query
*
* @param string $query SQL query
* @param int $limit Number of rows
* @param int $offset Offset
*
* @return string SQL query
*/
protected function set_limit($query, $limit = 0, $offset = 0)
{
$limit = intval($limit);
$offset = intval($offset);
$orderby = stristr($query, 'ORDER BY');
if ($orderby !== false) {
$sort = (stripos($orderby, ' desc') !== false) ? 'desc' : 'asc';
$order = str_ireplace('ORDER BY', '', $orderby);
$order = trim(preg_replace('/\bASC\b|\bDESC\b/i', '', $order));
}
$query = preg_replace('/^SELECT\s/i', 'SELECT TOP ' . ($limit + $offset) . ' ', $query);
$query = 'SELECT * FROM (SELECT TOP ' . $limit . ' * FROM (' . $query . ') AS inner_tbl';
if ($orderby !== false) {
$query .= ' ORDER BY ' . $order . ' ';
$query .= (stripos($sort, 'asc') !== false) ? 'DESC' : 'ASC';
}
$query .= ') AS outer_tbl';
if ($orderby !== false) {
$query .= ' ORDER BY ' . $order . ' ' . $sort;
}
return $query;
}
/**
* Returns PDO DSN string from DSN array
*/
protected function dsn_string($dsn)
{
$params = array();
$result = $dsn['phptype'] . ':';
if ($dsn['hostspec']) {
$host = $dsn['hostspec'];
if ($dsn['port']) {
$host .= ',' . $dsn['port'];
}
$params[] = 'host=' . $host;
}
if ($dsn['database']) {
$params[] = 'dbname=' . $dsn['database'];
}
if (!empty($params)) {
$result .= implode(';', $params);
}
return $result;
}
}

@ -0,0 +1,154 @@
<?php
/**
+-----------------------------------------------------------------------+
| program/include/rcube_db_mysql.php |
| |
| This file is part of the Roundcube Webmail client |
| Copyright (C) 2005-2012, The Roundcube Dev Team |
| |
| Licensed under the GNU General Public License version 3 or |
| any later version with exceptions for skins & plugins. |
| See the README file for a full license statement. |
| |
| PURPOSE: |
| Database wrapper class that implements PHP PDO functions |
| for MySQL database |
| |
+-----------------------------------------------------------------------+
| Author: Aleksander Machniak <alec@alec.pl> |
+-----------------------------------------------------------------------+
*/
/**
* Database independent query interface
*
* This is a wrapper for the PHP PDO
*
* @package Database
* @version 1.0
*/
class rcube_db_mysql extends rcube_db
{
/**
* Driver initialization/configuration
*/
protected function init()
{
// SQL identifiers quoting
$this->options['identifier_start'] = '`';
$this->options['identifier_end'] = '`';
}
/**
* Abstract SQL statement for value concatenation
*
* @return string SQL statement to be used in query
*/
public function concat(/* col1, col2, ... */)
{
$args = func_get_args();
if (is_array($args[0])) {
$args = $args[0];
}
return 'CONCAT(' . join(', ', $args) . ')';
}
/**
* Returns PDO DSN string from DSN array
*
* @param array $dsn DSN parameters
*
* @return string Connection string
*/
protected function dsn_string($dsn)
{
$params = array();
$result = 'mysql:';
if ($dsn['database']) {
$params[] = 'dbname=' . $dsn['database'];
}
if ($dsn['hostspec']) {
$params[] = 'host=' . $dsn['hostspec'];
}
if ($dsn['port']) {
$params[] = 'port=' . $dsn['port'];
}
if ($dsn['socket']) {
$params[] = 'unix_socket=' . $dsn['socket'];
}
$params[] = 'charset=utf8';
if (!empty($params)) {
$result .= implode(';', $params);
}
return $result;
}
/**
* Returns driver-specific connection options
*
* @param array $dsn DSN parameters
*
* @return array Connection options
*/
protected function dsn_options($dsn)
{
$result = array();
if (!empty($dsn['key'])) {
$result[PDO::MYSQL_ATTR_KEY] = $dsn['key'];
}
if (!empty($dsn['cipher'])) {
$result[PDO::MYSQL_ATTR_CIPHER] = $dsn['cipher'];
}
if (!empty($dsn['cert'])) {
$result[PDO::MYSQL_ATTR_SSL_CERT] = $dsn['cert'];
}
if (!empty($dsn['capath'])) {
$result[PDO::MYSQL_ATTR_SSL_CAPATH] = $dsn['capath'];
}
if (!empty($dsn['ca'])) {
$result[PDO::MYSQL_ATTR_SSL_CA] = $dsn['ca'];
}
return $result;
}
/**
* Get database runtime variables
*
* @param string $varname Variable name
* @param mixed $default Default value if variable is not set
*
* @return mixed Variable value or default
*/
public function get_variable($varname, $default = null)
{
if (!isset($this->variables)) {
$this->variables = array();
$result = $this->query('SHOW VARIABLES');
while ($sql_arr = $this->fetch_array($result)) {
$this->variables[$row[0]] = $row[1];
}
}
return isset($this->variables[$varname]) ? $this->variables[$varname] : $default;
}
}

@ -0,0 +1,135 @@
<?php
/**
+-----------------------------------------------------------------------+
| program/include/rcube_db_pgsql.php |
| |
| This file is part of the Roundcube Webmail client |
| Copyright (C) 2005-2012, The Roundcube Dev Team |
| |
| Licensed under the GNU General Public License version 3 or |
| any later version with exceptions for skins & plugins. |
| See the README file for a full license statement. |
| |
| PURPOSE: |
| Database wrapper class that implements PHP PDO functions |
| for PostgreSQL database |
| |
+-----------------------------------------------------------------------+
| Author: Aleksander Machniak <alec@alec.pl> |
+-----------------------------------------------------------------------+
*/
/**
* Database independent query interface
*
* This is a wrapper for the PHP PDO
*
* @package Database
* @version 1.0
*/
class rcube_db_pgsql extends rcube_db
{
/**
* Get last inserted record ID
*
* @param string $table Table name (to find the incremented sequence)
*
* @return mixed ID or false on failure
*/
public function insert_id($table = null)
{
if (!$this->db_connected || $this->db_mode == 'r') {
return false;
}
if ($table) {
$table = $this->sequence_name($table);
}
$id = $this->dbh->lastInsertId($table);
return $id;
}
/**
* Return correct name for a specific database sequence
*
* @param string $sequence Secuence name
*
* @return string Translated sequence name
*/
protected function sequence_name($sequence)
{
$rcube = rcube::get_instance();
// return sequence name if configured
$config_key = 'db_sequence_'.$sequence;
if ($name = $rcube->config->get($config_key)) {
return $name;
}
return $sequence;
}
/**
* Return SQL statement to convert a field value into a unix timestamp
*
* This method is deprecated and should not be used anymore due to limitations
* of timestamp functions in Mysql (year 2038 problem)
*
* @param string $field Field name
*
* @return string SQL statement to use in query
* @deprecated
*/
public function unixtimestamp($field)
{
return "EXTRACT (EPOCH FROM $field)";
}
/**
* Return SQL statement for case insensitive LIKE
*
* @param string $column Field name
* @param string $value Search value
*
* @return string SQL statement to use in query
*/
public function ilike($column, $value)
{
return $this->quote_identifier($column) . ' ILIKE ' . $this->quote($value);
}
/**
* Get database runtime variables
*
* @param string $varname Variable name
* @param mixed $default Default value if variable is not set
*
* @return mixed Variable value or default
*/
public function get_variable($varname, $default = null)
{
// There's a known case when max_allowed_packet is queried
// PostgreSQL doesn't have such limit, return immediately
if ($varname == 'max_allowed_packet') {
return $default;
}
if (!isset($this->variables)) {
$this->variables = array();
$result = $this->query('SHOW ALL');
while ($row = $this->fetch_array($result)) {
$this->variables[$row[0]] = $row[1];
}
}
return isset($this->variables[$varname]) ? $this->variables[$varname] : $default;
}
}

@ -0,0 +1,178 @@
<?php
/**
+-----------------------------------------------------------------------+
| program/include/rcube_db_sqlite.php |
| |
| This file is part of the Roundcube Webmail client |
| Copyright (C) 2005-2012, The Roundcube Dev Team |
| |
| Licensed under the GNU General Public License version 3 or |
| any later version with exceptions for skins & plugins. |
| See the README file for a full license statement. |
| |
| PURPOSE: |
| Database wrapper class that implements PHP PDO functions |
| for SQLite database |
| |
+-----------------------------------------------------------------------+
| Author: Aleksander Machniak <alec@alec.pl> |
+-----------------------------------------------------------------------+
*/
/**
* Database independent query interface
*
* This is a wrapper for the PHP PDO
*
* @package Database
* @version 1.0
*/
class rcube_db_sqlite extends rcube_db
{
/**
* Database character set
*/
protected function set_charset($charset)
{
}
/**
* Prepare connection
*/
protected function conn_prepare($dsn)
{
// Create database file, required by PDO to exist on connection
if (!empty($dsn['database']) && !file_exists($dsn['database'])) {
$created = touch($dsn['database']);
// File mode setting, for compat. with MDB2
if (!empty($dsn['mode']) && $created) {
chmod($dsn['database'], octdec($dsn['mode']));
}
}
}
/**
* Configure connection, create database if not exists
*/
protected function conn_configure($dsn, $dbh)
{
// we emulate via callback some missing functions
$dbh->sqliteCreateFunction('unix_timestamp', array('rcube_db_sqlite', 'sqlite_unix_timestamp'), 1);
$dbh->sqliteCreateFunction('now', array('rcube_db_sqlite', 'sqlite_now'), 0);
// Initialize database structure in file is empty
if (!empty($dsn['database']) && !filesize($dsn['database'])) {
$data = file_get_contents(INSTALL_PATH . 'SQL/sqlite.initial.sql');
if (strlen($data)) {
$this->debug('INITIALIZE DATABASE');
$q = $dbh->exec($data);
if ($q === false) {
$error = $dbh->errorInfo();
$this->db_error = true;
$this->db_error_msg = sprintf('[%s] %s', $error[1], $error[2]);
rcube::raise_error(array('code' => 500, 'type' => 'db',
'line' => __LINE__, 'file' => __FILE__,
'message' => $this->db_error_msg), true, false);
}
}
}
}
/**
* Callback for sqlite: unix_timestamp()
*/
public static function sqlite_unix_timestamp($timestamp = '')
{
$timestamp = trim($timestamp);
if (!$timestamp) {
$ret = time();
}
else if (!preg_match('/^[0-9]+$/s', $timestamp)) {
$ret = strtotime($timestamp);
}
else {
$ret = $timestamp;
}
return $ret;
}
/**
* Callback for sqlite: now()
*/
public static function sqlite_now()
{
return date("Y-m-d H:i:s");
}
/**
* Returns list of tables in database
*
* @return array List of all tables of the current database
*/
public function list_tables()
{
if ($this->tables === null) {
$q = $this->query('SELECT name FROM sqlite_master'
.' WHERE type = \'table\' ORDER BY name');
if ($res = $this->_get_result($q)) {
$this->tables = $res->fetchAll(PDO::FETCH_COLUMN, 0);
}
else {
$this->tables = array();
}
}
return $this->tables;
}
/**
* Returns list of columns in database table
*
* @param string $table Table name
*
* @return array List of table cols
*/
public function list_cols($table)
{
$q = $this->query('SELECT sql FROM sqlite_master WHERE type = ? AND name = ?',
array('table', $table));
$columns = array();
if ($sql = $this->fetch_array($q)) {
$sql = $sql[0];
$start_pos = strpos($sql, '(');
$end_pos = strrpos($sql, ')');
$sql = substr($sql, $start_pos+1, $end_pos-$start_pos-1);
$lines = explode(',', $sql);
foreach ($lines as $line) {
$line = explode(' ', trim($line));
if ($line[0] && strpos($line[0], '--') !== 0) {
$column = $line[0];
$columns[] = trim($column, '"');
}
}
}
return $columns;
}
/**
* Build DSN string for PDO constructor
*/
protected function dsn_string($dsn)
{
return $dsn['phptype'] . ':' . $dsn['database'];
}
}

@ -0,0 +1,156 @@
<?php
/**
+-----------------------------------------------------------------------+
| program/include/rcube_db_sqlsrv.php |
| |
| This file is part of the Roundcube Webmail client |
| Copyright (C) 2005-2012, The Roundcube Dev Team |
| |
| Licensed under the GNU General Public License version 3 or |
| any later version with exceptions for skins & plugins. |
| See the README file for a full license statement. |
| |
| PURPOSE: |
| Database wrapper class that implements PHP PDO functions |
| for MS SQL Server database |
| |
+-----------------------------------------------------------------------+
| Author: Aleksander Machniak <alec@alec.pl> |
+-----------------------------------------------------------------------+
*/
/**
* Database independent query interface
*
* This is a wrapper for the PHP PDO
*
* @package Database
* @version 1.0
*/
class rcube_db_sqlsrv extends rcube_db
{
/**
* Driver initialization
*/
protected function init()
{
$this->options['identifier_start'] = '[';
$this->options['identifier_end'] = ']';
}
/**
* Database character set setting
*/
protected function set_charset($charset)
{
// UTF-8 is default
}
/**
* Return SQL function for current time and date
*
* @return string SQL function to use in query
*/
public function now()
{
return "getdate()";
}
/**
* Return SQL statement to convert a field value into a unix timestamp
*
* This method is deprecated and should not be used anymore due to limitations
* of timestamp functions in Mysql (year 2038 problem)
*
* @param string $field Field name
*
* @return string SQL statement to use in query
* @deprecated
*/
public function unixtimestamp($field)
{
return "DATEDIFF(second, '19700101', $field) + DATEDIFF(second, GETDATE(), GETUTCDATE())";
}
/**
* Abstract SQL statement for value concatenation
*
* @return string SQL statement to be used in query
*/
public function concat(/* col1, col2, ... */)
{
$args = func_get_args();
if (is_array($args[0])) {
$args = $args[0];
}
return '(' . join('+', $args) . ')';
}
/**
* Adds TOP (LIMIT,OFFSET) clause to the query
*
* @param string $query SQL query
* @param int $limit Number of rows
* @param int $offset Offset
*
* @return string SQL query
*/
protected function set_limit($query, $limit = 0, $offset = 0)
{
$limit = intval($limit);
$offset = intval($offset);
$orderby = stristr($query, 'ORDER BY');
if ($orderby !== false) {
$sort = (stripos($orderby, ' desc') !== false) ? 'desc' : 'asc';
$order = str_ireplace('ORDER BY', '', $orderby);
$order = trim(preg_replace('/\bASC\b|\bDESC\b/i', '', $order));
}
$query = preg_replace('/^SELECT\s/i', 'SELECT TOP ' . ($limit + $offset) . ' ', $query);
$query = 'SELECT * FROM (SELECT TOP ' . $limit . ' * FROM (' . $query . ') AS inner_tbl';
if ($orderby !== false) {
$query .= ' ORDER BY ' . $order . ' ';
$query .= (stripos($sort, 'asc') !== false) ? 'DESC' : 'ASC';
}
$query .= ') AS outer_tbl';
if ($orderby !== false) {
$query .= ' ORDER BY ' . $order . ' ' . $sort;
}
return $query;
}
/**
* Returns PDO DSN string from DSN array
*/
protected function dsn_string($dsn)
{
$params = array();
$result = 'sqlsrv:';
if ($dsn['hostspec']) {
$host = $dsn['hostspec'];
if ($dsn['port']) {
$host .= ',' . $dsn['port'];
}
$params[] = 'Server=' . $host;
}
if ($dsn['database']) {
$params[] = 'Database=' . $dsn['database'];
}
if (!empty($params)) {
$result .= implode(';', $params);
}
return $result;
}
}

@ -39,9 +39,9 @@ class rcube_imap_cache
private $imap;
/**
* Instance of rcube_mdb2
* Instance of rcube_db
*
* @var rcube_mdb2
* @var rcube_db
*/
private $db;

@ -1,935 +0,0 @@
<?php
/*
+-----------------------------------------------------------------------+
| program/include/rcube_mdb2.php |
| |
| This file is part of the Roundcube Webmail client |
| Copyright (C) 2005-2009, The Roundcube Dev Team |
| |
| Licensed under the GNU General Public License version 3 or |
| any later version with exceptions for skins & plugins. |
| See the README file for a full license statement. |
| |
| PURPOSE: |
| PEAR:DB wrapper class that implements PEAR MDB2 functions |
| See http://pear.php.net/package/MDB2 |
| |
+-----------------------------------------------------------------------+
| Author: Lukas Kahwe Smith <smith@pooteeweet.org> |
+-----------------------------------------------------------------------+
*/
/**
* Database independent query interface
*
* This is a wrapper for the PEAR::MDB2 class
*
* @package Database
* @author David Saez Padros <david@ols.es>
* @author Thomas Bruederli <roundcube@gmail.com>
* @author Lukas Kahwe Smith <smith@pooteeweet.org>
* @version 1.18
* @link http://pear.php.net/package/MDB2
*/
class rcube_mdb2
{
public $db_dsnw; // DSN for write operations
public $db_dsnr; // DSN for read operations
public $db_connected = false; // Already connected ?
public $db_mode = ''; // Connection mode
public $db_handle = 0; // Connection handle
public $db_error = false;
public $db_error_msg = '';
private $debug_mode = false;
private $conn_failure = false;
private $a_query_results = array('dummy');
private $last_res_id = 0;
private $tables;
private $variables;
/**
* Object constructor
*
* @param string $db_dsnw DSN for read/write operations
* @param string $db_dsnr Optional DSN for read only operations
*/
public function __construct($db_dsnw, $db_dsnr='', $pconn=false)
{
if (empty($db_dsnr)) {
$db_dsnr = $db_dsnw;
}
$this->db_dsnw = $db_dsnw;
$this->db_dsnr = $db_dsnr;
$this->db_pconn = $pconn;
$dsn_array = MDB2::parseDSN($db_dsnw);
$this->db_provider = $dsn_array['phptype'];
}
/**
* Connect to specific database
*
* @param string $dsn DSN for DB connections
* @return MDB2 PEAR database handle
* @access private
*/
private function dsn_connect($dsn)
{
// Use persistent connections if available
$db_options = array(
'persistent' => $this->db_pconn,
'emulate_prepared' => $this->debug_mode,
'debug' => $this->debug_mode,
'debug_handler' => array($this, 'debug_handler'),
'portability' => MDB2_PORTABILITY_ALL ^ MDB2_PORTABILITY_EMPTY_TO_NULL,
);
if ($this->db_provider == 'pgsql') {
$db_options['disable_smart_seqname'] = true;
$db_options['seqname_format'] = '%s';
}
$this->db_error = false;
$this->db_error_msg = null;
$dbh = MDB2::connect($dsn, $db_options);
if (MDB2::isError($dbh)) {
$this->db_error = true;
$this->db_error_msg = $dbh->getMessage();
rcube::raise_error(array('code' => 500, 'type' => 'db',
'line' => __LINE__, 'file' => __FILE__,
'message' => $dbh->getUserInfo()), true, false);
}
else if ($this->db_provider == 'sqlite') {
$dsn_array = MDB2::parseDSN($dsn);
if (!filesize($dsn_array['database']) && !empty($this->sqlite_initials)) {
$this->sqlite_create_database($dbh, $this->sqlite_initials);
}
}
else if ($this->db_provider != 'mssql' && $this->db_provider != 'sqlsrv') {
$dbh->setCharset('utf8');
}
return $dbh;
}
/**
* Connect to appropiate database depending on the operation
*
* @param string $mode Connection mode (r|w)
*/
public function db_connect($mode)
{
// previous connection failed, don't attempt to connect again
if ($this->conn_failure) {
return;
}
// no replication
if ($this->db_dsnw == $this->db_dsnr) {
$mode = 'w';
}
// Already connected
if ($this->db_connected) {
// connected to db with the same or "higher" mode
if ($this->db_mode == 'w' || $this->db_mode == $mode) {
return;
}
}
$dsn = ($mode == 'r') ? $this->db_dsnr : $this->db_dsnw;
$this->db_handle = $this->dsn_connect($dsn);
$this->db_connected = !PEAR::isError($this->db_handle);
// use write-master when read-only fails
if (!$this->db_connected && $mode == 'r') {
$mode = 'w';
$this->db_handle = $this->dsn_connect($this->db_dsnw);
$this->db_connected = !PEAR::isError($this->db_handle);
}
if ($this->db_connected) {
$this->db_mode = $mode;
}
else {
$this->conn_failure = true;
}
}
/**
* Activate/deactivate debug mode
*
* @param boolean $dbg True if SQL queries should be logged
*/
public function set_debug($dbg = true)
{
$this->debug_mode = $dbg;
if ($this->db_connected) {
$this->db_handle->setOption('debug', $dbg);
$this->db_handle->setOption('emulate_prepared', $dbg);
}
}
/**
* Getter for error state
*
* @param boolean True on error
*/
public function is_error()
{
return $this->db_error ? $this->db_error_msg : false;
}
/**
* Connection state checker
*
* @param boolean True if in connected state
*/
public function is_connected()
{
return PEAR::isError($this->db_handle) ? false : $this->db_connected;
}
/**
* Is database replication configured?
* This returns true if dsnw != dsnr
*/
public function is_replicated()
{
return !empty($this->db_dsnr) && $this->db_dsnw != $this->db_dsnr;
}
/**
* Get database runtime variables
*
* @param string Variable name
* @param mixed Default value if var is not set
* @return mixed Variable value or default
*/
public function get_variable($varname, $default = null)
{
if (!isset($this->variables)) {
$this->variables = array();
// only mysql and postgres are know to support this
if ($this->db_provider == 'pgsql' || $this->db_provider == 'mysql' || $this->db_provider == 'mysqli') {
$this->db_connect('r');
$query = $this->db_provider == 'pgsql' ? 'SHOW ALL' : 'SHOW VARIABLES';
foreach ((array)$this->db_handle->queryAll($query) as $row)
$this->variables[$row[0]] = $row[1];
}
}
return isset($this->variables[$varname]) ? $this->variables[$varname] : $default;
}
/**
* Execute a SQL query
*
* @param string SQL query to execute
* @param mixed Values to be inserted in query
*
* @return number Query handle identifier
*/
public function query()
{
$params = func_get_args();
$query = array_shift($params);
// Support one argument of type array, instead of n arguments
if (count($params) == 1 && is_array($params[0])) {
$params = $params[0];
}
return $this->_query($query, 0, 0, $params);
}
/**
* Execute a SQL query with limits
*
* @param string SQL query to execute
* @param number Offset for LIMIT statement
* @param number Number of rows for LIMIT statement
* @param mixed Values to be inserted in query
*
* @return number Query handle identifier
*/
public function limitquery()
{
$params = func_get_args();
$query = array_shift($params);
$offset = array_shift($params);
$numrows = array_shift($params);
return $this->_query($query, $offset, $numrows, $params);
}
/**
* Execute a SQL query with limits
*
* @param string $query SQL query to execute
* @param number $offset Offset for LIMIT statement
* @param number $numrows Number of rows for LIMIT statement
* @param array $params Values to be inserted in query
* @return number Query handle identifier
* @access private
*/
private function _query($query, $offset, $numrows, $params)
{
// Read or write ?
$mode = (strtolower(substr(trim($query),0,6)) == 'select') ? 'r' : 'w';
$this->db_connect($mode);
// check connection before proceeding
if (!$this->is_connected()) {
return null;
}
if ($this->db_provider == 'sqlite') {
$this->sqlite_prepare();
}
if ($numrows || $offset) {
$result = $this->db_handle->setLimit($numrows,$offset);
}
if (empty($params)) {
$result = $mode == 'r' ? $this->db_handle->query($query) : $this->db_handle->exec($query);
}
else {
$params = (array)$params;
$q = $this->db_handle->prepare($query, null, $mode=='w' ? MDB2_PREPARE_MANIP : null);
if ($this->db_handle->isError($q)) {
$this->db_error = true;
$this->db_error_msg = $q->userinfo;
rcube::raise_error(array('code' => 500, 'type' => 'db',
'line' => __LINE__, 'file' => __FILE__,
'message' => $this->db_error_msg), true, false);
$result = false;
}
else {
$result = $q->execute($params);
$q->free();
}
}
// add result, even if it's an error
return $this->_add_result($result);
}
/**
* Get number of rows for a SQL query
* If no query handle is specified, the last query will be taken as reference
*
* @param number $res_id Optional query handle identifier
* @return mixed Number of rows or false on failure
*/
public function num_rows($res_id=null)
{
if (!$this->db_connected) {
return false;
}
if ($result = $this->_get_result($res_id)) {
return $result->numRows();
}
return false;
}
/**
* Get number of affected rows for the last query
*
* @param number $res_id Optional query handle identifier
* @return mixed Number of rows or false on failure
*/
public function affected_rows($res_id = null)
{
if (!$this->db_connected) {
return false;
}
return $this->_get_result($res_id);
}
/**
* Get last inserted record ID
* For Postgres databases, a sequence name is required
*
* @param string $table Table name (to find the incremented sequence)
*
* @return mixed ID or false on failure
*/
public function insert_id($table = '')
{
if (!$this->db_connected || $this->db_mode == 'r') {
return false;
}
if ($table) {
if ($this->db_provider == 'pgsql') {
// find sequence name
$table = $this->sequence_name($table);
}
else {
// resolve table name
$table = $this->table_name($table);
}
}
$id = $this->db_handle->lastInsertID($table);
return $this->db_handle->isError($id) ? null : $id;
}
/**
* Get an associative array for one row
* If no query handle is specified, the last query will be taken as reference
*
* @param number $res_id Optional query handle identifier
*
* @return mixed Array with col values or false on failure
*/
public function fetch_assoc($res_id = null)
{
$result = $this->_get_result($res_id);
return $this->_fetch_row($result, MDB2_FETCHMODE_ASSOC);
}
/**
* Get an index array for one row
* If no query handle is specified, the last query will be taken as reference
*
* @param number $res_id Optional query handle identifier
*
* @return mixed Array with col values or false on failure
*/
public function fetch_array($res_id = null)
{
$result = $this->_get_result($res_id);
return $this->_fetch_row($result, MDB2_FETCHMODE_ORDERED);
}
/**
* Get col values for a result row
*
* @param MDB2_Result_Common Query $result result handle
* @param number $mode Fetch mode identifier
*
* @return mixed Array with col values or false on failure
*/
private function _fetch_row($result, $mode)
{
if ($result === false || PEAR::isError($result) || !$this->is_connected()) {
return false;
}
return $result->fetchRow($mode);
}
/**
* Wrapper for the SHOW TABLES command
*
* @return array List of all tables of the current database
* @since 0.4-beta
*/
public function list_tables()
{
// get tables if not cached
if (!$this->tables) {
$this->db_handle->loadModule('Manager');
if (!PEAR::isError($result = $this->db_handle->listTables())) {
$this->tables = $result;
}
else {
$this->tables = array();
}
}
return $this->tables;
}
/**
* Wrapper for SHOW COLUMNS command
*
* @param string Table name
*
* @return array List of table cols
*/
public function list_cols($table)
{
$this->db_handle->loadModule('Manager');
if (!PEAR::isError($result = $this->db_handle->listTableFields($table))) {
return $result;
}
return null;
}
/**
* Formats input so it can be safely used in a query
*
* @param mixed $input Value to quote
* @param string $type Type of data
*
* @return string Quoted/converted string for use in query
*/
public function quote($input, $type = null)
{
// handle int directly for better performance
if ($type == 'integer') {
return intval($input);
}
// create DB handle if not available
if (!$this->db_handle) {
$this->db_connect('r');
}
return $this->db_connected ? $this->db_handle->quote($input, $type) : addslashes($input);
}
/**
* Quotes a string so it can be safely used as a table or column name
*
* @param string $str Value to quote
*
* @return string Quoted string for use in query
* @deprecated Replaced by rcube_MDB2::quote_identifier
* @see rcube_mdb2::quote_identifier
*/
public function quoteIdentifier($str)
{
return $this->quote_identifier($str);
}
/**
* Quotes a string so it can be safely used as a table or column name
*
* @param string $str Value to quote
*
* @return string Quoted string for use in query
*/
public function quote_identifier($str)
{
if (!$this->db_handle) {
$this->db_connect('r');
}
return $this->db_connected ? $this->db_handle->quoteIdentifier($str) : $str;
}
/**
* Escapes a string
*
* @param string $str The string to be escaped
*
* @return string The escaped string
* @since 0.1.1
*/
public function escapeSimple($str)
{
if (!$this->db_handle) {
$this->db_connect('r');
}
return $this->db_handle->escape($str);
}
/**
* Return SQL function for current time and date
*
* @return string SQL function to use in query
*/
public function now()
{
switch ($this->db_provider) {
case 'mssql':
case 'sqlsrv':
return "getdate()";
default:
return "now()";
}
}
/**
* Return list of elements for use with SQL's IN clause
*
* @param array $arr Input array
* @param string $type Type of data
*
* @return string Comma-separated list of quoted values for use in query
*/
public function array2list($arr, $type = null)
{
if (!is_array($arr)) {
return $this->quote($arr, $type);
}
foreach ($arr as $idx => $item) {
$arr[$idx] = $this->quote($item, $type);
}
return implode(',', $arr);
}
/**
* Return SQL statement to convert a field value into a unix timestamp
*
* This method is deprecated and should not be used anymore due to limitations
* of timestamp functions in Mysql (year 2038 problem)
*
* @param string $field Field name
*
* @return string SQL statement to use in query
* @deprecated
*/
public function unixtimestamp($field)
{
switch($this->db_provider) {
case 'pgsql':
return "EXTRACT (EPOCH FROM $field)";
case 'mssql':
case 'sqlsrv':
return "DATEDIFF(second, '19700101', $field) + DATEDIFF(second, GETDATE(), GETUTCDATE())";
default:
return "UNIX_TIMESTAMP($field)";
}
}
/**
* Return SQL statement to convert from a unix timestamp
*
* @param string $timestamp Field name
*
* @return string SQL statement to use in query
*/
public function fromunixtime($timestamp)
{
return date("'Y-m-d H:i:s'", $timestamp);
}
/**
* Return SQL statement for case insensitive LIKE
*
* @param string $column Field name
* @param string $value Search value
*
* @return string SQL statement to use in query
*/
public function ilike($column, $value)
{
// TODO: use MDB2's matchPattern() function
switch ($this->db_provider) {
case 'pgsql':
return $this->quote_identifier($column).' ILIKE '.$this->quote($value);
default:
return $this->quote_identifier($column).' LIKE '.$this->quote($value);
}
}
/**
* Abstract SQL statement for value concatenation
*
* @return string SQL statement to be used in query
*/
public function concat(/* col1, col2, ... */)
{
$func = '';
$args = func_get_args();
if (is_array($args[0]))
$args = $args[0];
switch ($this->db_provider) {
case 'mysql':
case 'mysqli':
$func = 'CONCAT';
$delim = ', ';
break;
case 'mssql':
case 'sqlsrv':
$delim = ' + ';
// Modify arguments, because + operator requires them to be of type varchar (#1488505)
// with SQL Server 2012 we can use just CONCAT(), but we need to support older versions
foreach ($args as $idx => $arg) {
$args[$idx] = "CAST($arg AS varchar)";
}
break;
default:
$delim = ' || ';
}
return $func . '(' . join($delim, $args) . ')';
}
/**
* Encodes non-UTF-8 characters in string/array/object (recursive)
*
* @param mixed $input Data to fix
*
* @return mixed Properly UTF-8 encoded data
*/
public static function encode($input)
{
if (is_object($input)) {
foreach (get_object_vars($input) as $idx => $value) {
$input->$idx = self::encode($value);
}
return $input;
}
else if (is_array($input)) {
foreach ($input as $idx => $value) {
$input[$idx] = self::encode($value);
}
return $input;
}
return utf8_encode($input);
}
/**
* Decodes encoded UTF-8 string/object/array (recursive)
*
* @param mixed $input Input data
*
* @return mixed Decoded data
*/
public static function decode($input)
{
if (is_object($input)) {
foreach (get_object_vars($input) as $idx => $value) {
$input->$idx = self::decode($value);
}
return $input;
}
else if (is_array($input)) {
foreach ($input as $idx => $value) {
$input[$idx] = self::decode($value);
}
return $input;
}
return utf8_decode($input);
}
/**
* Adds a query result and returns a handle ID
*
* @param object $res Query handle
*
* @return mixed Handle ID
*/
private function _add_result($res)
{
// sql error occured
if (PEAR::isError($res)) {
$this->db_error = true;
$this->db_error_msg = $res->getMessage();
rcube::raise_error(array('code' => 500, 'type' => 'db',
'line' => __LINE__, 'file' => __FILE__,
'message' => $res->getMessage() . " Query: "
. substr(preg_replace('/[\r\n]+\s*/', ' ', $res->userinfo), 0, 512)),
true, false);
}
$res_id = sizeof($this->a_query_results);
$this->last_res_id = $res_id;
$this->a_query_results[$res_id] = $res;
return $res_id;
}
/**
* Resolves a given handle ID and returns the according query handle
* If no ID is specified, the last resource handle will be returned
*
* @param number $res_id Handle ID
*
* @return mixed Resource handle or false on failure
*/
private function _get_result($res_id = null)
{
if ($res_id == null) {
$res_id = $this->last_res_id;
}
if (isset($this->a_query_results[$res_id])) {
if (!PEAR::isError($this->a_query_results[$res_id])) {
return $this->a_query_results[$res_id];
}
}
return false;
}
/**
* Create a sqlite database from a file
*
* @param MDB2 $dbh SQLite database handle
* @param string $file_name File path to use for DB creation
*/
private function sqlite_create_database($dbh, $file_name)
{
if (empty($file_name) || !is_string($file_name)) {
return;
}
$data = file_get_contents($file_name);
if (strlen($data)) {
if (!sqlite_exec($dbh->connection, $data, $error) || MDB2::isError($dbh)) {
rcube::raise_error(array('code' => 500, 'type' => 'db',
'line' => __LINE__, 'file' => __FILE__,
'message' => $error), true, false);
}
}
}
/**
* Add some proprietary database functions to the current SQLite handle
* in order to make it MySQL compatible
*/
private function sqlite_prepare()
{
// we emulate via callback some missing MySQL functions
sqlite_create_function($this->db_handle->connection,
'unix_timestamp', array('rcube_mdb2', 'sqlite_unix_timestamp'));
sqlite_create_function($this->db_handle->connection,
'now', array('rcube_mdb2', 'sqlite_now'));
}
/**
* Debug handler for the MDB2
*/
function debug_handler(&$db, $scope, $message, $context = array())
{
if ($scope != 'prepare') {
$debug_output = sprintf('%s(%d): %s;',
$scope, $db->db_index, rtrim($message, ';'));
rcube::write_log('sql', $debug_output);
}
}
/**
* Return correct name for a specific database table
*
* @param string $table Table name
*
* @return string Translated table name
*/
public function table_name($table)
{
$rcube = rcube::get_instance();
// return table name if configured
$config_key = 'db_table_'.$table;
if ($name = $rcube->config->get($config_key)) {
return $name;
}
return $table;
}
/**
* Return correct name for a specific database sequence
* (used for Postgres only)
*
* @param string $sequence Secuence name
*
* @return string Translated sequence name
*/
public function sequence_name($sequence)
{
$rcube = rcube::get_instance();
// return sequence name if configured
$config_key = 'db_sequence_'.$sequence;
if ($name = $rcube->config->get($config_key)) {
return $name;
}
return $sequence;
}
/**
* Callback for sqlite: unix_timestamp()
*/
public static function sqlite_unix_timestamp($timestamp = '')
{
$timestamp = trim($timestamp);
if (!$timestamp) {
$ret = time();
}
else if (!preg_match('/^[0-9]+$/s', $timestamp)) {
$ret = strtotime($timestamp);
}
else {
$ret = $timestamp;
}
return $ret;
}
/**
* Callback for sqlite: now()
*/
public static function sqlite_now()
{
return date("Y-m-d H:i:s");
}
}

@ -407,7 +407,7 @@ function rcube_autoload($classname)
'/^utf8$/',
),
array(
'MDB2/\\1',
'Mail/\\1',
'Mail/\\1',
'Net/\\1',
'Auth/\\1',

@ -36,7 +36,7 @@ class rcube_user
/**
* Holds database connection.
*
* @var rcube_mdb2
* @var rcube_db
*/
private $db;

File diff suppressed because it is too large Load Diff

@ -1,183 +0,0 @@
<?php
// +----------------------------------------------------------------------+
// | PHP versions 4 and 5 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1998-2006 Manuel Lemos, Tomas V.V.Cox, |
// | Stig. S. Bakken, Lukas Smith |
// | All rights reserved. |
// +----------------------------------------------------------------------+
// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB |
// | API as well as database abstraction for PHP applications. |
// | This LICENSE is in the BSD license style. |
// | |
// | Redistribution and use in source and binary forms, with or without |
// | modification, are permitted provided that the following conditions |
// | are met: |
// | |
// | Redistributions of source code must retain the above copyright |
// | notice, this list of conditions and the following disclaimer. |
// | |
// | Redistributions in binary form must reproduce the above copyright |
// | notice, this list of conditions and the following disclaimer in the |
// | documentation and/or other materials provided with the distribution. |
// | |
// | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken, |
// | Lukas Smith nor the names of his contributors may be used to endorse |
// | or promote products derived from this software without specific prior|
// | written permission. |
// | |
// | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
// | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
// | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
// | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE |
// | REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, |
// | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
// | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS|
// | OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED |
// | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
// | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY|
// | WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
// | POSSIBILITY OF SUCH DAMAGE. |
// +----------------------------------------------------------------------+
// | Author: Lukas Smith <smith@pooteeweet.org> |
// +----------------------------------------------------------------------+
//
// $Id: Date.php 208329 2006-03-01 12:15:38Z lsmith $
//
/**
* @package MDB2
* @category Database
* @author Lukas Smith <smith@pooteeweet.org>
*/
/**
* Several methods to convert the MDB2 native timestamp format (ISO based)
* to and from data structures that are convenient to worth with in side of php.
* For more complex date arithmetic please take a look at the Date package in PEAR
*
* @package MDB2
* @category Database
* @author Lukas Smith <smith@pooteeweet.org>
*/
class MDB2_Date
{
// {{{ mdbNow()
/**
* return the current datetime
*
* @return string current datetime in the MDB2 format
* @access public
*/
function mdbNow()
{
return date('Y-m-d H:i:s');
}
// }}}
// {{{ mdbToday()
/**
* return the current date
*
* @return string current date in the MDB2 format
* @access public
*/
function mdbToday()
{
return date('Y-m-d');
}
// }}}
// {{{ mdbTime()
/**
* return the current time
*
* @return string current time in the MDB2 format
* @access public
*/
function mdbTime()
{
return date('H:i:s');
}
// }}}
// {{{ date2Mdbstamp()
/**
* convert a date into a MDB2 timestamp
*
* @param int hour of the date
* @param int minute of the date
* @param int second of the date
* @param int month of the date
* @param int day of the date
* @param int year of the date
*
* @return string a valid MDB2 timestamp
* @access public
*/
function date2Mdbstamp($hour = null, $minute = null, $second = null,
$month = null, $day = null, $year = null)
{
return MDB2_Date::unix2Mdbstamp(mktime($hour, $minute, $second, $month, $day, $year, -1));
}
// }}}
// {{{ unix2Mdbstamp()
/**
* convert a unix timestamp into a MDB2 timestamp
*
* @param int a valid unix timestamp
*
* @return string a valid MDB2 timestamp
* @access public
*/
function unix2Mdbstamp($unix_timestamp)
{
return date('Y-m-d H:i:s', $unix_timestamp);
}
// }}}
// {{{ mdbstamp2Unix()
/**
* convert a MDB2 timestamp into a unix timestamp
*
* @param int a valid MDB2 timestamp
* @return string unix timestamp with the time stored in the MDB2 format
*
* @access public
*/
function mdbstamp2Unix($mdb_timestamp)
{
$arr = MDB2_Date::mdbstamp2Date($mdb_timestamp);
return mktime($arr['hour'], $arr['minute'], $arr['second'], $arr['month'], $arr['day'], $arr['year'], -1);
}
// }}}
// {{{ mdbstamp2Date()
/**
* convert a MDB2 timestamp into an array containing all
* values necessary to pass to php's date() function
*
* @param int a valid MDB2 timestamp
*
* @return array with the time split
* @access public
*/
function mdbstamp2Date($mdb_timestamp)
{
list($arr['year'], $arr['month'], $arr['day'], $arr['hour'], $arr['minute'], $arr['second']) =
sscanf($mdb_timestamp, "%04u-%02u-%02u %02u:%02u:%02u");
return $arr;
}
// }}}
}
?>

File diff suppressed because it is too large Load Diff

@ -1,496 +0,0 @@
<?php
// vim: set et ts=4 sw=4 fdm=marker:
// +----------------------------------------------------------------------+
// | PHP versions 4 and 5 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1998-2007 Manuel Lemos, Tomas V.V.Cox, |
// | Stig. S. Bakken, Lukas Smith |
// | All rights reserved. |
// +----------------------------------------------------------------------+
// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB |
// | API as well as database abstraction for PHP applications. |
// | This LICENSE is in the BSD license style. |
// | |
// | Redistribution and use in source and binary forms, with or without |
// | modification, are permitted provided that the following conditions |
// | are met: |
// | |
// | Redistributions of source code must retain the above copyright |
// | notice, this list of conditions and the following disclaimer. |
// | |
// | Redistributions in binary form must reproduce the above copyright |
// | notice, this list of conditions and the following disclaimer in the |
// | documentation and/or other materials provided with the distribution. |
// | |
// | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken, |
// | Lukas Smith nor the names of his contributors may be used to endorse |
// | or promote products derived from this software without specific prior|
// | written permission. |
// | |
// | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
// | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
// | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
// | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE |
// | REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, |
// | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
// | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS|
// | OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED |
// | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
// | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY|
// | WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
// | POSSIBILITY OF SUCH DAMAGE. |
// +----------------------------------------------------------------------+
// | Authors: Lukas Smith <smith@pooteeweet.org> |
// | Daniel Convissor <danielc@php.net> |
// +----------------------------------------------------------------------+
//
// $Id: mssql.php 295587 2010-02-28 17:16:38Z quipo $
//
require_once 'MDB2/Driver/Datatype/Common.php';
/**
* MDB2 MS SQL driver
*
* @package MDB2
* @category Database
* @author Lukas Smith <smith@pooteeweet.org>
*/
class MDB2_Driver_Datatype_mssql extends MDB2_Driver_Datatype_Common
{
// {{{ _baseConvertResult()
/**
* general type conversion method
*
* @param mixed $value refernce to a value to be converted
* @param string $type specifies which type to convert to
* @param boolean $rtrim [optional] when TRUE [default], apply rtrim() to text
* @return object a MDB2 error on failure
* @access protected
*/
function _baseConvertResult($value, $type, $rtrim = true)
{
if (null === $value) {
return null;
}
switch ($type) {
case 'boolean':
return $value == '1';
case 'date':
if (strlen($value) > 10) {
$value = substr($value,0,10);
}
return $value;
case 'time':
if (strlen($value) > 8) {
$value = substr($value,11,8);
}
return $value;
}
return parent::_baseConvertResult($value, $type, $rtrim);
}
// }}}
// {{{ _getCollationFieldDeclaration()
/**
* Obtain DBMS specific SQL code portion needed to set the COLLATION
* of a field declaration to be used in statements like CREATE TABLE.
*
* @param string $collation name of the collation
*
* @return string DBMS specific SQL code portion needed to set the COLLATION
* of a field declaration.
*/
function _getCollationFieldDeclaration($collation)
{
return 'COLLATE '.$collation;
}
// }}}
// {{{ getTypeDeclaration()
/**
* Obtain DBMS specific SQL code portion needed to declare an text type
* field to be used in statements like CREATE TABLE.
*
* @param array $field associative array with the name of the properties
* of the field being declared as array indexes. Currently, the types
* of supported field properties are as follows:
*
* length
* Integer value that determines the maximum length of the text
* field. If this argument is missing the field should be
* declared to have the longest length allowed by the DBMS.
*
* default
* Text value to be used as default for this field.
*
* notnull
* Boolean flag that indicates whether this field is constrained
* to not be set to null.
* @return string DBMS specific SQL code portion that should be used to
* declare the specified field.
* @access public
*/
function getTypeDeclaration($field)
{
$db = $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
switch ($field['type']) {
case 'text':
$length = !empty($field['length'])
? $field['length'] : false;
$fixed = !empty($field['fixed']) ? $field['fixed'] : false;
return $fixed ? ($length ? 'CHAR('.$length.')' : 'CHAR('.$db->options['default_text_field_length'].')')
: ($length ? 'VARCHAR('.$length.')' : 'TEXT');
case 'clob':
if (!empty($field['length'])) {
$length = $field['length'];
if ($length <= 8000) {
return 'VARCHAR('.$length.')';
}
}
return 'TEXT';
case 'blob':
if (!empty($field['length'])) {
$length = $field['length'];
if ($length <= 8000) {
return "VARBINARY($length)";
}
}
return 'IMAGE';
case 'integer':
return 'INT';
case 'boolean':
return 'BIT';
case 'date':
return 'CHAR ('.strlen('YYYY-MM-DD').')';
case 'time':
return 'CHAR ('.strlen('HH:MM:SS').')';
case 'timestamp':
return 'CHAR ('.strlen('YYYY-MM-DD HH:MM:SS').')';
case 'float':
return 'FLOAT';
case 'decimal':
$length = !empty($field['length']) ? $field['length'] : 18;
$scale = !empty($field['scale']) ? $field['scale'] : $db->options['decimal_places'];
return 'DECIMAL('.$length.','.$scale.')';
}
return '';
}
// }}}
// {{{ _getIntegerDeclaration()
/**
* Obtain DBMS specific SQL code portion needed to declare an integer type
* field to be used in statements like CREATE TABLE.
*
* @param string $name name the field to be declared.
* @param string $field associative array with the name of the properties
* of the field being declared as array indexes.
* Currently, the types of supported field
* properties are as follows:
*
* unsigned
* Boolean flag that indicates whether the field
* should be declared as unsigned integer if
* possible.
*
* default
* Integer value to be used as default for this
* field.
*
* notnull
* Boolean flag that indicates whether this field is
* constrained to not be set to null.
* @return string DBMS specific SQL code portion that should be used to
* declare the specified field.
* @access protected
*/
function _getIntegerDeclaration($name, $field)
{
$db = $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
$notnull = empty($field['notnull']) ? ' NULL' : ' NOT NULL';
$default = $autoinc = '';
if (!empty($field['autoincrement'])) {
$autoinc = ' IDENTITY PRIMARY KEY';
} elseif (array_key_exists('default', $field)) {
if ($field['default'] === '') {
$field['default'] = 0;
}
if (null === $field['default']) {
$default = ' DEFAULT (null)';
} else {
$default = ' DEFAULT (' . $this->quote($field['default'], 'integer') . ')';
}
}
if (!empty($field['unsigned'])) {
$db->warnings[] = "unsigned integer field \"$name\" is being declared as signed integer";
}
$name = $db->quoteIdentifier($name, true);
return $name.' '.$this->getTypeDeclaration($field).$notnull.$default.$autoinc;
}
// }}}
// {{{ _getCLOBDeclaration()
/**
* Obtain DBMS specific SQL code portion needed to declare an character
* large object type field to be used in statements like CREATE TABLE.
*
* @param string $name name the field to be declared.
* @param array $field associative array with the name of the properties
* of the field being declared as array indexes. Currently, the types
* of supported field properties are as follows:
*
* length
* Integer value that determines the maximum length of the large
* object field. If this argument is missing the field should be
* declared to have the longest length allowed by the DBMS.
*
* notnull
* Boolean flag that indicates whether this field is constrained
* to not be set to null.
* @return string DBMS specific SQL code portion that should be used to
* declare the specified field.
* @access public
*/
function _getCLOBDeclaration($name, $field)
{
$db = $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
$notnull = empty($field['notnull']) ? ' NULL' : ' NOT NULL';
$name = $db->quoteIdentifier($name, true);
return $name.' '.$this->getTypeDeclaration($field).$notnull;
}
// }}}
// {{{ _getBLOBDeclaration()
/**
* Obtain DBMS specific SQL code portion needed to declare an binary large
* object type field to be used in statements like CREATE TABLE.
*
* @param string $name name the field to be declared.
* @param array $field associative array with the name of the properties
* of the field being declared as array indexes. Currently, the types
* of supported field properties are as follows:
*
* length
* Integer value that determines the maximum length of the large
* object field. If this argument is missing the field should be
* declared to have the longest length allowed by the DBMS.
*
* notnull
* Boolean flag that indicates whether this field is constrained
* to not be set to null.
* @return string DBMS specific SQL code portion that should be used to
* declare the specified field.
* @access protected
*/
function _getBLOBDeclaration($name, $field)
{
$db = $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
$notnull = empty($field['notnull']) ? ' NULL' : ' NOT NULL';
$name = $db->quoteIdentifier($name, true);
return $name.' '.$this->getTypeDeclaration($field).$notnull;
}
// }}}
// {{{ _quoteBLOB()
/**
* Convert a text value into a DBMS specific format that is suitable to
* compose query statements.
*
* @param string $value text string value that is intended to be converted.
* @param bool $quote determines if the value should be quoted and escaped
* @param bool $escape_wildcards if to escape escape wildcards
* @return string text string that represents the given argument value in
* a DBMS specific format.
* @access protected
*/
function _quoteBLOB($value, $quote, $escape_wildcards)
{
if (!$quote) {
return $value;
}
$value = '0x'.bin2hex($this->_readFile($value));
return $value;
}
// }}}
// {{{ matchPattern()
/**
* build a pattern matching string
*
* @access public
*
* @param array $pattern even keys are strings, odd are patterns (% and _)
* @param string $operator optional pattern operator (LIKE, ILIKE and maybe others in the future)
* @param string $field optional field name that is being matched against
* (might be required when emulating ILIKE)
*
* @return string SQL pattern
*/
function matchPattern($pattern, $operator = null, $field = null)
{
$db = $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
$match = '';
if (null !== $operator) {
$field = (null === $field) ? '' : $field.' ';
$operator = strtoupper($operator);
switch ($operator) {
// case insensitive
case 'ILIKE':
$match = $field.'LIKE ';
break;
case 'NOT ILIKE':
$match = $field.'NOT LIKE ';
break;
// case sensitive
case 'LIKE':
$match = $field.'LIKE ';
break;
case 'NOT LIKE':
$match = $field.'NOT LIKE ';
break;
default:
return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
'not a supported operator type:'. $operator, __FUNCTION__);
}
}
$match.= "'";
foreach ($pattern as $key => $value) {
if ($key % 2) {
$match.= $value;
} else {
$match.= $db->escapePattern($db->escape($value));
}
}
$match.= "'";
$match.= $this->patternEscapeString();
return $match;
}
// }}}
// {{{ _mapNativeDatatype()
/**
* Maps a native array description of a field to a MDB2 datatype and length
*
* @param array $field native field description
* @return array containing the various possible types, length, sign, fixed
* @access public
*/
function _mapNativeDatatype($field)
{
// todo: handle length of various int variations
$db_type = preg_replace('/\d/', '', strtolower($field['type']));
$length = $field['length'];
$type = array();
// todo: unsigned handling seems to be missing
$unsigned = $fixed = null;
switch ($db_type) {
case 'bit':
$type[0] = 'boolean';
break;
case 'tinyint':
$type[0] = 'integer';
$length = 1;
break;
case 'smallint':
$type[0] = 'integer';
$length = 2;
break;
case 'int':
$type[0] = 'integer';
$length = 4;
break;
case 'bigint':
$type[0] = 'integer';
$length = 8;
break;
case 'smalldatetime':
case 'datetime':
$type[0] = 'timestamp';
break;
case 'float':
case 'real':
case 'numeric':
$type[0] = 'float';
break;
case 'decimal':
case 'money':
$type[0] = 'decimal';
$length = $field['numeric_precision'].','.$field['numeric_scale'];
break;
case 'text':
case 'ntext':
case 'varchar':
case 'nvarchar':
$fixed = false;
case 'char':
case 'nchar':
$type[0] = 'text';
if ($length == '1') {
$type[] = 'boolean';
if (preg_match('/^(is|has)/', $field['name'])) {
$type = array_reverse($type);
}
} elseif (strstr($db_type, 'text')) {
$type[] = 'clob';
$type = array_reverse($type);
}
if ($fixed !== false) {
$fixed = true;
}
break;
case 'image':
case 'varbinary':
$type[] = 'blob';
$length = null;
break;
default:
$db = $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
'unknown database attribute type: '.$db_type, __FUNCTION__);
}
if ((int)$length <= 0) {
$length = null;
}
return array($type, $length, $unsigned, $fixed);
}
// }}}
}
?>

@ -1,562 +0,0 @@
<?php
// vim: set et ts=4 sw=4 fdm=marker:
// +----------------------------------------------------------------------+
// | PHP versions 4 and 5 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1998-2008 Manuel Lemos, Tomas V.V.Cox, |
// | Stig. S. Bakken, Lukas Smith |
// | All rights reserved. |
// +----------------------------------------------------------------------+
// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB |
// | API as well as database abstraction for PHP applications. |
// | This LICENSE is in the BSD license style. |
// | |
// | Redistribution and use in source and binary forms, with or without |
// | modification, are permitted provided that the following conditions |
// | are met: |
// | |
// | Redistributions of source code must retain the above copyright |
// | notice, this list of conditions and the following disclaimer. |
// | |
// | Redistributions in binary form must reproduce the above copyright |
// | notice, this list of conditions and the following disclaimer in the |
// | documentation and/or other materials provided with the distribution. |
// | |
// | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken, |
// | Lukas Smith nor the names of his contributors may be used to endorse |
// | or promote products derived from this software without specific prior|
// | written permission. |
// | |
// | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
// | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
// | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
// | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE |
// | REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, |
// | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
// | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS|
// | OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED |
// | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
// | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY|
// | WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
// | POSSIBILITY OF SUCH DAMAGE. |
// +----------------------------------------------------------------------+
// | Author: Lukas Smith <smith@pooteeweet.org> |
// +----------------------------------------------------------------------+
//
// $Id: mysql.php 295587 2010-02-28 17:16:38Z quipo $
//
require_once 'MDB2/Driver/Datatype/Common.php';
/**
* MDB2 MySQL driver
*
* @package MDB2
* @category Database
* @author Lukas Smith <smith@pooteeweet.org>
*/
class MDB2_Driver_Datatype_mysql extends MDB2_Driver_Datatype_Common
{
// {{{ _getCharsetFieldDeclaration()
/**
* Obtain DBMS specific SQL code portion needed to set the CHARACTER SET
* of a field declaration to be used in statements like CREATE TABLE.
*
* @param string $charset name of the charset
* @return string DBMS specific SQL code portion needed to set the CHARACTER SET
* of a field declaration.
*/
function _getCharsetFieldDeclaration($charset)
{
return 'CHARACTER SET '.$charset;
}
// }}}
// {{{ _getCollationFieldDeclaration()
/**
* Obtain DBMS specific SQL code portion needed to set the COLLATION
* of a field declaration to be used in statements like CREATE TABLE.
*
* @param string $collation name of the collation
* @return string DBMS specific SQL code portion needed to set the COLLATION
* of a field declaration.
*/
function _getCollationFieldDeclaration($collation)
{
return 'COLLATE '.$collation;
}
// }}}
// {{{ getTypeDeclaration()
/**
* Obtain DBMS specific SQL code portion needed to declare an text type
* field to be used in statements like CREATE TABLE.
*
* @param array $field associative array with the name of the properties
* of the field being declared as array indexes. Currently, the types
* of supported field properties are as follows:
*
* length
* Integer value that determines the maximum length of the text
* field. If this argument is missing the field should be
* declared to have the longest length allowed by the DBMS.
*
* default
* Text value to be used as default for this field.
*
* notnull
* Boolean flag that indicates whether this field is constrained
* to not be set to null.
* @return string DBMS specific SQL code portion that should be used to
* declare the specified field.
* @access public
*/
function getTypeDeclaration($field)
{
$db = $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
switch ($field['type']) {
case 'text':
if (empty($field['length']) && array_key_exists('default', $field)) {
$field['length'] = $db->varchar_max_length;
}
$length = !empty($field['length']) ? $field['length'] : false;
$fixed = !empty($field['fixed']) ? $field['fixed'] : false;
return $fixed ? ($length ? 'CHAR('.$length.')' : 'CHAR(255)')
: ($length ? 'VARCHAR('.$length.')' : 'TEXT');
case 'clob':
if (!empty($field['length'])) {
$length = $field['length'];
if ($length <= 255) {
return 'TINYTEXT';
} elseif ($length <= 65532) {
return 'TEXT';
} elseif ($length <= 16777215) {
return 'MEDIUMTEXT';
}
}
return 'LONGTEXT';
case 'blob':
if (!empty($field['length'])) {
$length = $field['length'];
if ($length <= 255) {
return 'TINYBLOB';
} elseif ($length <= 65532) {
return 'BLOB';
} elseif ($length <= 16777215) {
return 'MEDIUMBLOB';
}
}
return 'LONGBLOB';
case 'integer':
if (!empty($field['length'])) {
$length = $field['length'];
if ($length <= 1) {
return 'TINYINT';
} elseif ($length == 2) {
return 'SMALLINT';
} elseif ($length == 3) {
return 'MEDIUMINT';
} elseif ($length == 4) {
return 'INT';
} elseif ($length > 4) {
return 'BIGINT';
}
}
return 'INT';
case 'boolean':
return 'TINYINT(1)';
case 'date':
return 'DATE';
case 'time':
return 'TIME';
case 'timestamp':
return 'DATETIME';
case 'float':
return 'DOUBLE';
case 'decimal':
$length = !empty($field['length']) ? $field['length'] : 18;
$scale = !empty($field['scale']) ? $field['scale'] : $db->options['decimal_places'];
return 'DECIMAL('.$length.','.$scale.')';
}
return '';
}
// }}}
// {{{ _getIntegerDeclaration()
/**
* Obtain DBMS specific SQL code portion needed to declare an integer type
* field to be used in statements like CREATE TABLE.
*
* @param string $name name the field to be declared.
* @param string $field associative array with the name of the properties
* of the field being declared as array indexes.
* Currently, the types of supported field
* properties are as follows:
*
* unsigned
* Boolean flag that indicates whether the field
* should be declared as unsigned integer if
* possible.
*
* default
* Integer value to be used as default for this
* field.
*
* notnull
* Boolean flag that indicates whether this field is
* constrained to not be set to null.
* @return string DBMS specific SQL code portion that should be used to
* declare the specified field.
* @access protected
*/
function _getIntegerDeclaration($name, $field)
{
$db = $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
$default = $autoinc = '';
if (!empty($field['autoincrement'])) {
$autoinc = ' AUTO_INCREMENT PRIMARY KEY';
} elseif (array_key_exists('default', $field)) {
if ($field['default'] === '') {
$field['default'] = empty($field['notnull']) ? null : 0;
}
$default = ' DEFAULT '.$this->quote($field['default'], 'integer');
}
$notnull = empty($field['notnull']) ? '' : ' NOT NULL';
$unsigned = empty($field['unsigned']) ? '' : ' UNSIGNED';
if (empty($default) && empty($notnull)) {
$default = ' DEFAULT NULL';
}
$name = $db->quoteIdentifier($name, true);
return $name.' '.$this->getTypeDeclaration($field).$unsigned.$default.$notnull.$autoinc;
}
// }}}
// {{{ _getFloatDeclaration()
/**
* Obtain DBMS specific SQL code portion needed to declare an float type
* field to be used in statements like CREATE TABLE.
*
* @param string $name name the field to be declared.
* @param string $field associative array with the name of the properties
* of the field being declared as array indexes.
* Currently, the types of supported field
* properties are as follows:
*
* unsigned
* Boolean flag that indicates whether the field
* should be declared as unsigned float if
* possible.
*
* default
* float value to be used as default for this
* field.
*
* notnull
* Boolean flag that indicates whether this field is
* constrained to not be set to null.
* @return string DBMS specific SQL code portion that should be used to
* declare the specified field.
* @access protected
*/
function _getFloatDeclaration($name, $field)
{
// Since AUTO_INCREMENT can be used for integer or floating-point types,
// reuse the INTEGER declaration
// @see http://bugs.mysql.com/bug.php?id=31032
return $this->_getIntegerDeclaration($name, $field);
}
// }}}
// {{{ _getDecimalDeclaration()
/**
* Obtain DBMS specific SQL code portion needed to declare an decimal type
* field to be used in statements like CREATE TABLE.
*
* @param string $name name the field to be declared.
* @param string $field associative array with the name of the properties
* of the field being declared as array indexes.
* Currently, the types of supported field
* properties are as follows:
*
* unsigned
* Boolean flag that indicates whether the field
* should be declared as unsigned integer if
* possible.
*
* default
* Decimal value to be used as default for this
* field.
*
* notnull
* Boolean flag that indicates whether this field is
* constrained to not be set to null.
* @return string DBMS specific SQL code portion that should be used to
* declare the specified field.
* @access protected
*/
function _getDecimalDeclaration($name, $field)
{
$db = $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
$default = '';
if (array_key_exists('default', $field)) {
if ($field['default'] === '') {
$field['default'] = empty($field['notnull']) ? null : 0;
}
$default = ' DEFAULT '.$this->quote($field['default'], 'integer');
} elseif (empty($field['notnull'])) {
$default = ' DEFAULT NULL';
}
$notnull = empty($field['notnull']) ? '' : ' NOT NULL';
$unsigned = empty($field['unsigned']) ? '' : ' UNSIGNED';
$name = $db->quoteIdentifier($name, true);
return $name.' '.$this->getTypeDeclaration($field).$unsigned.$default.$notnull;
}
// }}}
// {{{ matchPattern()
/**
* build a pattern matching string
*
* @access public
*
* @param array $pattern even keys are strings, odd are patterns (% and _)
* @param string $operator optional pattern operator (LIKE, ILIKE and maybe others in the future)
* @param string $field optional field name that is being matched against
* (might be required when emulating ILIKE)
*
* @return string SQL pattern
*/
function matchPattern($pattern, $operator = null, $field = null)
{
$db = $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
$match = '';
if (null !== $operator) {
$field = (null === $field) ? '' : $field.' ';
$operator = strtoupper($operator);
switch ($operator) {
// case insensitive
case 'ILIKE':
$match = $field.'LIKE ';
break;
case 'NOT ILIKE':
$match = $field.'NOT LIKE ';
break;
// case sensitive
case 'LIKE':
$match = $field.'LIKE BINARY ';
break;
case 'NOT LIKE':
$match = $field.'NOT LIKE BINARY ';
break;
default:
return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
'not a supported operator type:'. $operator, __FUNCTION__);
}
}
$match.= "'";
foreach ($pattern as $key => $value) {
if ($key % 2) {
$match.= $value;
} else {
$match.= $db->escapePattern($db->escape($value));
}
}
$match.= "'";
$match.= $this->patternEscapeString();
return $match;
}
// }}}
// {{{ _mapNativeDatatype()
/**
* Maps a native array description of a field to a MDB2 datatype and length
*
* @param array $field native field description
* @return array containing the various possible types, length, sign, fixed
* @access public
*/
function _mapNativeDatatype($field)
{
$db_type = strtolower($field['type']);
$db_type = strtok($db_type, '(), ');
if ($db_type == 'national') {
$db_type = strtok('(), ');
}
if (!empty($field['length'])) {
$length = strtok($field['length'], ', ');
$decimal = strtok(', ');
} else {
$length = strtok('(), ');
$decimal = strtok('(), ');
}
$type = array();
$unsigned = $fixed = null;
switch ($db_type) {
case 'tinyint':
$type[] = 'integer';
$type[] = 'boolean';
if (preg_match('/^(is|has)/', $field['name'])) {
$type = array_reverse($type);
}
$unsigned = preg_match('/ unsigned/i', $field['type']);
$length = 1;
break;
case 'smallint':
$type[] = 'integer';
$unsigned = preg_match('/ unsigned/i', $field['type']);
$length = 2;
break;
case 'mediumint':
$type[] = 'integer';
$unsigned = preg_match('/ unsigned/i', $field['type']);
$length = 3;
break;
case 'int':
case 'integer':
$type[] = 'integer';
$unsigned = preg_match('/ unsigned/i', $field['type']);
$length = 4;
break;
case 'bigint':
$type[] = 'integer';
$unsigned = preg_match('/ unsigned/i', $field['type']);
$length = 8;
break;
case 'tinytext':
case 'mediumtext':
case 'longtext':
case 'text':
case 'varchar':
$fixed = false;
case 'string':
case 'char':
$type[] = 'text';
if ($length == '1') {
$type[] = 'boolean';
if (preg_match('/^(is|has)/', $field['name'])) {
$type = array_reverse($type);
}
} elseif (strstr($db_type, 'text')) {
$type[] = 'clob';
if ($decimal == 'binary') {
$type[] = 'blob';
}
$type = array_reverse($type);
}
if ($fixed !== false) {
$fixed = true;
}
break;
case 'enum':
$type[] = 'text';
preg_match_all('/\'.+\'/U', $field['type'], $matches);
$length = 0;
$fixed = false;
if (is_array($matches)) {
foreach ($matches[0] as $value) {
$length = max($length, strlen($value)-2);
}
if ($length == '1' && count($matches[0]) == 2) {
$type[] = 'boolean';
if (preg_match('/^(is|has)/', $field['name'])) {
$type = array_reverse($type);
}
}
}
$type[] = 'integer';
case 'set':
$fixed = false;
$type[] = 'text';
$type[] = 'integer';
break;
case 'date':
$type[] = 'date';
$length = null;
break;
case 'datetime':
case 'timestamp':
$type[] = 'timestamp';
$length = null;
break;
case 'time':
$type[] = 'time';
$length = null;
break;
case 'float':
case 'double':
case 'real':
$type[] = 'float';
$unsigned = preg_match('/ unsigned/i', $field['type']);
break;
case 'unknown':
case 'decimal':
case 'numeric':
$type[] = 'decimal';
$unsigned = preg_match('/ unsigned/i', $field['type']);
if ($decimal !== false) {
$length = $length.','.$decimal;
}
break;
case 'tinyblob':
case 'mediumblob':
case 'longblob':
case 'blob':
$type[] = 'blob';
$length = null;
break;
case 'binary':
case 'varbinary':
$type[] = 'blob';
break;
case 'year':
$type[] = 'integer';
$type[] = 'date';
$length = null;
break;
default:
$db = $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
'unknown database attribute type: '.$db_type, __FUNCTION__);
}
if ((int)$length <= 0) {
$length = null;
}
return array($type, $length, $unsigned, $fixed);
}
// }}}
}
?>

@ -1,599 +0,0 @@
<?php
// vim: set et ts=4 sw=4 fdm=marker:
// +----------------------------------------------------------------------+
// | PHP versions 4 and 5 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1998-2007 Manuel Lemos, Tomas V.V.Cox, |
// | Stig. S. Bakken, Lukas Smith |
// | All rights reserved. |
// +----------------------------------------------------------------------+
// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB |
// | API as well as database abstraction for PHP applications. |
// | This LICENSE is in the BSD license style. |
// | |
// | Redistribution and use in source and binary forms, with or without |
// | modification, are permitted provided that the following conditions |
// | are met: |
// | |
// | Redistributions of source code must retain the above copyright |
// | notice, this list of conditions and the following disclaimer. |
// | |
// | Redistributions in binary form must reproduce the above copyright |
// | notice, this list of conditions and the following disclaimer in the |
// | documentation and/or other materials provided with the distribution. |
// | |
// | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken, |
// | Lukas Smith nor the names of his contributors may be used to endorse |
// | or promote products derived from this software without specific prior|
// | written permission. |
// | |
// | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
// | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
// | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
// | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE |
// | REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, |
// | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
// | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS|
// | OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED |
// | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
// | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY|
// | WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
// | POSSIBILITY OF SUCH DAMAGE. |
// +----------------------------------------------------------------------+
// | Author: Lukas Smith <smith@pooteeweet.org> |
// +----------------------------------------------------------------------+
//
// $Id: mysqli.php 295587 2010-02-28 17:16:38Z quipo $
//
require_once 'MDB2/Driver/Datatype/Common.php';
/**
* MDB2 MySQLi driver
*
* @package MDB2
* @category Database
* @author Lukas Smith <smith@pooteeweet.org>
*/
class MDB2_Driver_Datatype_mysqli extends MDB2_Driver_Datatype_Common
{
// {{{ _getCharsetFieldDeclaration()
/**
* Obtain DBMS specific SQL code portion needed to set the CHARACTER SET
* of a field declaration to be used in statements like CREATE TABLE.
*
* @param string $charset name of the charset
* @return string DBMS specific SQL code portion needed to set the CHARACTER SET
* of a field declaration.
*/
function _getCharsetFieldDeclaration($charset)
{
return 'CHARACTER SET '.$charset;
}
// }}}
// {{{ _getCollationFieldDeclaration()
/**
* Obtain DBMS specific SQL code portion needed to set the COLLATION
* of a field declaration to be used in statements like CREATE TABLE.
*
* @param string $collation name of the collation
* @return string DBMS specific SQL code portion needed to set the COLLATION
* of a field declaration.
*/
function _getCollationFieldDeclaration($collation)
{
return 'COLLATE '.$collation;
}
// }}}
// {{{ getTypeDeclaration()
/**
* Obtain DBMS specific SQL code portion needed to declare an text type
* field to be used in statements like CREATE TABLE.
*
* @param array $field associative array with the name of the properties
* of the field being declared as array indexes. Currently, the types
* of supported field properties are as follows:
*
* length
* Integer value that determines the maximum length of the text
* field. If this argument is missing the field should be
* declared to have the longest length allowed by the DBMS.
*
* default
* Text value to be used as default for this field.
*
* notnull
* Boolean flag that indicates whether this field is constrained
* to not be set to null.
* @return string DBMS specific SQL code portion that should be used to
* declare the specified field.
* @access public
*/
function getTypeDeclaration($field)
{
$db = $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
switch ($field['type']) {
case 'text':
if (empty($field['length']) && array_key_exists('default', $field)) {
$field['length'] = $db->varchar_max_length;
}
$length = !empty($field['length']) ? $field['length'] : false;
$fixed = !empty($field['fixed']) ? $field['fixed'] : false;
return $fixed ? ($length ? 'CHAR('.$length.')' : 'CHAR(255)')
: ($length ? 'VARCHAR('.$length.')' : 'TEXT');
case 'clob':
if (!empty($field['length'])) {
$length = $field['length'];
if ($length <= 255) {
return 'TINYTEXT';
} elseif ($length <= 65532) {
return 'TEXT';
} elseif ($length <= 16777215) {
return 'MEDIUMTEXT';
}
}
return 'LONGTEXT';
case 'blob':
if (!empty($field['length'])) {
$length = $field['length'];
if ($length <= 255) {
return 'TINYBLOB';
} elseif ($length <= 65532) {
return 'BLOB';
} elseif ($length <= 16777215) {
return 'MEDIUMBLOB';
}
}
return 'LONGBLOB';
case 'integer':
if (!empty($field['length'])) {
$length = $field['length'];
if ($length <= 1) {
return 'TINYINT';
} elseif ($length == 2) {
return 'SMALLINT';
} elseif ($length == 3) {
return 'MEDIUMINT';
} elseif ($length == 4) {
return 'INT';
} elseif ($length > 4) {
return 'BIGINT';
}
}
return 'INT';
case 'boolean':
return 'TINYINT(1)';
case 'date':
return 'DATE';
case 'time':
return 'TIME';
case 'timestamp':
return 'DATETIME';
case 'float':
return 'DOUBLE';
case 'decimal':
$length = !empty($field['length']) ? $field['length'] : 18;
$scale = !empty($field['scale']) ? $field['scale'] : $db->options['decimal_places'];
return 'DECIMAL('.$length.','.$scale.')';
}
return '';
}
// }}}
// {{{ _getIntegerDeclaration()
/**
* Obtain DBMS specific SQL code portion needed to declare an integer type
* field to be used in statements like CREATE TABLE.
*
* @param string $name name the field to be declared.
* @param string $field associative array with the name of the properties
* of the field being declared as array indexes.
* Currently, the types of supported field
* properties are as follows:
*
* unsigned
* Boolean flag that indicates whether the field
* should be declared as unsigned integer if
* possible.
*
* default
* Integer value to be used as default for this
* field.
*
* notnull
* Boolean flag that indicates whether this field is
* constrained to not be set to null.
* @return string DBMS specific SQL code portion that should be used to
* declare the specified field.
* @access protected
*/
function _getIntegerDeclaration($name, $field)
{
$db = $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
$default = $autoinc = '';
if (!empty($field['autoincrement'])) {
$autoinc = ' AUTO_INCREMENT PRIMARY KEY';
} elseif (array_key_exists('default', $field)) {
if ($field['default'] === '') {
$field['default'] = empty($field['notnull']) ? null : 0;
}
$default = ' DEFAULT '.$this->quote($field['default'], 'integer');
}
$notnull = empty($field['notnull']) ? '' : ' NOT NULL';
$unsigned = empty($field['unsigned']) ? '' : ' UNSIGNED';
if (empty($default) && empty($notnull)) {
$default = ' DEFAULT NULL';
}
$name = $db->quoteIdentifier($name, true);
return $name.' '.$this->getTypeDeclaration($field).$unsigned.$default.$notnull.$autoinc;
}
// }}}
// {{{ _getFloatDeclaration()
/**
* Obtain DBMS specific SQL code portion needed to declare an float type
* field to be used in statements like CREATE TABLE.
*
* @param string $name name the field to be declared.
* @param string $field associative array with the name of the properties
* of the field being declared as array indexes.
* Currently, the types of supported field
* properties are as follows:
*
* unsigned
* Boolean flag that indicates whether the field
* should be declared as unsigned float if
* possible.
*
* default
* float value to be used as default for this
* field.
*
* notnull
* Boolean flag that indicates whether this field is
* constrained to not be set to null.
* @return string DBMS specific SQL code portion that should be used to
* declare the specified field.
* @access protected
*/
function _getFloatDeclaration($name, $field)
{
// Since AUTO_INCREMENT can be used for integer or floating-point types,
// reuse the INTEGER declaration
// @see http://bugs.mysql.com/bug.php?id=31032
return $this->_getIntegerDeclaration($name, $field);
}
// }}}
// {{{ _getDecimalDeclaration()
/**
* Obtain DBMS specific SQL code portion needed to declare an decimal type
* field to be used in statements like CREATE TABLE.
*
* @param string $name name the field to be declared.
* @param string $field associative array with the name of the properties
* of the field being declared as array indexes.
* Currently, the types of supported field
* properties are as follows:
*
* unsigned
* Boolean flag that indicates whether the field
* should be declared as unsigned integer if
* possible.
*
* default
* Decimal value to be used as default for this
* field.
*
* notnull
* Boolean flag that indicates whether this field is
* constrained to not be set to null.
* @return string DBMS specific SQL code portion that should be used to
* declare the specified field.
* @access protected
*/
function _getDecimalDeclaration($name, $field)
{
$db = $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
$default = '';
if (array_key_exists('default', $field)) {
if ($field['default'] === '') {
$field['default'] = empty($field['notnull']) ? null : 0;
}
$default = ' DEFAULT '.$this->quote($field['default'], 'integer');
} elseif (empty($field['notnull'])) {
$default = ' DEFAULT NULL';
}
$notnull = empty($field['notnull']) ? '' : ' NOT NULL';
$unsigned = empty($field['unsigned']) ? '' : ' UNSIGNED';
$name = $db->quoteIdentifier($name, true);
return $name.' '.$this->getTypeDeclaration($field).$unsigned.$default.$notnull;
}
// }}}
// {{{ matchPattern()
/**
* build a pattern matching string
*
* @access public
*
* @param array $pattern even keys are strings, odd are patterns (% and _)
* @param string $operator optional pattern operator (LIKE, ILIKE and maybe others in the future)
* @param string $field optional field name that is being matched against
* (might be required when emulating ILIKE)
*
* @return string SQL pattern
*/
function matchPattern($pattern, $operator = null, $field = null)
{
$db = $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
$match = '';
if (null !== $operator) {
$field = (null === $field) ? '' : $field.' ';
$operator = strtoupper($operator);
switch ($operator) {
// case insensitive
case 'ILIKE':
$match = $field.'LIKE ';
break;
case 'NOT ILIKE':
$match = $field.'NOT LIKE ';
break;
// case sensitive
case 'LIKE':
$match = $field.'LIKE BINARY ';
break;
case 'NOT LIKE':
$match = $field.'NOT LIKE BINARY ';
break;
default:
return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
'not a supported operator type:'. $operator, __FUNCTION__);
}
}
$match.= "'";
foreach ($pattern as $key => $value) {
if ($key % 2) {
$match.= $value;
} else {
$match.= $db->escapePattern($db->escape($value));
}
}
$match.= "'";
$match.= $this->patternEscapeString();
return $match;
}
// }}}
// {{{ _mapNativeDatatype()
/**
* Maps a native array description of a field to a MDB2 datatype and length
*
* @param array $field native field description
* @return array containing the various possible types, length, sign, fixed
* @access public
*/
function _mapNativeDatatype($field)
{
$db_type = strtolower($field['type']);
$db_type = strtok($db_type, '(), ');
if ($db_type == 'national') {
$db_type = strtok('(), ');
}
if (!empty($field['length'])) {
$length = strtok($field['length'], ', ');
$decimal = strtok(', ');
} else {
$length = strtok('(), ');
$decimal = strtok('(), ');
}
$type = array();
$unsigned = $fixed = null;
switch ($db_type) {
case 'tinyint':
$type[] = 'integer';
$type[] = 'boolean';
if (preg_match('/^(is|has)/', $field['name'])) {
$type = array_reverse($type);
}
$unsigned = preg_match('/ unsigned/i', $field['type']);
$length = 1;
break;
case 'smallint':
$type[] = 'integer';
$unsigned = preg_match('/ unsigned/i', $field['type']);
$length = 2;
break;
case 'mediumint':
$type[] = 'integer';
$unsigned = preg_match('/ unsigned/i', $field['type']);
$length = 3;
break;
case 'int':
case 'integer':
$type[] = 'integer';
$unsigned = preg_match('/ unsigned/i', $field['type']);
$length = 4;
break;
case 'bigint':
$type[] = 'integer';
$unsigned = preg_match('/ unsigned/i', $field['type']);
$length = 8;
break;
case 'tinytext':
case 'mediumtext':
case 'longtext':
case 'text':
case 'varchar':
$fixed = false;
case 'string':
case 'char':
$type[] = 'text';
if ($length == '1') {
$type[] = 'boolean';
if (preg_match('/^(is|has)/', $field['name'])) {
$type = array_reverse($type);
}
} elseif (strstr($db_type, 'text')) {
$type[] = 'clob';
if ($decimal == 'binary') {
$type[] = 'blob';
}
$type = array_reverse($type);
}
if ($fixed !== false) {
$fixed = true;
}
break;
case 'enum':
$type[] = 'text';
preg_match_all('/\'.+\'/U', $field['type'], $matches);
$length = 0;
$fixed = false;
if (is_array($matches)) {
foreach ($matches[0] as $value) {
$length = max($length, strlen($value)-2);
}
if ($length == '1' && count($matches[0]) == 2) {
$type[] = 'boolean';
if (preg_match('/^(is|has)/', $field['name'])) {
$type = array_reverse($type);
}
}
}
$type[] = 'integer';
case 'set':
$fixed = false;
$type[] = 'text';
$type[] = 'integer';
break;
case 'date':
$type[] = 'date';
$length = null;
break;
case 'datetime':
case 'timestamp':
$type[] = 'timestamp';
$length = null;
break;
case 'time':
$type[] = 'time';
$length = null;
break;
case 'float':
case 'double':
case 'real':
$type[] = 'float';
$unsigned = preg_match('/ unsigned/i', $field['type']);
break;
case 'unknown':
case 'decimal':
case 'numeric':
$type[] = 'decimal';
$unsigned = preg_match('/ unsigned/i', $field['type']);
if ($decimal !== false) {
$length = $length.','.$decimal;
}
break;
case 'tinyblob':
case 'mediumblob':
case 'longblob':
case 'blob':
$type[] = 'blob';
$length = null;
break;
case 'binary':
case 'varbinary':
$type[] = 'blob';
break;
case 'year':
$type[] = 'integer';
$type[] = 'date';
$length = null;
break;
default:
$db = $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
'unknown database attribute type: '.$db_type, __FUNCTION__);
}
if ((int)$length <= 0) {
$length = null;
}
return array($type, $length, $unsigned, $fixed);
}
// }}}
// {{{ mapPrepareDatatype()
/**
* Maps an MDB2 datatype to native prepare type
*
* @param string $type
* @return string
* @access public
*/
function mapPrepareDatatype($type)
{
$db = $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
if (!empty($db->options['datatype_map'][$type])) {
$type = $db->options['datatype_map'][$type];
if (!empty($db->options['datatype_map_callback'][$type])) {
$parameter = array('type' => $type);
return call_user_func_array($db->options['datatype_map_callback'][$type], array(&$db, __FUNCTION__, $parameter));
}
}
switch ($type) {
case 'integer':
return 'i';
case 'float':
return 'd';
case 'blob':
return 'b';
default:
break;
}
return 's';
}
// }}}
}
?>

@ -1,579 +0,0 @@
<?php
// +----------------------------------------------------------------------+
// | PHP versions 4 and 5 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1998-2007 Manuel Lemos, Tomas V.V.Cox, |
// | Stig. S. Bakken, Lukas Smith |
// | All rights reserved. |
// +----------------------------------------------------------------------+
// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB |
// | API as well as database abstraction for PHP applications. |
// | This LICENSE is in the BSD license style. |
// | |
// | Redistribution and use in source and binary forms, with or without |
// | modification, are permitted provided that the following conditions |
// | are met: |
// | |
// | Redistributions of source code must retain the above copyright |
// | notice, this list of conditions and the following disclaimer. |
// | |
// | Redistributions in binary form must reproduce the above copyright |
// | notice, this list of conditions and the following disclaimer in the |
// | documentation and/or other materials provided with the distribution. |
// | |
// | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken, |
// | Lukas Smith nor the names of his contributors may be used to endorse |
// | or promote products derived from this software without specific prior|
// | written permission. |
// | |
// | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
// | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
// | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
// | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE |
// | REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, |
// | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
// | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS|
// | OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED |
// | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
// | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY|
// | WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
// | POSSIBILITY OF SUCH DAMAGE. |
// +----------------------------------------------------------------------+
// | Author: Paul Cooper <pgc@ucecom.com> |
// +----------------------------------------------------------------------+
//
// $Id: pgsql.php 295587 2010-02-28 17:16:38Z quipo $
require_once 'MDB2/Driver/Datatype/Common.php';
/**
* MDB2 PostGreSQL driver
*
* @package MDB2
* @category Database
* @author Paul Cooper <pgc@ucecom.com>
*/
class MDB2_Driver_Datatype_pgsql extends MDB2_Driver_Datatype_Common
{
// {{{ _baseConvertResult()
/**
* General type conversion method
*
* @param mixed $value refernce to a value to be converted
* @param string $type specifies which type to convert to
* @param boolean $rtrim [optional] when TRUE [default], apply rtrim() to text
* @return object a MDB2 error on failure
* @access protected
*/
function _baseConvertResult($value, $type, $rtrim = true)
{
if (null === $value) {
return null;
}
switch ($type) {
case 'boolean':
return $value == 't';
case 'float':
return doubleval($value);
case 'date':
return $value;
case 'time':
return substr($value, 0, strlen('HH:MM:SS'));
case 'timestamp':
return substr($value, 0, strlen('YYYY-MM-DD HH:MM:SS'));
case 'blob':
$value = pg_unescape_bytea($value);
return parent::_baseConvertResult($value, $type, $rtrim);
}
return parent::_baseConvertResult($value, $type, $rtrim);
}
// }}}
// {{{ getTypeDeclaration()
/**
* Obtain DBMS specific SQL code portion needed to declare an text type
* field to be used in statements like CREATE TABLE.
*
* @param array $field associative array with the name of the properties
* of the field being declared as array indexes. Currently, the types
* of supported field properties are as follows:
*
* length
* Integer value that determines the maximum length of the text
* field. If this argument is missing the field should be
* declared to have the longest length allowed by the DBMS.
*
* default
* Text value to be used as default for this field.
*
* notnull
* Boolean flag that indicates whether this field is constrained
* to not be set to null.
* @return string DBMS specific SQL code portion that should be used to
* declare the specified field.
* @access public
*/
function getTypeDeclaration($field)
{
$db = $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
switch ($field['type']) {
case 'text':
$length = !empty($field['length']) ? $field['length'] : false;
$fixed = !empty($field['fixed']) ? $field['fixed'] : false;
return $fixed ? ($length ? 'CHAR('.$length.')' : 'CHAR('.$db->options['default_text_field_length'].')')
: ($length ? 'VARCHAR('.$length.')' : 'TEXT');
case 'clob':
return 'TEXT';
case 'blob':
return 'BYTEA';
case 'integer':
if (!empty($field['autoincrement'])) {
if (!empty($field['length'])) {
$length = $field['length'];
if ($length > 4) {
return 'BIGSERIAL PRIMARY KEY';
}
}
return 'SERIAL PRIMARY KEY';
}
if (!empty($field['length'])) {
$length = $field['length'];
if ($length <= 2) {
return 'SMALLINT';
} elseif ($length == 3 || $length == 4) {
return 'INT';
} elseif ($length > 4) {
return 'BIGINT';
}
}
return 'INT';
case 'boolean':
return 'BOOLEAN';
case 'date':
return 'DATE';
case 'time':
return 'TIME without time zone';
case 'timestamp':
return 'TIMESTAMP without time zone';
case 'float':
return 'FLOAT8';
case 'decimal':
$length = !empty($field['length']) ? $field['length'] : 18;
$scale = !empty($field['scale']) ? $field['scale'] : $db->options['decimal_places'];
return 'NUMERIC('.$length.','.$scale.')';
}
}
// }}}
// {{{ _getIntegerDeclaration()
/**
* Obtain DBMS specific SQL code portion needed to declare an integer type
* field to be used in statements like CREATE TABLE.
*
* @param string $name name the field to be declared.
* @param array $field associative array with the name of the properties
* of the field being declared as array indexes. Currently, the types
* of supported field properties are as follows:
*
* unsigned
* Boolean flag that indicates whether the field should be
* declared as unsigned integer if possible.
*
* default
* Integer value to be used as default for this field.
*
* notnull
* Boolean flag that indicates whether this field is constrained
* to not be set to null.
* @return string DBMS specific SQL code portion that should be used to
* declare the specified field.
* @access protected
*/
function _getIntegerDeclaration($name, $field)
{
$db = $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
if (!empty($field['unsigned'])) {
$db->warnings[] = "unsigned integer field \"$name\" is being declared as signed integer";
}
if (!empty($field['autoincrement'])) {
$name = $db->quoteIdentifier($name, true);
return $name.' '.$this->getTypeDeclaration($field);
}
$default = '';
if (array_key_exists('default', $field)) {
if ($field['default'] === '') {
$field['default'] = empty($field['notnull']) ? null : 0;
}
$default = ' DEFAULT '.$this->quote($field['default'], 'integer');
}
$notnull = empty($field['notnull']) ? '' : ' NOT NULL';
if (empty($default) && empty($notnull)) {
$default = ' DEFAULT NULL';
}
$name = $db->quoteIdentifier($name, true);
return $name.' '.$this->getTypeDeclaration($field).$default.$notnull;
}
// }}}
// {{{ _quoteCLOB()
/**
* Convert a text value into a DBMS specific format that is suitable to
* compose query statements.
*
* @param string $value text string value that is intended to be converted.
* @param bool $quote determines if the value should be quoted and escaped
* @param bool $escape_wildcards if to escape escape wildcards
* @return string text string that represents the given argument value in
* a DBMS specific format.
* @access protected
*/
function _quoteCLOB($value, $quote, $escape_wildcards)
{
$db = $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
if ($db->options['lob_allow_url_include']) {
$value = $this->_readFile($value);
if (PEAR::isError($value)) {
return $value;
}
}
return $this->_quoteText($value, $quote, $escape_wildcards);
}
// }}}
// {{{ _quoteBLOB()
/**
* Convert a text value into a DBMS specific format that is suitable to
* compose query statements.
*
* @param string $value text string value that is intended to be converted.
* @param bool $quote determines if the value should be quoted and escaped
* @param bool $escape_wildcards if to escape escape wildcards
* @return string text string that represents the given argument value in
* a DBMS specific format.
* @access protected
*/
function _quoteBLOB($value, $quote, $escape_wildcards)
{
if (!$quote) {
return $value;
}
$db = $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
if ($db->options['lob_allow_url_include']) {
$value = $this->_readFile($value);
if (PEAR::isError($value)) {
return $value;
}
}
if (version_compare(PHP_VERSION, '5.2.0RC6', '>=')) {
$connection = $db->getConnection();
if (PEAR::isError($connection)) {
return $connection;
}
$value = @pg_escape_bytea($connection, $value);
} else {
$value = @pg_escape_bytea($value);
}
return "'".$value."'";
}
// }}}
// {{{ _quoteBoolean()
/**
* Convert a text value into a DBMS specific format that is suitable to
* compose query statements.
*
* @param string $value text string value that is intended to be converted.
* @param bool $quote determines if the value should be quoted and escaped
* @param bool $escape_wildcards if to escape escape wildcards
* @return string text string that represents the given argument value in
* a DBMS specific format.
* @access protected
*/
function _quoteBoolean($value, $quote, $escape_wildcards)
{
$value = $value ? 't' : 'f';
if (!$quote) {
return $value;
}
return "'".$value."'";
}
// }}}
// {{{ matchPattern()
/**
* build a pattern matching string
*
* @access public
*
* @param array $pattern even keys are strings, odd are patterns (% and _)
* @param string $operator optional pattern operator (LIKE, ILIKE and maybe others in the future)
* @param string $field optional field name that is being matched against
* (might be required when emulating ILIKE)
*
* @return string SQL pattern
*/
function matchPattern($pattern, $operator = null, $field = null)
{
$db = $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
$match = '';
if (null !== $operator) {
$field = (null === $field) ? '' : $field.' ';
$operator = strtoupper($operator);
switch ($operator) {
// case insensitive
case 'ILIKE':
$match = $field.'ILIKE ';
break;
case 'NOT ILIKE':
$match = $field.'NOT ILIKE ';
break;
// case sensitive
case 'LIKE':
$match = $field.'LIKE ';
break;
case 'NOT LIKE':
$match = $field.'NOT LIKE ';
break;
default:
return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
'not a supported operator type:'. $operator, __FUNCTION__);
}
}
$match.= "'";
foreach ($pattern as $key => $value) {
if ($key % 2) {
$match.= $value;
} else {
$match.= $db->escapePattern($db->escape($value));
}
}
$match.= "'";
$match.= $this->patternEscapeString();
return $match;
}
// }}}
// {{{ patternEscapeString()
/**
* build string to define escape pattern string
*
* @access public
*
*
* @return string define escape pattern
*/
function patternEscapeString()
{
$db = $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
return ' ESCAPE '.$this->quote($db->string_quoting['escape_pattern']);
}
// }}}
// {{{ _mapNativeDatatype()
/**
* Maps a native array description of a field to a MDB2 datatype and length
*
* @param array $field native field description
* @return array containing the various possible types, length, sign, fixed
* @access public
*/
function _mapNativeDatatype($field)
{
$db_type = strtolower($field['type']);
$length = $field['length'];
$type = array();
$unsigned = $fixed = null;
switch ($db_type) {
case 'smallint':
case 'int2':
$type[] = 'integer';
$unsigned = false;
$length = 2;
if ($length == '2') {
$type[] = 'boolean';
if (preg_match('/^(is|has)/', $field['name'])) {
$type = array_reverse($type);
}
}
break;
case 'int':
case 'int4':
case 'integer':
case 'serial':
case 'serial4':
$type[] = 'integer';
$unsigned = false;
$length = 4;
break;
case 'bigint':
case 'int8':
case 'bigserial':
case 'serial8':
$type[] = 'integer';
$unsigned = false;
$length = 8;
break;
case 'bool':
case 'boolean':
$type[] = 'boolean';
$length = null;
break;
case 'text':
case 'varchar':
$fixed = false;
case 'unknown':
case 'char':
case 'bpchar':
$type[] = 'text';
if ($length == '1') {
$type[] = 'boolean';
if (preg_match('/^(is|has)/', $field['name'])) {
$type = array_reverse($type);
}
} elseif (strstr($db_type, 'text')) {
$type[] = 'clob';
$type = array_reverse($type);
}
if ($fixed !== false) {
$fixed = true;
}
break;
case 'date':
$type[] = 'date';
$length = null;
break;
case 'datetime':
case 'timestamp':
case 'timestamptz':
$type[] = 'timestamp';
$length = null;
break;
case 'time':
$type[] = 'time';
$length = null;
break;
case 'float':
case 'float4':
case 'float8':
case 'double':
case 'real':
$type[] = 'float';
break;
case 'decimal':
case 'money':
case 'numeric':
$type[] = 'decimal';
if (isset($field['scale'])) {
$length = $length.','.$field['scale'];
}
break;
case 'tinyblob':
case 'mediumblob':
case 'longblob':
case 'blob':
case 'bytea':
$type[] = 'blob';
$length = null;
break;
case 'oid':
$type[] = 'blob';
$type[] = 'clob';
$length = null;
break;
case 'year':
$type[] = 'integer';
$type[] = 'date';
$length = null;
break;
default:
$db = $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
'unknown database attribute type: '.$db_type, __FUNCTION__);
}
if ((int)$length <= 0) {
$length = null;
}
return array($type, $length, $unsigned, $fixed);
}
// }}}
// {{{ mapPrepareDatatype()
/**
* Maps an mdb2 datatype to native prepare type
*
* @param string $type
* @return string
* @access public
*/
function mapPrepareDatatype($type)
{
$db = $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
if (!empty($db->options['datatype_map'][$type])) {
$type = $db->options['datatype_map'][$type];
if (!empty($db->options['datatype_map_callback'][$type])) {
$parameter = array('type' => $type);
return call_user_func_array($db->options['datatype_map_callback'][$type], array(&$db, __FUNCTION__, $parameter));
}
}
switch ($type) {
case 'integer':
return 'int';
case 'boolean':
return 'bool';
case 'decimal':
case 'float':
return 'numeric';
case 'clob':
return 'text';
case 'blob':
return 'bytea';
default:
break;
}
return $type;
}
// }}}
}
?>

@ -1,418 +0,0 @@
<?php
// vim: set et ts=4 sw=4 fdm=marker:
// +----------------------------------------------------------------------+
// | PHP versions 4 and 5 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1998-2007 Manuel Lemos, Tomas V.V.Cox, |
// | Stig. S. Bakken, Lukas Smith |
// | All rights reserved. |
// +----------------------------------------------------------------------+
// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB |
// | API as well as database abstraction for PHP applications. |
// | This LICENSE is in the BSD license style. |
// | |
// | Redistribution and use in source and binary forms, with or without |
// | modification, are permitted provided that the following conditions |
// | are met: |
// | |
// | Redistributions of source code must retain the above copyright |
// | notice, this list of conditions and the following disclaimer. |
// | |
// | Redistributions in binary form must reproduce the above copyright |
// | notice, this list of conditions and the following disclaimer in the |
// | documentation and/or other materials provided with the distribution. |
// | |
// | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken, |
// | Lukas Smith nor the names of his contributors may be used to endorse |
// | or promote products derived from this software without specific prior|
// | written permission. |
// | |
// | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
// | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
// | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
// | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE |
// | REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, |
// | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
// | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS|
// | OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED |
// | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
// | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY|
// | WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
// | POSSIBILITY OF SUCH DAMAGE. |
// +----------------------------------------------------------------------+
// | Author: Lukas Smith <smith@pooteeweet.org> |
// +----------------------------------------------------------------------+
//
// $Id: sqlite.php 295587 2010-02-28 17:16:38Z quipo $
//
require_once 'MDB2/Driver/Datatype/Common.php';
/**
* MDB2 SQLite driver
*
* @package MDB2
* @category Database
* @author Lukas Smith <smith@pooteeweet.org>
*/
class MDB2_Driver_Datatype_sqlite extends MDB2_Driver_Datatype_Common
{
// {{{ _getCollationFieldDeclaration()
/**
* Obtain DBMS specific SQL code portion needed to set the COLLATION
* of a field declaration to be used in statements like CREATE TABLE.
*
* @param string $collation name of the collation
*
* @return string DBMS specific SQL code portion needed to set the COLLATION
* of a field declaration.
*/
function _getCollationFieldDeclaration($collation)
{
return 'COLLATE '.$collation;
}
// }}}
// {{{ getTypeDeclaration()
/**
* Obtain DBMS specific SQL code portion needed to declare an text type
* field to be used in statements like CREATE TABLE.
*
* @param array $field associative array with the name of the properties
* of the field being declared as array indexes. Currently, the types
* of supported field properties are as follows:
*
* length
* Integer value that determines the maximum length of the text
* field. If this argument is missing the field should be
* declared to have the longest length allowed by the DBMS.
*
* default
* Text value to be used as default for this field.
*
* notnull
* Boolean flag that indicates whether this field is constrained
* to not be set to null.
* @return string DBMS specific SQL code portion that should be used to
* declare the specified field.
* @access public
*/
function getTypeDeclaration($field)
{
$db = $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
switch ($field['type']) {
case 'text':
$length = !empty($field['length'])
? $field['length'] : false;
$fixed = !empty($field['fixed']) ? $field['fixed'] : false;
return $fixed ? ($length ? 'CHAR('.$length.')' : 'CHAR('.$db->options['default_text_field_length'].')')
: ($length ? 'VARCHAR('.$length.')' : 'TEXT');
case 'clob':
if (!empty($field['length'])) {
$length = $field['length'];
if ($length <= 255) {
return 'TINYTEXT';
} elseif ($length <= 65532) {
return 'TEXT';
} elseif ($length <= 16777215) {
return 'MEDIUMTEXT';
}
}
return 'LONGTEXT';
case 'blob':
if (!empty($field['length'])) {
$length = $field['length'];
if ($length <= 255) {
return 'TINYBLOB';
} elseif ($length <= 65532) {
return 'BLOB';
} elseif ($length <= 16777215) {
return 'MEDIUMBLOB';
}
}
return 'LONGBLOB';
case 'integer':
if (!empty($field['length'])) {
$length = $field['length'];
if ($length <= 2) {
return 'SMALLINT';
} elseif ($length == 3 || $length == 4) {
return 'INTEGER';
} elseif ($length > 4) {
return 'BIGINT';
}
}
return 'INTEGER';
case 'boolean':
return 'BOOLEAN';
case 'date':
return 'DATE';
case 'time':
return 'TIME';
case 'timestamp':
return 'DATETIME';
case 'float':
return 'DOUBLE'.($db->options['fixed_float'] ? '('.
($db->options['fixed_float']+2).','.$db->options['fixed_float'].')' : '');
case 'decimal':
$length = !empty($field['length']) ? $field['length'] : 18;
$scale = !empty($field['scale']) ? $field['scale'] : $db->options['decimal_places'];
return 'DECIMAL('.$length.','.$scale.')';
}
return '';
}
// }}}
// {{{ _getIntegerDeclaration()
/**
* Obtain DBMS specific SQL code portion needed to declare an integer type
* field to be used in statements like CREATE TABLE.
*
* @param string $name name the field to be declared.
* @param string $field associative array with the name of the properties
* of the field being declared as array indexes.
* Currently, the types of supported field
* properties are as follows:
*
* unsigned
* Boolean flag that indicates whether the field
* should be declared as unsigned integer if
* possible.
*
* default
* Integer value to be used as default for this
* field.
*
* notnull
* Boolean flag that indicates whether this field is
* constrained to not be set to null.
* @return string DBMS specific SQL code portion that should be used to
* declare the specified field.
* @access protected
*/
function _getIntegerDeclaration($name, $field)
{
$db = $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
$default = $autoinc = '';
if (!empty($field['autoincrement'])) {
$autoinc = ' PRIMARY KEY';
} elseif (array_key_exists('default', $field)) {
if ($field['default'] === '') {
$field['default'] = empty($field['notnull']) ? null : 0;
}
$default = ' DEFAULT '.$this->quote($field['default'], 'integer');
}
$notnull = empty($field['notnull']) ? '' : ' NOT NULL';
$unsigned = empty($field['unsigned']) ? '' : ' UNSIGNED';
if (empty($default) && empty($notnull)) {
$default = ' DEFAULT NULL';
}
$name = $db->quoteIdentifier($name, true);
return $name.' '.$this->getTypeDeclaration($field).$unsigned.$default.$notnull.$autoinc;
}
// }}}
// {{{ matchPattern()
/**
* build a pattern matching string
*
* @access public
*
* @param array $pattern even keys are strings, odd are patterns (% and _)
* @param string $operator optional pattern operator (LIKE, ILIKE and maybe others in the future)
* @param string $field optional field name that is being matched against
* (might be required when emulating ILIKE)
*
* @return string SQL pattern
*/
function matchPattern($pattern, $operator = null, $field = null)
{
$db = $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
$match = '';
if (null !== $operator) {
$field = (null === $field) ? '' : $field.' ';
$operator = strtoupper($operator);
switch ($operator) {
// case insensitive
case 'ILIKE':
$match = $field.'LIKE ';
break;
case 'NOT ILIKE':
$match = $field.'NOT LIKE ';
break;
// case sensitive
case 'LIKE':
$match = $field.'LIKE ';
break;
case 'NOT LIKE':
$match = $field.'NOT LIKE ';
break;
default:
return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
'not a supported operator type:'. $operator, __FUNCTION__);
}
}
$match.= "'";
foreach ($pattern as $key => $value) {
if ($key % 2) {
$match.= $value;
} else {
$match.= $db->escapePattern($db->escape($value));
}
}
$match.= "'";
$match.= $this->patternEscapeString();
return $match;
}
// }}}
// {{{ _mapNativeDatatype()
/**
* Maps a native array description of a field to a MDB2 datatype and length
*
* @param array $field native field description
* @return array containing the various possible types, length, sign, fixed
* @access public
*/
function _mapNativeDatatype($field)
{
$db_type = strtolower($field['type']);
$length = !empty($field['length']) ? $field['length'] : null;
$unsigned = !empty($field['unsigned']) ? $field['unsigned'] : null;
$fixed = null;
$type = array();
switch ($db_type) {
case 'boolean':
$type[] = 'boolean';
break;
case 'tinyint':
$type[] = 'integer';
$type[] = 'boolean';
if (preg_match('/^(is|has)/', $field['name'])) {
$type = array_reverse($type);
}
$unsigned = preg_match('/ unsigned/i', $field['type']);
$length = 1;
break;
case 'smallint':
$type[] = 'integer';
$unsigned = preg_match('/ unsigned/i', $field['type']);
$length = 2;
break;
case 'mediumint':
$type[] = 'integer';
$unsigned = preg_match('/ unsigned/i', $field['type']);
$length = 3;
break;
case 'int':
case 'integer':
case 'serial':
$type[] = 'integer';
$unsigned = preg_match('/ unsigned/i', $field['type']);
$length = 4;
break;
case 'bigint':
case 'bigserial':
$type[] = 'integer';
$unsigned = preg_match('/ unsigned/i', $field['type']);
$length = 8;
break;
case 'clob':
$type[] = 'clob';
$fixed = false;
break;
case 'tinytext':
case 'mediumtext':
case 'longtext':
case 'text':
case 'varchar':
case 'varchar2':
$fixed = false;
case 'char':
$type[] = 'text';
if ($length == '1') {
$type[] = 'boolean';
if (preg_match('/^(is|has)/', $field['name'])) {
$type = array_reverse($type);
}
} elseif (strstr($db_type, 'text')) {
$type[] = 'clob';
$type = array_reverse($type);
}
if ($fixed !== false) {
$fixed = true;
}
break;
case 'date':
$type[] = 'date';
$length = null;
break;
case 'datetime':
case 'timestamp':
$type[] = 'timestamp';
$length = null;
break;
case 'time':
$type[] = 'time';
$length = null;
break;
case 'float':
case 'double':
case 'real':
$type[] = 'float';
break;
case 'decimal':
case 'numeric':
$type[] = 'decimal';
$length = $length.','.$field['decimal'];
break;
case 'tinyblob':
case 'mediumblob':
case 'longblob':
case 'blob':
$type[] = 'blob';
$length = null;
break;
case 'year':
$type[] = 'integer';
$type[] = 'date';
$length = null;
break;
default:
$db = $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
'unknown database attribute type: '.$db_type, __FUNCTION__);
}
if ((int)$length <= 0) {
$length = null;
}
return array($type, $length, $unsigned, $fixed);
}
// }}}
}
?>

@ -1,451 +0,0 @@
<?php
// vim: set et ts=4 sw=4 fdm=marker:
// +----------------------------------------------------------------------+
// | PHP versions 4 and 5 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1998-2007 Manuel Lemos, Tomas V.V.Cox, |
// | Stig. S. Bakken, Lukas Smith |
// | All rights reserved. |
// +----------------------------------------------------------------------+
// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB |
// | API as well as database abstraction for PHP applications. |
// | This LICENSE is in the BSD license style. |
// | |
// | Redistribution and use in source and binary forms, with or without |
// | modification, are permitted provided that the following conditions |
// | are met: |
// | |
// | Redistributions of source code must retain the above copyright |
// | notice, this list of conditions and the following disclaimer. |
// | |
// | Redistributions in binary form must reproduce the above copyright |
// | notice, this list of conditions and the following disclaimer in the |
// | documentation and/or other materials provided with the distribution. |
// | |
// | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken, |
// | Lukas Smith nor the names of his contributors may be used to endorse |
// | or promote products derived from this software without specific prior|
// | written permission. |
// | |
// | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
// | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
// | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
// | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE |
// | REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, |
// | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
// | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS|
// | OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED |
// | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
// | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY|
// | WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
// | POSSIBILITY OF SUCH DAMAGE. |
// +----------------------------------------------------------------------+
// | Authors: Lukas Smith <smith@pooteeweet.org> |
// | Daniel Convissor <danielc@php.net> |
// +----------------------------------------------------------------------+
require_once 'MDB2/Driver/Datatype/Common.php';
/**
* MDB2 MS SQL driver
*
* @package MDB2
* @category Database
*/
class MDB2_Driver_Datatype_sqlsrv extends MDB2_Driver_Datatype_Common
{
// {{{ _baseConvertResult()
/**
* general type conversion method
*
* @param mixed $value refernce to a value to be converted
* @param string $type specifies which type to convert to
* @param boolean $rtrim [optional] when TRUE [default], apply rtrim() to text
* @return object a MDB2 error on failure
* @access protected
*/
function _baseConvertResult($value, $type, $rtrim = true)
{
if (null === $value) {
return null;
}
switch ($type) {
case 'boolean':
return $value == '1';
case 'date':
if (strlen($value) > 10) {
$value = substr($value,0,10);
}
return $value;
case 'time':
if (strlen($value) > 8) {
$value = substr($value,11,8);
}
return $value;
}
return parent::_baseConvertResult($value, $type, $rtrim);
}
// }}}
// {{{ _getCollationFieldDeclaration()
/**
* Obtain DBMS specific SQL code portion needed to set the COLLATION
* of a field declaration to be used in statements like CREATE TABLE.
*
* @param string $collation name of the collation
*
* @return string DBMS specific SQL code portion needed to set the COLLATION
* of a field declaration.
*/
function _getCollationFieldDeclaration($collation)
{
return 'COLLATE '.$collation;
}
// }}}
// {{{ getTypeDeclaration()
/**
* Obtain DBMS specific SQL code portion needed to declare an text type
* field to be used in statements like CREATE TABLE.
*
* @param array $field associative array with the name of the properties
* of the field being declared as array indexes. Currently, the types
* of supported field properties are as follows:
*
* length
* Integer value that determines the maximum length of the text
* field. If this argument is missing the field should be
* declared to have the longest length allowed by the DBMS.
*
* default
* Text value to be used as default for this field.
*
* notnull
* Boolean flag that indicates whether this field is constrained
* to not be set to null.
* @return string DBMS specific SQL code portion that should be used to
* declare the specified field.
* @access public
*/
function getTypeDeclaration($field)
{
$db = $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
switch ($field['type']) {
case 'text':
$length = !empty($field['length'])
? $field['length'] : false;
$fixed = !empty($field['fixed']) ? $field['fixed'] : false;
return $fixed ? ($length ? 'CHAR('.$length.')' : 'CHAR('.$db->options['default_text_field_length'].')')
: ($length ? 'VARCHAR('.$length.')' : 'VARCHAR(MAX)');
case 'clob':
if (!empty($field['length'])) {
$length = $field['length'];
if ($length <= 8000) {
return 'VARCHAR('.$length.')';
}
}
return 'VARCHAR(MAX)';
case 'blob':
if (!empty($field['length'])) {
$length = $field['length'];
if ($length <= 8000) {
return "VARBINARY($length)";
}
}
return 'IMAGE';
case 'integer':
return 'INT';
case 'boolean':
return 'BIT';
case 'date':
return 'CHAR ('.strlen('YYYY-MM-DD').')';
case 'time':
return 'CHAR ('.strlen('HH:MM:SS').')';
case 'timestamp':
return 'CHAR ('.strlen('YYYY-MM-DD HH:MM:SS').')';
case 'float':
return 'FLOAT';
case 'decimal':
$length = !empty($field['length']) ? $field['length'] : 18;
$scale = !empty($field['scale']) ? $field['scale'] : $db->options['decimal_places'];
return 'DECIMAL('.$length.','.$scale.')';
}
return '';
}
// }}}
// {{{ _getIntegerDeclaration()
/**
* Obtain DBMS specific SQL code portion needed to declare an integer type
* field to be used in statements like CREATE TABLE.
*
* @param string $name name the field to be declared.
* @param string $field associative array with the name of the properties
* of the field being declared as array indexes.
* Currently, the types of supported field
* properties are as follows:
*
* unsigned
* Boolean flag that indicates whether the field
* should be declared as unsigned integer if
* possible.
*
* default
* Integer value to be used as default for this
* field.
*
* notnull
* Boolean flag that indicates whether this field is
* constrained to not be set to null.
* @return string DBMS specific SQL code portion that should be used to
* declare the specified field.
* @access protected
*/
function _getIntegerDeclaration($name, $field)
{
$db = $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
$notnull = empty($field['notnull']) ? ' NULL' : ' NOT NULL';
$default = $autoinc = '';
if (!empty($field['autoincrement'])) {
$autoinc = ' IDENTITY PRIMARY KEY';
} elseif (array_key_exists('default', $field)) {
if ($field['default'] === '') {
$field['default'] = 0;
}
if (null === $field['default']) {
$default = ' DEFAULT (NULL)';
} else {
$default = ' DEFAULT (' . $this->quote($field['default'], 'integer') . ')';
}
}
if (!empty($field['unsigned'])) {
$db->warnings[] = "unsigned integer field \"$name\" is being declared as signed integer";
}
$name = $db->quoteIdentifier($name, true);
return $name.' '.$this->getTypeDeclaration($field).$notnull.$default.$autoinc;
}
// }}}
// {{{ _getCLOBDeclaration()
/**
* Obtain DBMS specific SQL code portion needed to declare an character
* large object type field to be used in statements like CREATE TABLE.
*
* @param string $name name the field to be declared.
* @param array $field associative array with the name of the properties
* of the field being declared as array indexes. Currently, the types
* of supported field properties are as follows:
*
* length
* Integer value that determines the maximum length of the large
* object field. If this argument is missing the field should be
* declared to have the longest length allowed by the DBMS.
*
* notnull
* Boolean flag that indicates whether this field is constrained
* to not be set to null.
* @return string DBMS specific SQL code portion that should be used to
* declare the specified field.
* @access public
*/
function _getCLOBDeclaration($name, $field)
{
$db = $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
$notnull = empty($field['notnull']) ? ' NULL' : ' NOT NULL';
$name = $db->quoteIdentifier($name, true);
return $name.' '.$this->getTypeDeclaration($field).$notnull;
}
// }}}
// {{{ _getBLOBDeclaration()
/**
* Obtain DBMS specific SQL code portion needed to declare an binary large
* object type field to be used in statements like CREATE TABLE.
*
* @param string $name name the field to be declared.
* @param array $field associative array with the name of the properties
* of the field being declared as array indexes. Currently, the types
* of supported field properties are as follows:
*
* length
* Integer value that determines the maximum length of the large
* object field. If this argument is missing the field should be
* declared to have the longest length allowed by the DBMS.
*
* notnull
* Boolean flag that indicates whether this field is constrained
* to not be set to null.
* @return string DBMS specific SQL code portion that should be used to
* declare the specified field.
* @access protected
*/
function _getBLOBDeclaration($name, $field)
{
$db = $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
$notnull = empty($field['notnull']) ? ' NULL' : ' NOT NULL';
$name = $db->quoteIdentifier($name, true);
return $name.' '.$this->getTypeDeclaration($field).$notnull;
}
// }}}
// {{{ _quoteBLOB()
/**
* Convert a text value into a DBMS specific format that is suitable to
* compose query statements.
*
* @param string $value text string value that is intended to be converted.
* @param bool $quote determines if the value should be quoted and escaped
* @param bool $escape_wildcards if to escape escape wildcards
* @return string text string that represents the given argument value in
* a DBMS specific format.
* @access protected
*/
function _quoteBLOB($value, $quote, $escape_wildcards)
{
if (!$quote) {
return $value;
}
$value = '0x'.bin2hex($this->_readFile($value));
return $value;
}
// }}}
// {{{ _mapNativeDatatype()
/**
* Maps a native array description of a field to a MDB2 datatype and length
*
* @param array $field native field description
* @return array containing the various possible types, length, sign, fixed
* @access public
*/
function _mapNativeDatatype($field)
{
// todo: handle length of various int variations
$db_type = $field['type'];
$length = $field['length'];
$type = array();
// todo: unsigned handling seems to be missing
$unsigned = $fixed = null;
switch ($db_type) {
case 'bit':
case SQLSRV_SQLTYPE_BIT:
$type[0] = 'boolean';
break;
case 'tinyint':
case SQLSRV_SQLTYPE_TINYINT:
$type[0] = 'integer';
$length = 1;
break;
case 'smallint':
case SQLSRV_SQLTYPE_SMALLINT:
$type[0] = 'integer';
$length = 2;
break;
case 'int':
case SQLSRV_SQLTYPE_INT:
$type[0] = 'integer';
$length = 4;
break;
case 'bigint':
case SQLSRV_SQLTYPE_BIGINT:
$type[0] = 'integer';
$length = 8;
break;
case 'datetime':
case SQLSRV_SQLTYPE_DATETIME:
$type[0] = 'timestamp';
break;
case 'float':
case SQLSRV_SQLTYPE_FLOAT:
case 'real':
case SQLSRV_SQLTYPE_REAL:
$type[0] = 'float';
break;
case 'numeric':
case SQLSRV_SQLTYPE_NUMERIC:
case 'decimal':
case SQLSRV_SQLTYPE_DECIMAL:
case 'money':
case SQLSRV_SQLTYPE_MONEY:
$type[0] = 'decimal';
$length = $field['numeric_precision'].','.$field['numeric_scale'];
break;
case 'text':
case SQLSRV_SQLTYPE_TEXT:
case 'ntext':
case SQLSRV_SQLTYPE_NTEXT:
case 'varchar':
case SQLSRV_SQLTYPE_VARCHAR:
case 'nvarchar':
case SQLSRV_SQLTYPE_NVARCHAR:
$fixed = false;
case 'char':
case SQLSRV_SQLTYPE_CHAR:
case 'nchar':
case SQLSRV_SQLTYPE_NCHAR:
$type[0] = 'text';
if ($length == '1') {
$type[] = 'boolean';
if (preg_match('/^(is|has)/', $field['name'])) {
$type = array_reverse($type);
}
} elseif (strstr($db_type, 'text') || strstr($db_type, SQLSRV_SQLTYPE_TEXT)) {
$type[] = 'clob';
$type = array_reverse($type);
}
if ($fixed !== false) {
$fixed = true;
}
break;
case 'image':
case SQLSRV_SQLTYPE_IMAGE:
case 'varbinary':
case SQLSRV_SQLTYPE_VARBINARY:
$type[] = 'blob';
$length = null;
break;
default:
$db = $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
'unknown database attribute type: '.$db_type, __FUNCTION__);
}
if ((int)$length <= 0) {
$length = null;
}
return array($type, $length, $unsigned, $fixed);
}
// }}}
}
?>

@ -1,293 +0,0 @@
<?php
// +----------------------------------------------------------------------+
// | PHP versions 4 and 5 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1998-2006 Manuel Lemos, Tomas V.V.Cox, |
// | Stig. S. Bakken, Lukas Smith |
// | All rights reserved. |
// +----------------------------------------------------------------------+
// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB |
// | API as well as database abstraction for PHP applications. |
// | This LICENSE is in the BSD license style. |
// | |
// | Redistribution and use in source and binary forms, with or without |
// | modification, are permitted provided that the following conditions |
// | are met: |
// | |
// | Redistributions of source code must retain the above copyright |
// | notice, this list of conditions and the following disclaimer. |
// | |
// | Redistributions in binary form must reproduce the above copyright |
// | notice, this list of conditions and the following disclaimer in the |
// | documentation and/or other materials provided with the distribution. |
// | |
// | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken, |
// | Lukas Smith nor the names of his contributors may be used to endorse |
// | or promote products derived from this software without specific prior|
// | written permission. |
// | |
// | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
// | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
// | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
// | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE |
// | REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, |
// | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
// | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS|
// | OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED |
// | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
// | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY|
// | WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
// | POSSIBILITY OF SUCH DAMAGE. |
// +----------------------------------------------------------------------+
// | Author: Lukas Smith <smith@pooteeweet.org> |
// +----------------------------------------------------------------------+
//
// $Id: Common.php 292715 2009-12-28 14:06:34Z quipo $
//
/**
* @package MDB2
* @category Database
* @author Lukas Smith <smith@pooteeweet.org>
*/
/**
* Base class for the function modules that is extended by each MDB2 driver
*
* To load this module in the MDB2 object:
* $mdb->loadModule('Function');
*
* @package MDB2
* @category Database
* @author Lukas Smith <smith@pooteeweet.org>
*/
class MDB2_Driver_Function_Common extends MDB2_Module_Common
{
// {{{ executeStoredProc()
/**
* Execute a stored procedure and return any results
*
* @param string $name string that identifies the function to execute
* @param mixed $params array that contains the paramaters to pass the stored proc
* @param mixed $types array that contains the types of the columns in
* the result set
* @param mixed $result_class string which specifies which result class to use
* @param mixed $result_wrap_class string which specifies which class to wrap results in
*
* @return mixed a result handle or MDB2_OK on success, a MDB2 error on failure
* @access public
*/
function &executeStoredProc($name, $params = null, $types = null, $result_class = true, $result_wrap_class = false)
{
$db =& $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
$error =& $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
'method not implemented', __FUNCTION__);
return $error;
}
// }}}
// {{{ functionTable()
/**
* return string for internal table used when calling only a function
*
* @return string for internal table used when calling only a function
* @access public
*/
function functionTable()
{
return '';
}
// }}}
// {{{ now()
/**
* Return string to call a variable with the current timestamp inside an SQL statement
* There are three special variables for current date and time:
* - CURRENT_TIMESTAMP (date and time, TIMESTAMP type)
* - CURRENT_DATE (date, DATE type)
* - CURRENT_TIME (time, TIME type)
*
* @param string $type 'timestamp' | 'time' | 'date'
*
* @return string to call a variable with the current timestamp
* @access public
*/
function now($type = 'timestamp')
{
switch ($type) {
case 'time':
return 'CURRENT_TIME';
case 'date':
return 'CURRENT_DATE';
case 'timestamp':
default:
return 'CURRENT_TIMESTAMP';
}
}
// }}}
// {{{ unixtimestamp()
/**
* return string to call a function to get the unix timestamp from a iso timestamp
*
* @param string $expression
*
* @return string to call a variable with the timestamp
* @access public
*/
function unixtimestamp($expression)
{
$db =& $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
$error =& $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
'method not implemented', __FUNCTION__);
return $error;
}
// }}}
// {{{ substring()
/**
* return string to call a function to get a substring inside an SQL statement
*
* @return string to call a function to get a substring
* @access public
*/
function substring($value, $position = 1, $length = null)
{
if (null !== $length) {
return "SUBSTRING($value FROM $position FOR $length)";
}
return "SUBSTRING($value FROM $position)";
}
// }}}
// {{{ replace()
/**
* return string to call a function to get replace inside an SQL statement.
*
* @return string to call a function to get a replace
* @access public
*/
function replace($str, $from_str, $to_str)
{
return "REPLACE($str, $from_str , $to_str)";
}
// }}}
// {{{ concat()
/**
* Returns string to concatenate two or more string parameters
*
* @param string $value1
* @param string $value2
* @param string $values...
*
* @return string to concatenate two strings
* @access public
*/
function concat($value1, $value2)
{
$args = func_get_args();
return "(".implode(' || ', $args).")";
}
// }}}
// {{{ random()
/**
* return string to call a function to get random value inside an SQL statement
*
* @return return string to generate float between 0 and 1
* @access public
*/
function random()
{
return 'RAND()';
}
// }}}
// {{{ lower()
/**
* return string to call a function to lower the case of an expression
*
* @param string $expression
*
* @return return string to lower case of an expression
* @access public
*/
function lower($expression)
{
return "LOWER($expression)";
}
// }}}
// {{{ upper()
/**
* return string to call a function to upper the case of an expression
*
* @param string $expression
*
* @return return string to upper case of an expression
* @access public
*/
function upper($expression)
{
return "UPPER($expression)";
}
// }}}
// {{{ length()
/**
* return string to call a function to get the length of a string expression
*
* @param string $expression
*
* @return return string to get the string expression length
* @access public
*/
function length($expression)
{
return "LENGTH($expression)";
}
// }}}
// {{{ guid()
/**
* Returns global unique identifier
*
* @return string to get global unique identifier
* @access public
*/
function guid()
{
$db =& $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
$error =& $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
'method not implemented', __FUNCTION__);
return $error;
}
// }}}
}
?>

@ -1,193 +0,0 @@
<?php
// +----------------------------------------------------------------------+
// | PHP versions 4 and 5 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1998-2008 Manuel Lemos, Tomas V.V.Cox, |
// | Stig. S. Bakken, Lukas Smith |
// | All rights reserved. |
// +----------------------------------------------------------------------+
// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB |
// | API as well as database abstraction for PHP applications. |
// | This LICENSE is in the BSD license style. |
// | |
// | Redistribution and use in source and binary forms, with or without |
// | modification, are permitted provided that the following conditions |
// | are met: |
// | |
// | Redistributions of source code must retain the above copyright |
// | notice, this list of conditions and the following disclaimer. |
// | |
// | Redistributions in binary form must reproduce the above copyright |
// | notice, this list of conditions and the following disclaimer in the |
// | documentation and/or other materials provided with the distribution. |
// | |
// | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken, |
// | Lukas Smith nor the names of his contributors may be used to endorse |
// | or promote products derived from this software without specific prior|
// | written permission. |
// | |
// | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
// | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
// | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
// | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE |
// | REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, |
// | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
// | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS|
// | OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED |
// | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
// | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY|
// | WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
// | POSSIBILITY OF SUCH DAMAGE. |
// +----------------------------------------------------------------------+
// | Author: Frank M. Kromann <frank@kromann.info> |
// +----------------------------------------------------------------------+
//
// $Id: mssql.php 295587 2010-02-28 17:16:38Z quipo $
//
require_once 'MDB2/Driver/Function/Common.php';
// {{{ class MDB2_Driver_Function_mssql
/**
* MDB2 MSSQL driver for the function modules
*
* @package MDB2
* @category Database
* @author Lukas Smith <smith@pooteeweet.org>
*/
class MDB2_Driver_Function_mssql extends MDB2_Driver_Function_Common
{
// {{{ executeStoredProc()
/**
* Execute a stored procedure and return any results
*
* @param string $name string that identifies the function to execute
* @param mixed $params array that contains the paramaters to pass the stored proc
* @param mixed $types array that contains the types of the columns in
* the result set
* @param mixed $result_class string which specifies which result class to use
* @param mixed $result_wrap_class string which specifies which class to wrap results in
* @return mixed a result handle or MDB2_OK on success, a MDB2 error on failure
* @access public
*/
function executeStoredProc($name, $params = null, $types = null, $result_class = true, $result_wrap_class = false)
{
$db = $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
$query = 'EXECUTE '.$name;
$query .= $params ? ' '.implode(', ', $params) : '';
return $db->query($query, $types, $result_class, $result_wrap_class);
}
// }}}
// {{{ now()
/**
* Return string to call a variable with the current timestamp inside an SQL statement
* There are three special variables for current date and time:
* - CURRENT_TIMESTAMP (date and time, TIMESTAMP type)
* - CURRENT_DATE (date, DATE type)
* - CURRENT_TIME (time, TIME type)
*
* @return string to call a variable with the current timestamp
* @access public
*/
function now($type = 'timestamp')
{
switch ($type) {
case 'time':
case 'date':
case 'timestamp':
default:
return 'GETDATE()';
}
}
// }}}
// {{{ unixtimestamp()
/**
* return string to call a function to get the unix timestamp from a iso timestamp
*
* @param string $expression
*
* @return string to call a variable with the timestamp
* @access public
*/
function unixtimestamp($expression)
{
return 'DATEDIFF(second, \'19700101\', '. $expression.') + DATEDIFF(second, GETDATE(), GETUTCDATE())';
}
// }}}
// {{{ substring()
/**
* return string to call a function to get a substring inside an SQL statement
*
* @return string to call a function to get a substring
* @access public
*/
function substring($value, $position = 1, $length = null)
{
if (null !== $length) {
return "SUBSTRING($value, $position, $length)";
}
return "SUBSTRING($value, $position, LEN($value) - $position + 1)";
}
// }}}
// {{{ concat()
/**
* Returns string to concatenate two or more string parameters
*
* @param string $value1
* @param string $value2
* @param string $values...
* @return string to concatenate two strings
* @access public
**/
function concat($value1, $value2)
{
$args = func_get_args();
return "(".implode(' + ', $args).")";
}
// }}}
// {{{ length()
/**
* return string to call a function to get the length of a string expression
*
* @param string $expression
* @return return string to get the string expression length
* @access public
*/
function length($expression)
{
return "LEN($expression)";
}
// }}}
// {{{ guid()
/**
* Returns global unique identifier
*
* @return string to get global unique identifier
* @access public
*/
function guid()
{
return 'NEWID()';
}
// }}}
}
// }}}
?>

@ -1,136 +0,0 @@
<?php
// +----------------------------------------------------------------------+
// | PHP versions 4 and 5 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1998-2008 Manuel Lemos, Tomas V.V.Cox, |
// | Stig. S. Bakken, Lukas Smith |
// | All rights reserved. |
// +----------------------------------------------------------------------+
// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB |
// | API as well as database abstraction for PHP applications. |
// | This LICENSE is in the BSD license style. |
// | |
// | Redistribution and use in source and binary forms, with or without |
// | modification, are permitted provided that the following conditions |
// | are met: |
// | |
// | Redistributions of source code must retain the above copyright |
// | notice, this list of conditions and the following disclaimer. |
// | |
// | Redistributions in binary form must reproduce the above copyright |
// | notice, this list of conditions and the following disclaimer in the |
// | documentation and/or other materials provided with the distribution. |
// | |
// | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken, |
// | Lukas Smith nor the names of his contributors may be used to endorse |
// | or promote products derived from this software without specific prior|
// | written permission. |
// | |
// | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
// | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
// | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
// | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE |
// | REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, |
// | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
// | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS|
// | OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED |
// | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
// | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY|
// | WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
// | POSSIBILITY OF SUCH DAMAGE. |
// +----------------------------------------------------------------------+
// | Author: Lukas Smith <smith@pooteeweet.org> |
// +----------------------------------------------------------------------+
//
// $Id: mysql.php 295587 2010-02-28 17:16:38Z quipo $
//
require_once 'MDB2/Driver/Function/Common.php';
/**
* MDB2 MySQL driver for the function modules
*
* @package MDB2
* @category Database
* @author Lukas Smith <smith@pooteeweet.org>
*/
class MDB2_Driver_Function_mysql extends MDB2_Driver_Function_Common
{
// }}}
// {{{ executeStoredProc()
/**
* Execute a stored procedure and return any results
*
* @param string $name string that identifies the function to execute
* @param mixed $params array that contains the paramaters to pass the stored proc
* @param mixed $types array that contains the types of the columns in
* the result set
* @param mixed $result_class string which specifies which result class to use
* @param mixed $result_wrap_class string which specifies which class to wrap results in
* @return mixed a result handle or MDB2_OK on success, a MDB2 error on failure
* @access public
*/
function executeStoredProc($name, $params = null, $types = null, $result_class = true, $result_wrap_class = false)
{
$db = $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
$query = 'CALL '.$name;
$query .= $params ? '('.implode(', ', $params).')' : '()';
return $db->query($query, $types, $result_class, $result_wrap_class);
}
// }}}
// {{{ unixtimestamp()
/**
* return string to call a function to get the unix timestamp from a iso timestamp
*
* @param string $expression
*
* @return string to call a variable with the timestamp
* @access public
*/
function unixtimestamp($expression)
{
return 'UNIX_TIMESTAMP('. $expression.')';
}
// }}}
// {{{ concat()
/**
* Returns string to concatenate two or more string parameters
*
* @param string $value1
* @param string $value2
* @param string $values...
* @return string to concatenate two strings
* @access public
**/
function concat($value1, $value2)
{
$args = func_get_args();
return "CONCAT(".implode(', ', $args).")";
}
// }}}
// {{{ guid()
/**
* Returns global unique identifier
*
* @return string to get global unique identifier
* @access public
*/
function guid()
{
return 'UUID()';
}
// }}}
}
?>

@ -1,144 +0,0 @@
<?php
// +----------------------------------------------------------------------+
// | PHP versions 4 and 5 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1998-2008 Manuel Lemos, Tomas V.V.Cox, |
// | Stig. S. Bakken, Lukas Smith |
// | All rights reserved. |
// +----------------------------------------------------------------------+
// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB |
// | API as well as database abstraction for PHP applications. |
// | This LICENSE is in the BSD license style. |
// | |
// | Redistribution and use in source and binary forms, with or without |
// | modification, are permitted provided that the following conditions |
// | are met: |
// | |
// | Redistributions of source code must retain the above copyright |
// | notice, this list of conditions and the following disclaimer. |
// | |
// | Redistributions in binary form must reproduce the above copyright |
// | notice, this list of conditions and the following disclaimer in the |
// | documentation and/or other materials provided with the distribution. |
// | |
// | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken, |
// | Lukas Smith nor the names of his contributors may be used to endorse |
// | or promote products derived from this software without specific prior|
// | written permission. |
// | |
// | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
// | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
// | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
// | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE |
// | REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, |
// | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
// | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS|
// | OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED |
// | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
// | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY|
// | WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
// | POSSIBILITY OF SUCH DAMAGE. |
// +----------------------------------------------------------------------+
// | Author: Lukas Smith <smith@pooteeweet.org> |
// +----------------------------------------------------------------------+
//
// $Id: mysqli.php 295587 2010-02-28 17:16:38Z quipo $
//
require_once 'MDB2/Driver/Function/Common.php';
/**
* MDB2 MySQLi driver for the function modules
*
* @package MDB2
* @category Database
* @author Lukas Smith <smith@pooteeweet.org>
*/
class MDB2_Driver_Function_mysqli extends MDB2_Driver_Function_Common
{
// }}}
// {{{ executeStoredProc()
/**
* Execute a stored procedure and return any results
*
* @param string $name string that identifies the function to execute
* @param mixed $params array that contains the paramaters to pass the stored proc
* @param mixed $types array that contains the types of the columns in
* the result set
* @param mixed $result_class string which specifies which result class to use
* @param mixed $result_wrap_class string which specifies which class to wrap results in
* @return mixed a result handle or MDB2_OK on success, a MDB2 error on failure
* @access public
*/
function executeStoredProc($name, $params = null, $types = null, $result_class = true, $result_wrap_class = false)
{
$db = $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
$multi_query = $db->getOption('multi_query');
if (!$multi_query) {
$db->setOption('multi_query', true);
}
$query = 'CALL '.$name;
$query .= $params ? '('.implode(', ', $params).')' : '()';
$result = $db->query($query, $types, $result_class, $result_wrap_class);
if (!$multi_query) {
$db->setOption('multi_query', false);
}
return $result;
}
// }}}
// {{{ unixtimestamp()
/**
* return string to call a function to get the unix timestamp from a iso timestamp
*
* @param string $expression
*
* @return string to call a variable with the timestamp
* @access public
*/
function unixtimestamp($expression)
{
return 'UNIX_TIMESTAMP('. $expression.')';
}
// }}}
// {{{ concat()
/**
* Returns string to concatenate two or more string parameters
*
* @param string $value1
* @param string $value2
* @param string $values...
* @return string to concatenate two strings
* @access public
**/
function concat($value1, $value2)
{
$args = func_get_args();
return "CONCAT(".implode(', ', $args).")";
}
// }}}
// {{{ guid()
/**
* Returns global unique identifier
*
* @return string to get global unique identifier
* @access public
*/
function guid()
{
return 'UUID()';
}
// }}}
}
?>

@ -1,115 +0,0 @@
<?php
// +----------------------------------------------------------------------+
// | PHP versions 4 and 5 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1998-2008 Manuel Lemos, Tomas V.V.Cox, |
// | Stig. S. Bakken, Lukas Smith |
// | All rights reserved. |
// +----------------------------------------------------------------------+
// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB |
// | API as well as database abstraction for PHP applications. |
// | This LICENSE is in the BSD license style. |
// | |
// | Redistribution and use in source and binary forms, with or without |
// | modification, are permitted provided that the following conditions |
// | are met: |
// | |
// | Redistributions of source code must retain the above copyright |
// | notice, this list of conditions and the following disclaimer. |
// | |
// | Redistributions in binary form must reproduce the above copyright |
// | notice, this list of conditions and the following disclaimer in the |
// | documentation and/or other materials provided with the distribution. |
// | |
// | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken, |
// | Lukas Smith nor the names of his contributors may be used to endorse |
// | or promote products derived from this software without specific prior|
// | written permission. |
// | |
// | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
// | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
// | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
// | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE |
// | REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, |
// | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
// | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS|
// | OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED |
// | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
// | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY|
// | WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
// | POSSIBILITY OF SUCH DAMAGE. |
// +----------------------------------------------------------------------+
// | Author: Paul Cooper <pgc@ucecom.com> |
// +----------------------------------------------------------------------+
//
// $Id: pgsql.php 295587 2010-02-28 17:16:38Z quipo $
require_once 'MDB2/Driver/Function/Common.php';
/**
* MDB2 MySQL driver for the function modules
*
* @package MDB2
* @category Database
* @author Lukas Smith <smith@pooteeweet.org>
*/
class MDB2_Driver_Function_pgsql extends MDB2_Driver_Function_Common
{
// {{{ executeStoredProc()
/**
* Execute a stored procedure and return any results
*
* @param string $name string that identifies the function to execute
* @param mixed $params array that contains the paramaters to pass the stored proc
* @param mixed $types array that contains the types of the columns in
* the result set
* @param mixed $result_class string which specifies which result class to use
* @param mixed $result_wrap_class string which specifies which class to wrap results in
* @return mixed a result handle or MDB2_OK on success, a MDB2 error on failure
* @access public
*/
function executeStoredProc($name, $params = null, $types = null, $result_class = true, $result_wrap_class = false)
{
$db = $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
$query = 'SELECT * FROM '.$name;
$query .= $params ? '('.implode(', ', $params).')' : '()';
return $db->query($query, $types, $result_class, $result_wrap_class);
}
// }}}
// {{{ unixtimestamp()
/**
* return string to call a function to get the unix timestamp from a iso timestamp
*
* @param string $expression
*
* @return string to call a variable with the timestamp
* @access public
*/
function unixtimestamp($expression)
{
return 'EXTRACT(EPOCH FROM DATE_TRUNC(\'seconds\', CAST ((' . $expression . ') AS TIMESTAMP)))';
}
// }}}
// {{{ random()
/**
* return string to call a function to get random value inside an SQL statement
*
* @return return string to generate float between 0 and 1
* @access public
*/
function random()
{
return 'RANDOM()';
}
// }}}
}
?>

@ -1,162 +0,0 @@
<?php
// +----------------------------------------------------------------------+
// | PHP versions 4 and 5 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1998-2008 Manuel Lemos, Tomas V.V.Cox, |
// | Stig. S. Bakken, Lukas Smith |
// | All rights reserved. |
// +----------------------------------------------------------------------+
// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB |
// | API as well as database abstraction for PHP applications. |
// | This LICENSE is in the BSD license style. |
// | |
// | Redistribution and use in source and binary forms, with or without |
// | modification, are permitted provided that the following conditions |
// | are met: |
// | |
// | Redistributions of source code must retain the above copyright |
// | notice, this list of conditions and the following disclaimer. |
// | |
// | Redistributions in binary form must reproduce the above copyright |
// | notice, this list of conditions and the following disclaimer in the |
// | documentation and/or other materials provided with the distribution. |
// | |
// | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken, |
// | Lukas Smith nor the names of his contributors may be used to endorse |
// | or promote products derived from this software without specific prior|
// | written permission. |
// | |
// | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
// | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
// | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
// | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE |
// | REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, |
// | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
// | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS|
// | OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED |
// | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
// | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY|
// | WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
// | POSSIBILITY OF SUCH DAMAGE. |
// +----------------------------------------------------------------------+
// | Author: Lukas Smith <smith@pooteeweet.org> |
// +----------------------------------------------------------------------+
//
// $Id: sqlite.php 295587 2010-02-28 17:16:38Z quipo $
//
require_once 'MDB2/Driver/Function/Common.php';
/**
* MDB2 SQLite driver for the function modules
*
* @package MDB2
* @category Database
* @author Lukas Smith <smith@pooteeweet.org>
*/
class MDB2_Driver_Function_sqlite extends MDB2_Driver_Function_Common
{
// {{{ constructor
/**
* Constructor
*/
function __construct($db_index)
{
parent::__construct($db_index);
// create all sorts of UDFs
}
// {{{ now()
/**
* Return string to call a variable with the current timestamp inside an SQL statement
* There are three special variables for current date and time.
*
* @return string to call a variable with the current timestamp
* @access public
*/
function now($type = 'timestamp')
{
switch ($type) {
case 'time':
return 'time(\'now\')';
case 'date':
return 'date(\'now\')';
case 'timestamp':
default:
return 'datetime(\'now\')';
}
}
// }}}
// {{{ unixtimestamp()
/**
* return string to call a function to get the unix timestamp from a iso timestamp
*
* @param string $expression
*
* @return string to call a variable with the timestamp
* @access public
*/
function unixtimestamp($expression)
{
return 'strftime("%s",'. $expression.', "utc")';
}
// }}}
// {{{ substring()
/**
* return string to call a function to get a substring inside an SQL statement
*
* @return string to call a function to get a substring
* @access public
*/
function substring($value, $position = 1, $length = null)
{
if (null !== $length) {
return "substr($value, $position, $length)";
}
return "substr($value, $position, length($value))";
}
// }}}
// {{{ random()
/**
* return string to call a function to get random value inside an SQL statement
*
* @return return string to generate float between 0 and 1
* @access public
*/
function random()
{
return '((RANDOM()+2147483648)/4294967296)';
}
// }}}
// {{{ replace()
/**
* return string to call a function to get a replacement inside an SQL statement.
*
* @return string to call a function to get a replace
* @access public
*/
function replace($str, $from_str, $to_str)
{
$db = $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
$error = $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
'method not implemented', __FUNCTION__);
return $error;
}
// }}}
}
?>

@ -1,189 +0,0 @@
<?php
// +----------------------------------------------------------------------+
// | PHP versions 4 and 5 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1998-2008 Manuel Lemos, Tomas V.V.Cox, |
// | Stig. S. Bakken, Lukas Smith |
// | All rights reserved. |
// +----------------------------------------------------------------------+
// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB |
// | API as well as database abstraction for PHP applications. |
// | This LICENSE is in the BSD license style. |
// | |
// | Redistribution and use in source and binary forms, with or without |
// | modification, are permitted provided that the following conditions |
// | are met: |
// | |
// | Redistributions of source code must retain the above copyright |
// | notice, this list of conditions and the following disclaimer. |
// | |
// | Redistributions in binary form must reproduce the above copyright |
// | notice, this list of conditions and the following disclaimer in the |
// | documentation and/or other materials provided with the distribution. |
// | |
// | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken, |
// | Lukas Smith nor the names of his contributors may be used to endorse |
// | or promote products derived from this software without specific prior|
// | written permission. |
// | |
// | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
// | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
// | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
// | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE |
// | REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, |
// | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
// | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS|
// | OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED |
// | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
// | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY|
// | WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
// | POSSIBILITY OF SUCH DAMAGE. |
// +----------------------------------------------------------------------+
// | Author: Frank M. Kromann <frank@kromann.info> |
// +----------------------------------------------------------------------+
require_once 'MDB2/Driver/Function/Common.php';
// {{{ class MDB2_Driver_Function_sqlsrv
/**
* MDB2 MSSQL driver for the function modules
*
* @package MDB2
* @category Database
*/
class MDB2_Driver_Function_sqlsrv extends MDB2_Driver_Function_Common
{
// {{{ executeStoredProc()
/**
* Execute a stored procedure and return any results
*
* @param string $name string that identifies the function to execute
* @param mixed $params array that contains the paramaters to pass the stored proc
* @param mixed $types array that contains the types of the columns in
* the result set
* @param mixed $result_class string which specifies which result class to use
* @param mixed $result_wrap_class string which specifies which class to wrap results in
* @return mixed a result handle or MDB2_OK on success, a MDB2 error on failure
* @access public
*/
function executeStoredProc($name, $params = null, $types = null, $result_class = true, $result_wrap_class = false)
{
$db = $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
$query = 'EXECUTE '.$name;
$query .= $params ? ' '.implode(', ', $params) : '';
return $db->query($query, $types, $result_class, $result_wrap_class);
}
// }}}
// {{{ now()
/**
* Return string to call a variable with the current timestamp inside an SQL statement
* There are three special variables for current date and time:
* - CURRENT_TIMESTAMP (date and time, TIMESTAMP type)
* - CURRENT_DATE (date, DATE type)
* - CURRENT_TIME (time, TIME type)
*
* @return string to call a variable with the current timestamp
* @access public
*/
function now($type = 'timestamp')
{
switch ($type) {
case 'time':
case 'date':
case 'timestamp':
default:
return 'GETDATE()';
}
}
// }}}
// {{{ unixtimestamp()
/**
* return string to call a function to get the unix timestamp from a iso timestamp
*
* @param string $expression
*
* @return string to call a variable with the timestamp
* @access public
*/
function unixtimestamp($expression)
{
return 'DATEDIFF(second, \'19700101\', '. $expression.') + DATEDIFF(second, GETDATE(), GETUTCDATE())';
}
// }}}
// {{{ substring()
/**
* return string to call a function to get a substring inside an SQL statement
*
* @return string to call a function to get a substring
* @access public
*/
function substring($value, $position = 1, $length = null)
{
if (null !== $length) {
return "SUBSTRING($value, $position, $length)";
}
return "SUBSTRING($value, $position, LEN($value) - $position + 1)";
}
// }}}
// {{{ concat()
/**
* Returns string to concatenate two or more string parameters
*
* @param string $value1
* @param string $value2
* @param string $values...
* @return string to concatenate two strings
* @access public
**/
function concat($value1, $value2)
{
$args = func_get_args();
return "(".implode(' + ', $args).")";
}
// }}}
// {{{ length()
/**
* return string to call a function to get the length of a string expression
*
* @param string $expression
* @return return string to get the string expression length
* @access public
*/
function length($expression)
{
return "LEN($expression)";
}
// }}}
// {{{ guid()
/**
* Returns global unique identifier
*
* @return string to get global unique identifier
* @access public
*/
function guid()
{
return 'NEWID()';
}
// }}}
}
// }}}
?>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -1,948 +0,0 @@
<?php
// +----------------------------------------------------------------------+
// | PHP versions 4 and 5 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1998-2008 Manuel Lemos, Tomas V.V.Cox, |
// | Stig. S. Bakken, Lukas Smith |
// | All rights reserved. |
// +----------------------------------------------------------------------+
// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB |
// | API as well as database abstraction for PHP applications. |
// | This LICENSE is in the BSD license style. |
// | |
// | Redistribution and use in source and binary forms, with or without |
// | modification, are permitted provided that the following conditions |
// | are met: |
// | |
// | Redistributions of source code must retain the above copyright |
// | notice, this list of conditions and the following disclaimer. |
// | |
// | Redistributions in binary form must reproduce the above copyright |
// | notice, this list of conditions and the following disclaimer in the |
// | documentation and/or other materials provided with the distribution. |
// | |
// | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken, |
// | Lukas Smith nor the names of his contributors may be used to endorse |
// | or promote products derived from this software without specific prior|
// | written permission. |
// | |
// | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
// | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
// | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
// | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE |
// | REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, |
// | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
// | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS|
// | OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED |
// | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
// | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY|
// | WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
// | POSSIBILITY OF SUCH DAMAGE. |
// +----------------------------------------------------------------------+
// | Author: Paul Cooper <pgc@ucecom.com> |
// +----------------------------------------------------------------------+
//
// $Id: pgsql.php 295587 2010-02-28 17:16:38Z quipo $
require_once 'MDB2/Driver/Manager/Common.php';
/**
* MDB2 MySQL driver for the management modules
*
* @package MDB2
* @category Database
* @author Paul Cooper <pgc@ucecom.com>
*/
class MDB2_Driver_Manager_pgsql extends MDB2_Driver_Manager_Common
{
// {{{ createDatabase()
/**
* create a new database
*
* @param string $name name of the database that should be created
* @param array $options array with charset info
*
* @return mixed MDB2_OK on success, a MDB2 error on failure
* @access public
*/
function createDatabase($name, $options = array())
{
$db = $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
$name = $db->quoteIdentifier($name, true);
$query = 'CREATE DATABASE ' . $name;
if (!empty($options['charset'])) {
$query .= ' WITH ENCODING ' . $db->quote($options['charset'], 'text');
}
return $db->standaloneQuery($query, null, true);
}
// }}}
// {{{ alterDatabase()
/**
* alter an existing database
*
* @param string $name name of the database that is intended to be changed
* @param array $options array with name, owner info
*
* @return mixed MDB2_OK on success, a MDB2 error on failure
* @access public
*/
function alterDatabase($name, $options = array())
{
$db = $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
$query = 'ALTER DATABASE '. $db->quoteIdentifier($name, true);
if (!empty($options['name'])) {
$query .= ' RENAME TO ' . $options['name'];
}
if (!empty($options['owner'])) {
$query .= ' OWNER TO ' . $options['owner'];
}
return $db->standaloneQuery($query, null, true);
}
// }}}
// {{{ dropDatabase()
/**
* drop an existing database
*
* @param string $name name of the database that should be dropped
* @return mixed MDB2_OK on success, a MDB2 error on failure
* @access public
*/
function dropDatabase($name)
{
$db = $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
$name = $db->quoteIdentifier($name, true);
$query = "DROP DATABASE $name";
return $db->standaloneQuery($query, null, true);
}
// }}}
// {{{ _getAdvancedFKOptions()
/**
* Return the FOREIGN KEY query section dealing with non-standard options
* as MATCH, INITIALLY DEFERRED, ON UPDATE, ...
*
* @param array $definition
* @return string
* @access protected
*/
function _getAdvancedFKOptions($definition)
{
$query = '';
if (!empty($definition['match'])) {
$query .= ' MATCH '.$definition['match'];
}
if (!empty($definition['onupdate'])) {
$query .= ' ON UPDATE '.$definition['onupdate'];
}
if (!empty($definition['ondelete'])) {
$query .= ' ON DELETE '.$definition['ondelete'];
}
if (!empty($definition['deferrable'])) {
$query .= ' DEFERRABLE';
} else {
$query .= ' NOT DEFERRABLE';
}
if (!empty($definition['initiallydeferred'])) {
$query .= ' INITIALLY DEFERRED';
} else {
$query .= ' INITIALLY IMMEDIATE';
}
return $query;
}
// }}}
// {{{ truncateTable()
/**
* Truncate an existing table (if the TRUNCATE TABLE syntax is not supported,
* it falls back to a DELETE FROM TABLE query)
*
* @param string $name name of the table that should be truncated
* @return mixed MDB2_OK on success, a MDB2 error on failure
* @access public
*/
function truncateTable($name)
{
$db = $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
$name = $db->quoteIdentifier($name, true);
return $db->exec("TRUNCATE TABLE $name");
}
// }}}
// {{{ vacuum()
/**
* Optimize (vacuum) all the tables in the db (or only the specified table)
* and optionally run ANALYZE.
*
* @param string $table table name (all the tables if empty)
* @param array $options an array with driver-specific options:
* - timeout [int] (in seconds) [mssql-only]
* - analyze [boolean] [pgsql and mysql]
* - full [boolean] [pgsql-only]
* - freeze [boolean] [pgsql-only]
*
* @return mixed MDB2_OK success, a MDB2 error on failure
* @access public
*/
function vacuum($table = null, $options = array())
{
$db = $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
$query = 'VACUUM';
if (!empty($options['full'])) {
$query .= ' FULL';
}
if (!empty($options['freeze'])) {
$query .= ' FREEZE';
}
if (!empty($options['analyze'])) {
$query .= ' ANALYZE';
}
if (!empty($table)) {
$query .= ' '.$db->quoteIdentifier($table, true);
}
return $db->exec($query);
}
// }}}
// {{{ alterTable()
/**
* alter an existing table
*
* @param string $name name of the table that is intended to be changed.
* @param array $changes associative array that contains the details of each type
* of change that is intended to be performed. The types of
* changes that are currently supported are defined as follows:
*
* name
*
* New name for the table.
*
* add
*
* Associative array with the names of fields to be added as
* indexes of the array. The value of each entry of the array
* should be set to another associative array with the properties
* of the fields to be added. The properties of the fields should
* be the same as defined by the MDB2 parser.
*
*
* remove
*
* Associative array with the names of fields to be removed as indexes
* of the array. Currently the values assigned to each entry are ignored.
* An empty array should be used for future compatibility.
*
* rename
*
* Associative array with the names of fields to be renamed as indexes
* of the array. The value of each entry of the array should be set to
* another associative array with the entry named name with the new
* field name and the entry named Declaration that is expected to contain
* the portion of the field declaration already in DBMS specific SQL code
* as it is used in the CREATE TABLE statement.
*
* change
*
* Associative array with the names of the fields to be changed as indexes
* of the array. Keep in mind that if it is intended to change either the
* name of a field and any other properties, the change array entries
* should have the new names of the fields as array indexes.
*
* The value of each entry of the array should be set to another associative
* array with the properties of the fields to that are meant to be changed as
* array entries. These entries should be assigned to the new values of the
* respective properties. The properties of the fields should be the same
* as defined by the MDB2 parser.
*
* Example
* array(
* 'name' => 'userlist',
* 'add' => array(
* 'quota' => array(
* 'type' => 'integer',
* 'unsigned' => 1
* )
* ),
* 'remove' => array(
* 'file_limit' => array(),
* 'time_limit' => array()
* ),
* 'change' => array(
* 'name' => array(
* 'length' => '20',
* 'definition' => array(
* 'type' => 'text',
* 'length' => 20,
* ),
* )
* ),
* 'rename' => array(
* 'sex' => array(
* 'name' => 'gender',
* 'definition' => array(
* 'type' => 'text',
* 'length' => 1,
* 'default' => 'M',
* ),
* )
* )
* )
*
* @param boolean $check indicates whether the function should just check if the DBMS driver
* can perform the requested table alterations if the value is true or
* actually perform them otherwise.
* @access public
*
* @return mixed MDB2_OK on success, a MDB2 error on failure
*/
function alterTable($name, $changes, $check)
{
$db = $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
foreach ($changes as $change_name => $change) {
switch ($change_name) {
case 'add':
case 'remove':
case 'change':
case 'name':
case 'rename':
break;
default:
return $db->raiseError(MDB2_ERROR_CANNOT_ALTER, null, null,
'change type "'.$change_name.'\" not yet supported', __FUNCTION__);
}
}
if ($check) {
return MDB2_OK;
}
$name = $db->quoteIdentifier($name, true);
if (!empty($changes['remove']) && is_array($changes['remove'])) {
foreach ($changes['remove'] as $field_name => $field) {
$field_name = $db->quoteIdentifier($field_name, true);
$query = 'DROP ' . $field_name;
$result = $db->exec("ALTER TABLE $name $query");
if (PEAR::isError($result)) {
return $result;
}
}
}
if (!empty($changes['rename']) && is_array($changes['rename'])) {
foreach ($changes['rename'] as $field_name => $field) {
$field_name = $db->quoteIdentifier($field_name, true);
$result = $db->exec("ALTER TABLE $name RENAME COLUMN $field_name TO ".$db->quoteIdentifier($field['name'], true));
if (PEAR::isError($result)) {
return $result;
}
}
}
if (!empty($changes['add']) && is_array($changes['add'])) {
foreach ($changes['add'] as $field_name => $field) {
$query = 'ADD ' . $db->getDeclaration($field['type'], $field_name, $field);
$result = $db->exec("ALTER TABLE $name $query");
if (PEAR::isError($result)) {
return $result;
}
}
}
if (!empty($changes['change']) && is_array($changes['change'])) {
foreach ($changes['change'] as $field_name => $field) {
$field_name = $db->quoteIdentifier($field_name, true);
if (!empty($field['definition']['type'])) {
$server_info = $db->getServerVersion();
if (PEAR::isError($server_info)) {
return $server_info;
}
if (is_array($server_info) && $server_info['major'] < 8) {
return $db->raiseError(MDB2_ERROR_CANNOT_ALTER, null, null,
'changing column type for "'.$change_name.'\" requires PostgreSQL 8.0 or above', __FUNCTION__);
}
$db->loadModule('Datatype', null, true);
$type = $db->datatype->getTypeDeclaration($field['definition']);
$query = "ALTER $field_name TYPE $type USING CAST($field_name AS $type)";
$result = $db->exec("ALTER TABLE $name $query");
if (PEAR::isError($result)) {
return $result;
}
}
if (array_key_exists('default', $field['definition'])) {
$query = "ALTER $field_name SET DEFAULT ".$db->quote($field['definition']['default'], $field['definition']['type']);
$result = $db->exec("ALTER TABLE $name $query");
if (PEAR::isError($result)) {
return $result;
}
}
if (array_key_exists('notnull', $field['definition'])) {
$query = "ALTER $field_name ".($field['definition']['notnull'] ? 'SET' : 'DROP').' NOT NULL';
$result = $db->exec("ALTER TABLE $name $query");
if (PEAR::isError($result)) {
return $result;
}
}
}
}
if (!empty($changes['name'])) {
$change_name = $db->quoteIdentifier($changes['name'], true);
$result = $db->exec("ALTER TABLE $name RENAME TO ".$change_name);
if (PEAR::isError($result)) {
return $result;
}
}
return MDB2_OK;
}
// }}}
// {{{ listDatabases()
/**
* list all databases
*
* @return mixed array of database names on success, a MDB2 error on failure
* @access public
*/
function listDatabases()
{
$db = $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
$query = 'SELECT datname FROM pg_database';
$result2 = $db->standaloneQuery($query, array('text'), false);
if (!MDB2::isResultCommon($result2)) {
return $result2;
}
$result = $result2->fetchCol();
$result2->free();
if (PEAR::isError($result)) {
return $result;
}
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
$result = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result);
}
return $result;
}
// }}}
// {{{ listUsers()
/**
* list all users
*
* @return mixed array of user names on success, a MDB2 error on failure
* @access public
*/
function listUsers()
{
$db = $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
$query = 'SELECT usename FROM pg_user';
$result2 = $db->standaloneQuery($query, array('text'), false);
if (!MDB2::isResultCommon($result2)) {
return $result2;
}
$result = $result2->fetchCol();
$result2->free();
return $result;
}
// }}}
// {{{ listViews()
/**
* list all views in the current database
*
* @return mixed array of view names on success, a MDB2 error on failure
* @access public
*/
function listViews()
{
$db = $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
$query = "SELECT viewname
FROM pg_views
WHERE schemaname NOT IN ('pg_catalog', 'information_schema')
AND viewname !~ '^pg_'";
$result = $db->queryCol($query);
if (PEAR::isError($result)) {
return $result;
}
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
$result = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result);
}
return $result;
}
// }}}
// {{{ listTableViews()
/**
* list the views in the database that reference a given table
*
* @param string table for which all referenced views should be found
* @return mixed array of view names on success, a MDB2 error on failure
* @access public
*/
function listTableViews($table)
{
$db = $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
$query = 'SELECT viewname FROM pg_views NATURAL JOIN pg_tables';
$query.= ' WHERE tablename ='.$db->quote($table, 'text');
$result = $db->queryCol($query);
if (PEAR::isError($result)) {
return $result;
}
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
$result = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result);
}
return $result;
}
// }}}
// {{{ listFunctions()
/**
* list all functions in the current database
*
* @return mixed array of function names on success, a MDB2 error on failure
* @access public
*/
function listFunctions()
{
$db = $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
$query = "
SELECT
proname
FROM
pg_proc pr,
pg_type tp
WHERE
tp.oid = pr.prorettype
AND pr.proisagg = FALSE
AND tp.typname <> 'trigger'
AND pr.pronamespace IN
(SELECT oid FROM pg_namespace WHERE nspname NOT LIKE 'pg_%' AND nspname != 'information_schema')";
$result = $db->queryCol($query);
if (PEAR::isError($result)) {
return $result;
}
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
$result = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result);
}
return $result;
}
// }}}
// {{{ listTableTriggers()
/**
* list all triggers in the database that reference a given table
*
* @param string table for which all referenced triggers should be found
* @return mixed array of trigger names on success, a MDB2 error on failure
* @access public
*/
function listTableTriggers($table = null)
{
$db = $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
$query = 'SELECT trg.tgname AS trigger_name
FROM pg_trigger trg,
pg_class tbl
WHERE trg.tgrelid = tbl.oid';
if (null !== $table) {
$table = $db->quote(strtoupper($table), 'text');
$query .= " AND UPPER(tbl.relname) = $table";
}
$result = $db->queryCol($query);
if (PEAR::isError($result)) {
return $result;
}
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
$result = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result);
}
return $result;
}
// }}}
// {{{ listTables()
/**
* list all tables in the current database
*
* @return mixed array of table names on success, a MDB2 error on failure
* @access public
*/
function listTables()
{
$db = $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
// gratuitously stolen from PEAR DB _getSpecialQuery in pgsql.php
$query = 'SELECT c.relname AS "Name"'
. ' FROM pg_class c, pg_user u'
. ' WHERE c.relowner = u.usesysid'
. " AND c.relkind = 'r'"
. ' AND NOT EXISTS'
. ' (SELECT 1 FROM pg_views'
. ' WHERE viewname = c.relname)'
. " AND c.relname !~ '^(pg_|sql_)'"
. ' UNION'
. ' SELECT c.relname AS "Name"'
. ' FROM pg_class c'
. " WHERE c.relkind = 'r'"
. ' AND NOT EXISTS'
. ' (SELECT 1 FROM pg_views'
. ' WHERE viewname = c.relname)'
. ' AND NOT EXISTS'
. ' (SELECT 1 FROM pg_user'
. ' WHERE usesysid = c.relowner)'
. " AND c.relname !~ '^pg_'";
$result = $db->queryCol($query);
if (PEAR::isError($result)) {
return $result;
}
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
$result = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result);
}
return $result;
}
// }}}
// {{{ listTableFields()
/**
* list all fields in a table in the current database
*
* @param string $table name of table that should be used in method
* @return mixed array of field names on success, a MDB2 error on failure
* @access public
*/
function listTableFields($table)
{
$db = $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
list($schema, $table) = $this->splitTableSchema($table);
$table = $db->quoteIdentifier($table, true);
if (!empty($schema)) {
$table = $db->quoteIdentifier($schema, true) . '.' .$table;
}
$db->setLimit(1);
$result2 = $db->query("SELECT * FROM $table");
if (PEAR::isError($result2)) {
return $result2;
}
$result = $result2->getColumnNames();
$result2->free();
if (PEAR::isError($result)) {
return $result;
}
return array_flip($result);
}
// }}}
// {{{ listTableIndexes()
/**
* list all indexes in a table
*
* @param string $table name of table that should be used in method
* @return mixed array of index names on success, a MDB2 error on failure
* @access public
*/
function listTableIndexes($table)
{
$db = $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
list($schema, $table) = $this->splitTableSchema($table);
$table = $db->quote($table, 'text');
$subquery = "SELECT indexrelid
FROM pg_index
LEFT JOIN pg_class ON pg_class.oid = pg_index.indrelid
LEFT JOIN pg_namespace ON pg_class.relnamespace = pg_namespace.oid
WHERE pg_class.relname = $table
AND indisunique != 't'
AND indisprimary != 't'";
if (!empty($schema)) {
$subquery .= ' AND pg_namespace.nspname = '.$db->quote($schema, 'text');
}
$query = "SELECT relname FROM pg_class WHERE oid IN ($subquery)";
$indexes = $db->queryCol($query, 'text');
if (PEAR::isError($indexes)) {
return $indexes;
}
$result = array();
foreach ($indexes as $index) {
$index = $this->_fixIndexName($index);
if (!empty($index)) {
$result[$index] = true;
}
}
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
$result = array_change_key_case($result, $db->options['field_case']);
}
return array_keys($result);
}
// }}}
// {{{ dropConstraint()
/**
* drop existing constraint
*
* @param string $table name of table that should be used in method
* @param string $name name of the constraint to be dropped
* @param string $primary hint if the constraint is primary
*
* @return mixed MDB2_OK on success, a MDB2 error on failure
* @access public
*/
function dropConstraint($table, $name, $primary = false)
{
$db = $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
// is it an UNIQUE index?
$query = 'SELECT relname
FROM pg_class
WHERE oid IN (
SELECT indexrelid
FROM pg_index, pg_class
WHERE pg_class.relname = '.$db->quote($table, 'text').'
AND pg_class.oid = pg_index.indrelid
AND indisunique = \'t\')
EXCEPT
SELECT conname
FROM pg_constraint, pg_class
WHERE pg_constraint.conrelid = pg_class.oid
AND relname = '. $db->quote($table, 'text');
$unique = $db->queryCol($query, 'text');
if (PEAR::isError($unique) || empty($unique)) {
// not an UNIQUE index, maybe a CONSTRAINT
return parent::dropConstraint($table, $name, $primary);
}
if (in_array($name, $unique)) {
return $db->exec('DROP INDEX '.$db->quoteIdentifier($name, true));
}
$idxname = $db->getIndexName($name);
if (in_array($idxname, $unique)) {
return $db->exec('DROP INDEX '.$db->quoteIdentifier($idxname, true));
}
return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
$name . ' is not an existing constraint for table ' . $table, __FUNCTION__);
}
// }}}
// {{{ listTableConstraints()
/**
* list all constraints in a table
*
* @param string $table name of table that should be used in method
* @return mixed array of constraint names on success, a MDB2 error on failure
* @access public
*/
function listTableConstraints($table)
{
$db = $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
list($schema, $table) = $this->splitTableSchema($table);
$table = $db->quote($table, 'text');
$query = 'SELECT conname
FROM pg_constraint
LEFT JOIN pg_class ON pg_constraint.conrelid = pg_class.oid
LEFT JOIN pg_namespace ON pg_class.relnamespace = pg_namespace.oid
WHERE relname = ' .$table;
if (!empty($schema)) {
$query .= ' AND pg_namespace.nspname = ' . $db->quote($schema, 'text');
}
$query .= '
UNION DISTINCT
SELECT relname
FROM pg_class
WHERE oid IN (
SELECT indexrelid
FROM pg_index
LEFT JOIN pg_class ON pg_class.oid = pg_index.indrelid
LEFT JOIN pg_namespace ON pg_class.relnamespace = pg_namespace.oid
WHERE pg_class.relname = '.$table.'
AND indisunique = \'t\'';
if (!empty($schema)) {
$query .= ' AND pg_namespace.nspname = ' . $db->quote($schema, 'text');
}
$query .= ')';
$constraints = $db->queryCol($query);
if (PEAR::isError($constraints)) {
return $constraints;
}
$result = array();
foreach ($constraints as $constraint) {
$constraint = $this->_fixIndexName($constraint);
if (!empty($constraint)) {
$result[$constraint] = true;
}
}
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE
&& $db->options['field_case'] == CASE_LOWER
) {
$result = array_change_key_case($result, $db->options['field_case']);
}
return array_keys($result);
}
// }}}
// {{{ createSequence()
/**
* create sequence
*
* @param string $seq_name name of the sequence to be created
* @param string $start start value of the sequence; default is 1
* @return mixed MDB2_OK on success, a MDB2 error on failure
* @access public
*/
function createSequence($seq_name, $start = 1)
{
$db = $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
$sequence_name = $db->quoteIdentifier($db->getSequenceName($seq_name), true);
return $db->exec("CREATE SEQUENCE $sequence_name INCREMENT 1".
($start < 1 ? " MINVALUE $start" : '')." START $start");
}
// }}}
// {{{ dropSequence()
/**
* drop existing sequence
*
* @param string $seq_name name of the sequence to be dropped
* @return mixed MDB2_OK on success, a MDB2 error on failure
* @access public
*/
function dropSequence($seq_name)
{
$db = $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
$sequence_name = $db->quoteIdentifier($db->getSequenceName($seq_name), true);
return $db->exec("DROP SEQUENCE $sequence_name");
}
// }}}
// {{{ listSequences()
/**
* list all sequences in the current database
*
* @return mixed array of sequence names on success, a MDB2 error on failure
* @access public
*/
function listSequences()
{
$db = $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
$query = "SELECT relname FROM pg_class WHERE relkind = 'S' AND relnamespace IN";
$query.= "(SELECT oid FROM pg_namespace WHERE nspname NOT LIKE 'pg_%' AND nspname != 'information_schema')";
$table_names = $db->queryCol($query);
if (PEAR::isError($table_names)) {
return $table_names;
}
$result = array();
foreach ($table_names as $table_name) {
$result[] = $this->_fixSequenceName($table_name);
}
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
$result = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result);
}
return $result;
}
}
?>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -1,61 +0,0 @@
<?php
// +----------------------------------------------------------------------+
// | PHP versions 4 and 5 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1998-2006 Manuel Lemos, Tomas V.V.Cox, |
// | Stig. S. Bakken, Lukas Smith |
// | All rights reserved. |
// +----------------------------------------------------------------------+
// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB |
// | API as well as database abstraction for PHP applications. |
// | This LICENSE is in the BSD license style. |
// | |
// | Redistribution and use in source and binary forms, with or without |
// | modification, are permitted provided that the following conditions |
// | are met: |
// | |
// | Redistributions of source code must retain the above copyright |
// | notice, this list of conditions and the following disclaimer. |
// | |
// | Redistributions in binary form must reproduce the above copyright |
// | notice, this list of conditions and the following disclaimer in the |
// | documentation and/or other materials provided with the distribution. |
// | |
// | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken, |
// | Lukas Smith nor the names of his contributors may be used to endorse |
// | or promote products derived from this software without specific prior|
// | written permission. |
// | |
// | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
// | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
// | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
// | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE |
// | REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, |
// | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
// | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS|
// | OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED |
// | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
// | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY|
// | WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
// | POSSIBILITY OF SUCH DAMAGE. |
// +----------------------------------------------------------------------+
// | Author: Lukas Smith <smith@pooteeweet.org> |
// +----------------------------------------------------------------------+
//
// $Id: Common.php 242348 2007-09-09 13:47:36Z quipo $
//
/**
* Base class for the natuve modules that is extended by each MDB2 driver
*
* To load this module in the MDB2 object:
* $mdb->loadModule('Native');
*
* @package MDB2
* @category Database
* @author Lukas Smith <smith@pooteeweet.org>
*/
class MDB2_Driver_Native_Common extends MDB2_Module_Common
{
}
?>

@ -1,60 +0,0 @@
<?php
// +----------------------------------------------------------------------+
// | PHP versions 4 and 5 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1998-2006 Manuel Lemos, Tomas V.V.Cox, |
// | Stig. S. Bakken, Lukas Smith, Frank M. Kromann |
// | All rights reserved. |
// +----------------------------------------------------------------------+
// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB |
// | API as well as database abstraction for PHP applications. |
// | This LICENSE is in the BSD license style. |
// | |
// | Redistribution and use in source and binary forms, with or without |
// | modification, are permitted provided that the following conditions |
// | are met: |
// | |
// | Redistributions of source code must retain the above copyright |
// | notice, this list of conditions and the following disclaimer. |
// | |
// | Redistributions in binary form must reproduce the above copyright |
// | notice, this list of conditions and the following disclaimer in the |
// | documentation and/or other materials provided with the distribution. |
// | |
// | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken, |
// | Lukas Smith nor the names of his contributors may be used to endorse |
// | or promote products derived from this software without specific prior|
// | written permission. |
// | |
// | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
// | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
// | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
// | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE |
// | REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, |
// | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
// | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS|
// | OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED |
// | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
// | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY|
// | WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
// | POSSIBILITY OF SUCH DAMAGE. |
// +----------------------------------------------------------------------+
// | Author: Lukas Smith <smith@pooteeweet.org> |
// +----------------------------------------------------------------------+
//
// $Id: mssql.php 215004 2006-06-18 21:59:05Z lsmith $
//
require_once 'MDB2/Driver/Native/Common.php';
/**
* MDB2 MSSQL driver for the native module
*
* @package MDB2
* @category Database
* @author Lukas Smith <smith@dybnet.de>
*/
class MDB2_Driver_Native_mssql extends MDB2_Driver_Native_Common
{
}
?>

@ -1,60 +0,0 @@
<?php
// +----------------------------------------------------------------------+
// | PHP versions 4 and 5 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1998-2006 Manuel Lemos, Tomas V.V.Cox, |
// | Stig. S. Bakken, Lukas Smith |
// | All rights reserved. |
// +----------------------------------------------------------------------+
// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB |
// | API as well as database abstraction for PHP applications. |
// | This LICENSE is in the BSD license style. |
// | |
// | Redistribution and use in source and binary forms, with or without |
// | modification, are permitted provided that the following conditions |
// | are met: |
// | |
// | Redistributions of source code must retain the above copyright |
// | notice, this list of conditions and the following disclaimer. |
// | |
// | Redistributions in binary form must reproduce the above copyright |
// | notice, this list of conditions and the following disclaimer in the |
// | documentation and/or other materials provided with the distribution. |
// | |
// | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken, |
// | Lukas Smith nor the names of his contributors may be used to endorse |
// | or promote products derived from this software without specific prior|
// | written permission. |
// | |
// | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
// | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
// | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
// | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE |
// | REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, |
// | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
// | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS|
// | OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED |
// | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
// | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY|
// | WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
// | POSSIBILITY OF SUCH DAMAGE. |
// +----------------------------------------------------------------------+
// | Author: Lukas Smith <smith@pooteeweet.org> |
// +----------------------------------------------------------------------+
//
// $Id: mysql.php 215004 2006-06-18 21:59:05Z lsmith $
//
require_once 'MDB2/Driver/Native/Common.php';
/**
* MDB2 MySQL driver for the native module
*
* @package MDB2
* @category Database
* @author Lukas Smith <smith@pooteeweet.org>
*/
class MDB2_Driver_Native_mysql extends MDB2_Driver_Native_Common
{
}
?>

@ -1,60 +0,0 @@
<?php
// +----------------------------------------------------------------------+
// | PHP versions 4 and 5 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1998-2006 Manuel Lemos, Tomas V.V.Cox, |
// | Stig. S. Bakken, Lukas Smith |
// | All rights reserved. |
// +----------------------------------------------------------------------+
// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB |
// | API as well as database abstraction for PHP applications. |
// | This LICENSE is in the BSD license style. |
// | |
// | Redistribution and use in source and binary forms, with or without |
// | modification, are permitted provided that the following conditions |
// | are met: |
// | |
// | Redistributions of source code must retain the above copyright |
// | notice, this list of conditions and the following disclaimer. |
// | |
// | Redistributions in binary form must reproduce the above copyright |
// | notice, this list of conditions and the following disclaimer in the |
// | documentation and/or other materials provided with the distribution. |
// | |
// | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken, |
// | Lukas Smith nor the names of his contributors may be used to endorse |
// | or promote products derived from this software without specific prior|
// | written permission. |
// | |
// | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
// | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
// | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
// | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE |
// | REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, |
// | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
// | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS|
// | OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED |
// | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
// | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY|
// | WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
// | POSSIBILITY OF SUCH DAMAGE. |
// +----------------------------------------------------------------------+
// | Author: Lukas Smith <smith@pooteeweet.org> |
// +----------------------------------------------------------------------+
//
// $Id: mysqli.php 215004 2006-06-18 21:59:05Z lsmith $
//
require_once 'MDB2/Driver/Native/Common.php';
/**
* MDB2 MySQLi driver for the native module
*
* @package MDB2
* @category Database
* @author Lukas Smith <smith@pooteeweet.org>
*/
class MDB2_Driver_Native_mysqli extends MDB2_Driver_Native_Common
{
}
?>

@ -1,88 +0,0 @@
<?php
// +----------------------------------------------------------------------+
// | PHP versions 4 and 5 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1998-2006 Manuel Lemos, Tomas V.V.Cox, |
// | Stig. S. Bakken, Lukas Smith |
// | All rights reserved. |
// +----------------------------------------------------------------------+
// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB |
// | API as well as database abstraction for PHP applications. |
// | This LICENSE is in the BSD license style. |
// | |
// | Redistribution and use in source and binary forms, with or without |
// | modification, are permitted provided that the following conditions |
// | are met: |
// | |
// | Redistributions of source code must retain the above copyright |
// | notice, this list of conditions and the following disclaimer. |
// | |
// | Redistributions in binary form must reproduce the above copyright |
// | notice, this list of conditions and the following disclaimer in the |
// | documentation and/or other materials provided with the distribution. |
// | |
// | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken, |
// | Lukas Smith nor the names of his contributors may be used to endorse |
// | or promote products derived from this software without specific prior|
// | written permission. |
// | |
// | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
// | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
// | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
// | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE |
// | REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, |
// | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
// | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS|
// | OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED |
// | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
// | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY|
// | WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
// | POSSIBILITY OF SUCH DAMAGE. |
// +----------------------------------------------------------------------+
// | Author: Paul Cooper <pgc@ucecom.com> |
// +----------------------------------------------------------------------+
//
// $Id: pgsql.php 295587 2010-02-28 17:16:38Z quipo $
require_once 'MDB2/Driver/Native/Common.php';
/**
* MDB2 PostGreSQL driver for the native module
*
* @package MDB2
* @category Database
* @author Paul Cooper <pgc@ucecom.com>
*/
class MDB2_Driver_Native_pgsql extends MDB2_Driver_Native_Common
{
// }}}
// {{{ deleteOID()
/**
* delete an OID
*
* @param integer $OID
* @return mixed MDB2_OK on success or MDB2 Error Object on failure
* @access public
*/
function deleteOID($OID)
{
$db = $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
$connection = $db->getConnection();
if (PEAR::isError($connection)) {
return $connection;
}
if (!@pg_lo_unlink($connection, $OID)) {
return $db->raiseError(null, null, null,
'Unable to unlink OID: '.$OID, __FUNCTION__);
}
return MDB2_OK;
}
}
?>

@ -1,60 +0,0 @@
<?php
// +----------------------------------------------------------------------+
// | PHP versions 4 and 5 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1998-2006 Manuel Lemos, Tomas V.V.Cox, |
// | Stig. S. Bakken, Lukas Smith |
// | All rights reserved. |
// +----------------------------------------------------------------------+
// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB |
// | API as well as database abstraction for PHP applications. |
// | This LICENSE is in the BSD license style. |
// | |
// | Redistribution and use in source and binary forms, with or without |
// | modification, are permitted provided that the following conditions |
// | are met: |
// | |
// | Redistributions of source code must retain the above copyright |
// | notice, this list of conditions and the following disclaimer. |
// | |
// | Redistributions in binary form must reproduce the above copyright |
// | notice, this list of conditions and the following disclaimer in the |
// | documentation and/or other materials provided with the distribution. |
// | |
// | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken, |
// | Lukas Smith nor the names of his contributors may be used to endorse |
// | or promote products derived from this software without specific prior|
// | written permission. |
// | |
// | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
// | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
// | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
// | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE |
// | REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, |
// | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
// | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS|
// | OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED |
// | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
// | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY|
// | WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
// | POSSIBILITY OF SUCH DAMAGE. |
// +----------------------------------------------------------------------+
// | Author: Lukas Smith <smith@pooteeweet.org> |
// +----------------------------------------------------------------------+
//
// $Id: sqlite.php 215004 2006-06-18 21:59:05Z lsmith $
//
require_once 'MDB2/Driver/Native/Common.php';
/**
* MDB2 SQLite driver for the native module
*
* @package MDB2
* @category Database
* @author Lukas Smith <smith@pooteeweet.org>
*/
class MDB2_Driver_Native_sqlite extends MDB2_Driver_Native_Common
{
}
?>

@ -1,57 +0,0 @@
<?php
// +----------------------------------------------------------------------+
// | PHP versions 4 and 5 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1998-2006 Manuel Lemos, Tomas V.V.Cox, |
// | Stig. S. Bakken, Lukas Smith, Frank M. Kromann |
// | All rights reserved. |
// +----------------------------------------------------------------------+
// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB |
// | API as well as database abstraction for PHP applications. |
// | This LICENSE is in the BSD license style. |
// | |
// | Redistribution and use in source and binary forms, with or without |
// | modification, are permitted provided that the following conditions |
// | are met: |
// | |
// | Redistributions of source code must retain the above copyright |
// | notice, this list of conditions and the following disclaimer. |
// | |
// | Redistributions in binary form must reproduce the above copyright |
// | notice, this list of conditions and the following disclaimer in the |
// | documentation and/or other materials provided with the distribution. |
// | |
// | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken, |
// | Lukas Smith nor the names of his contributors may be used to endorse |
// | or promote products derived from this software without specific prior|
// | written permission. |
// | |
// | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
// | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
// | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
// | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE |
// | REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, |
// | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
// | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS|
// | OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED |
// | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
// | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY|
// | WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
// | POSSIBILITY OF SUCH DAMAGE. |
// +----------------------------------------------------------------------+
// | Author: Lukas Smith <smith@pooteeweet.org> |
// +----------------------------------------------------------------------+
require_once 'MDB2/Driver/Native/Common.php';
/**
* MDB2 MSSQL driver for the native module
*
* @package MDB2
* @category Database
* @author Lukas Smith <smith@dybnet.de>
*/
class MDB2_Driver_Native_sqlsrv extends MDB2_Driver_Native_Common
{
}
?>

@ -1,517 +0,0 @@
<?php
// +----------------------------------------------------------------------+
// | PHP versions 4 and 5 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1998-2007 Manuel Lemos, Tomas V.V.Cox, |
// | Stig. S. Bakken, Lukas Smith |
// | All rights reserved. |
// +----------------------------------------------------------------------+
// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB |
// | API as well as database abstraction for PHP applications. |
// | This LICENSE is in the BSD license style. |
// | |
// | Redistribution and use in source and binary forms, with or without |
// | modification, are permitted provided that the following conditions |
// | are met: |
// | |
// | Redistributions of source code must retain the above copyright |
// | notice, this list of conditions and the following disclaimer. |
// | |
// | Redistributions in binary form must reproduce the above copyright |
// | notice, this list of conditions and the following disclaimer in the |
// | documentation and/or other materials provided with the distribution. |
// | |
// | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken, |
// | Lukas Smith nor the names of his contributors may be used to endorse |
// | or promote products derived from this software without specific prior|
// | written permission. |
// | |
// | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
// | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
// | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
// | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE |
// | REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, |
// | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
// | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS|
// | OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED |
// | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
// | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY|
// | WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
// | POSSIBILITY OF SUCH DAMAGE. |
// +----------------------------------------------------------------------+
// | Author: Lukas Smith <smith@pooteeweet.org> |
// +----------------------------------------------------------------------+
//
// $Id: Common.php 273526 2009-01-14 15:01:21Z quipo $
//
/**
* @package MDB2
* @category Database
*/
/**
* These are constants for the tableInfo-function
* they are bitwised or'ed. so if there are more constants to be defined
* in the future, adjust MDB2_TABLEINFO_FULL accordingly
*/
define('MDB2_TABLEINFO_ORDER', 1);
define('MDB2_TABLEINFO_ORDERTABLE', 2);
define('MDB2_TABLEINFO_FULL', 3);
/**
* Base class for the schema reverse engineering module that is extended by each MDB2 driver
*
* To load this module in the MDB2 object:
* $mdb->loadModule('Reverse');
*
* @package MDB2
* @category Database
* @author Lukas Smith <smith@pooteeweet.org>
*/
class MDB2_Driver_Reverse_Common extends MDB2_Module_Common
{
// {{{ splitTableSchema()
/**
* Split the "[owner|schema].table" notation into an array
*
* @param string $table [schema and] table name
*
* @return array array(schema, table)
* @access private
*/
function splitTableSchema($table)
{
$ret = array();
if (strpos($table, '.') !== false) {
return explode('.', $table);
}
return array(null, $table);
}
// }}}
// {{{ getTableFieldDefinition()
/**
* Get the structure of a field into an array
*
* @param string $table name of table that should be used in method
* @param string $field name of field that should be used in method
* @return mixed data array on success, a MDB2 error on failure.
* The returned array contains an array for each field definition,
* with all or some of these indices, depending on the field data type:
* [notnull] [nativetype] [length] [fixed] [default] [type] [mdb2type]
* @access public
*/
function getTableFieldDefinition($table, $field)
{
$db =& $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
'method not implemented', __FUNCTION__);
}
// }}}
// {{{ getTableIndexDefinition()
/**
* Get the structure of an index into an array
*
* @param string $table name of table that should be used in method
* @param string $index name of index that should be used in method
* @return mixed data array on success, a MDB2 error on failure
* The returned array has this structure:
* </pre>
* array (
* [fields] => array (
* [field1name] => array() // one entry per each field covered
* [field2name] => array() // by the index
* [field3name] => array(
* [sorting] => ascending
* )
* )
* );
* </pre>
* @access public
*/
function getTableIndexDefinition($table, $index)
{
$db =& $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
'method not implemented', __FUNCTION__);
}
// }}}
// {{{ getTableConstraintDefinition()
/**
* Get the structure of an constraints into an array
*
* @param string $table name of table that should be used in method
* @param string $index name of index that should be used in method
* @return mixed data array on success, a MDB2 error on failure
* The returned array has this structure:
* <pre>
* array (
* [primary] => 0
* [unique] => 0
* [foreign] => 1
* [check] => 0
* [fields] => array (
* [field1name] => array() // one entry per each field covered
* [field2name] => array() // by the index
* [field3name] => array(
* [sorting] => ascending
* [position] => 3
* )
* )
* [references] => array(
* [table] => name
* [fields] => array(
* [field1name] => array( //one entry per each referenced field
* [position] => 1
* )
* )
* )
* [deferrable] => 0
* [initiallydeferred] => 0
* [onupdate] => CASCADE|RESTRICT|SET NULL|SET DEFAULT|NO ACTION
* [ondelete] => CASCADE|RESTRICT|SET NULL|SET DEFAULT|NO ACTION
* [match] => SIMPLE|PARTIAL|FULL
* );
* </pre>
* @access public
*/
function getTableConstraintDefinition($table, $index)
{
$db =& $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
'method not implemented', __FUNCTION__);
}
// }}}
// {{{ getSequenceDefinition()
/**
* Get the structure of a sequence into an array
*
* @param string $sequence name of sequence that should be used in method
* @return mixed data array on success, a MDB2 error on failure
* The returned array has this structure:
* <pre>
* array (
* [start] => n
* );
* </pre>
* @access public
*/
function getSequenceDefinition($sequence)
{
$db =& $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
$start = $db->currId($sequence);
if (PEAR::isError($start)) {
return $start;
}
if ($db->supports('current_id')) {
$start++;
} else {
$db->warnings[] = 'database does not support getting current
sequence value, the sequence value was incremented';
}
$definition = array();
if ($start != 1) {
$definition = array('start' => $start);
}
return $definition;
}
// }}}
// {{{ getTriggerDefinition()
/**
* Get the structure of a trigger into an array
*
* EXPERIMENTAL
*
* WARNING: this function is experimental and may change the returned value
* at any time until labelled as non-experimental
*
* @param string $trigger name of trigger that should be used in method
* @return mixed data array on success, a MDB2 error on failure
* The returned array has this structure:
* <pre>
* array (
* [trigger_name] => 'trigger name',
* [table_name] => 'table name',
* [trigger_body] => 'trigger body definition',
* [trigger_type] => 'BEFORE' | 'AFTER',
* [trigger_event] => 'INSERT' | 'UPDATE' | 'DELETE'
* //or comma separated list of multiple events, when supported
* [trigger_enabled] => true|false
* [trigger_comment] => 'trigger comment',
* );
* </pre>
* The oci8 driver also returns a [when_clause] index.
* @access public
*/
function getTriggerDefinition($trigger)
{
$db =& $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
'method not implemented', __FUNCTION__);
}
// }}}
// {{{ tableInfo()
/**
* Returns information about a table or a result set
*
* The format of the resulting array depends on which <var>$mode</var>
* you select. The sample output below is based on this query:
* <pre>
* SELECT tblFoo.fldID, tblFoo.fldPhone, tblBar.fldId
* FROM tblFoo
* JOIN tblBar ON tblFoo.fldId = tblBar.fldId
* </pre>
*
* <ul>
* <li>
*
* <kbd>null</kbd> (default)
* <pre>
* [0] => Array (
* [table] => tblFoo
* [name] => fldId
* [type] => int
* [len] => 11
* [flags] => primary_key not_null
* )
* [1] => Array (
* [table] => tblFoo
* [name] => fldPhone
* [type] => string
* [len] => 20
* [flags] =>
* )
* [2] => Array (
* [table] => tblBar
* [name] => fldId
* [type] => int
* [len] => 11
* [flags] => primary_key not_null
* )
* </pre>
*
* </li><li>
*
* <kbd>MDB2_TABLEINFO_ORDER</kbd>
*
* <p>In addition to the information found in the default output,
* a notation of the number of columns is provided by the
* <samp>num_fields</samp> element while the <samp>order</samp>
* element provides an array with the column names as the keys and
* their location index number (corresponding to the keys in the
* the default output) as the values.</p>
*
* <p>If a result set has identical field names, the last one is
* used.</p>
*
* <pre>
* [num_fields] => 3
* [order] => Array (
* [fldId] => 2
* [fldTrans] => 1
* )
* </pre>
*
* </li><li>
*
* <kbd>MDB2_TABLEINFO_ORDERTABLE</kbd>
*
* <p>Similar to <kbd>MDB2_TABLEINFO_ORDER</kbd> but adds more
* dimensions to the array in which the table names are keys and
* the field names are sub-keys. This is helpful for queries that
* join tables which have identical field names.</p>
*
* <pre>
* [num_fields] => 3
* [ordertable] => Array (
* [tblFoo] => Array (
* [fldId] => 0
* [fldPhone] => 1
* )
* [tblBar] => Array (
* [fldId] => 2
* )
* )
* </pre>
*
* </li>
* </ul>
*
* The <samp>flags</samp> element contains a space separated list
* of extra information about the field. This data is inconsistent
* between DBMS's due to the way each DBMS works.
* + <samp>primary_key</samp>
* + <samp>unique_key</samp>
* + <samp>multiple_key</samp>
* + <samp>not_null</samp>
*
* Most DBMS's only provide the <samp>table</samp> and <samp>flags</samp>
* elements if <var>$result</var> is a table name. The following DBMS's
* provide full information from queries:
* + fbsql
* + mysql
*
* If the 'portability' option has <samp>MDB2_PORTABILITY_FIX_CASE</samp>
* turned on, the names of tables and fields will be lower or upper cased.
*
* @param object|string $result MDB2_result object from a query or a
* string containing the name of a table.
* While this also accepts a query result
* resource identifier, this behavior is
* deprecated.
* @param int $mode either unused or one of the tableInfo modes:
* <kbd>MDB2_TABLEINFO_ORDERTABLE</kbd>,
* <kbd>MDB2_TABLEINFO_ORDER</kbd> or
* <kbd>MDB2_TABLEINFO_FULL</kbd> (which does both).
* These are bitwise, so the first two can be
* combined using <kbd>|</kbd>.
*
* @return array an associative array with the information requested.
* A MDB2_Error object on failure.
*
* @see MDB2_Driver_Common::setOption()
*/
function tableInfo($result, $mode = null)
{
$db =& $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
if (!is_string($result)) {
return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
'method not implemented', __FUNCTION__);
}
$db->loadModule('Manager', null, true);
$fields = $db->manager->listTableFields($result);
if (PEAR::isError($fields)) {
return $fields;
}
$flags = array();
$idxname_format = $db->getOption('idxname_format');
$db->setOption('idxname_format', '%s');
$indexes = $db->manager->listTableIndexes($result);
if (PEAR::isError($indexes)) {
$db->setOption('idxname_format', $idxname_format);
return $indexes;
}
foreach ($indexes as $index) {
$definition = $this->getTableIndexDefinition($result, $index);
if (PEAR::isError($definition)) {
$db->setOption('idxname_format', $idxname_format);
return $definition;
}
if (count($definition['fields']) > 1) {
foreach ($definition['fields'] as $field => $sort) {
$flags[$field] = 'multiple_key';
}
}
}
$constraints = $db->manager->listTableConstraints($result);
if (PEAR::isError($constraints)) {
return $constraints;
}
foreach ($constraints as $constraint) {
$definition = $this->getTableConstraintDefinition($result, $constraint);
if (PEAR::isError($definition)) {
$db->setOption('idxname_format', $idxname_format);
return $definition;
}
$flag = !empty($definition['primary'])
? 'primary_key' : (!empty($definition['unique'])
? 'unique_key' : false);
if ($flag) {
foreach ($definition['fields'] as $field => $sort) {
if (empty($flags[$field]) || $flags[$field] != 'primary_key') {
$flags[$field] = $flag;
}
}
}
}
$res = array();
if ($mode) {
$res['num_fields'] = count($fields);
}
foreach ($fields as $i => $field) {
$definition = $this->getTableFieldDefinition($result, $field);
if (PEAR::isError($definition)) {
$db->setOption('idxname_format', $idxname_format);
return $definition;
}
$res[$i] = $definition[0];
$res[$i]['name'] = $field;
$res[$i]['table'] = $result;
$res[$i]['type'] = preg_replace('/^([a-z]+).*$/i', '\\1', trim($definition[0]['nativetype']));
// 'primary_key', 'unique_key', 'multiple_key'
$res[$i]['flags'] = empty($flags[$field]) ? '' : $flags[$field];
// not_null', 'unsigned', 'auto_increment', 'default_[rawencodedvalue]'
if (!empty($res[$i]['notnull'])) {
$res[$i]['flags'].= ' not_null';
}
if (!empty($res[$i]['unsigned'])) {
$res[$i]['flags'].= ' unsigned';
}
if (!empty($res[$i]['auto_increment'])) {
$res[$i]['flags'].= ' autoincrement';
}
if (!empty($res[$i]['default'])) {
$res[$i]['flags'].= ' default_'.rawurlencode($res[$i]['default']);
}
if ($mode & MDB2_TABLEINFO_ORDER) {
$res['order'][$res[$i]['name']] = $i;
}
if ($mode & MDB2_TABLEINFO_ORDERTABLE) {
$res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i;
}
}
$db->setOption('idxname_format', $idxname_format);
return $res;
}
}
?>

@ -1,653 +0,0 @@
<?php
// +----------------------------------------------------------------------+
// | PHP versions 4 and 5 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1998-2007 Manuel Lemos, Tomas V.V.Cox, |
// | Stig. S. Bakken, Lukas Smith, Frank M. Kromann, Lorenzo Alberton |
// | All rights reserved. |
// +----------------------------------------------------------------------+
// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB |
// | API as well as database abstraction for PHP applications. |
// | This LICENSE is in the BSD license style. |
// | |
// | Redistribution and use in source and binary forms, with or without |
// | modification, are permitted provided that the following conditions |
// | are met: |
// | |
// | Redistributions of source code must retain the above copyright |
// | notice, this list of conditions and the following disclaimer. |
// | |
// | Redistributions in binary form must reproduce the above copyright |
// | notice, this list of conditions and the following disclaimer in the |
// | documentation and/or other materials provided with the distribution. |
// | |
// | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken, |
// | Lukas Smith nor the names of his contributors may be used to endorse |
// | or promote products derived from this software without specific prior|
// | written permission. |
// | |
// | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
// | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
// | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
// | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE |
// | REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, |
// | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
// | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS|
// | OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED |
// | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
// | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY|
// | WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
// | POSSIBILITY OF SUCH DAMAGE. |
// +----------------------------------------------------------------------+
// | Authors: Lukas Smith <smith@pooteeweet.org> |
// | Lorenzo Alberton <l.alberton@quipo.it> |
// +----------------------------------------------------------------------+
//
// $Id: mssql.php 295587 2010-02-28 17:16:38Z quipo $
//
require_once 'MDB2/Driver/Reverse/Common.php';
/**
* MDB2 MSSQL driver for the schema reverse engineering module
*
* @package MDB2
* @category Database
* @author Lukas Smith <smith@dybnet.de>
* @author Lorenzo Alberton <l.alberton@quipo.it>
*/
class MDB2_Driver_Reverse_mssql extends MDB2_Driver_Reverse_Common
{
// {{{ getTableFieldDefinition()
/**
* Get the structure of a field into an array
*
* @param string $table_name name of table that should be used in method
* @param string $field_name name of field that should be used in method
* @return mixed data array on success, a MDB2 error on failure
* @access public
*/
function getTableFieldDefinition($table_name, $field_name)
{
$db = $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
$result = $db->loadModule('Datatype', null, true);
if (PEAR::isError($result)) {
return $result;
}
list($schema, $table) = $this->splitTableSchema($table_name);
$table = $db->quoteIdentifier($table, true);
$fldname = $db->quoteIdentifier($field_name, true);
$query = "SELECT t.table_name,
c.column_name 'name',
c.data_type 'type',
CASE c.is_nullable WHEN 'YES' THEN 1 ELSE 0 END AS 'is_nullable',
c.column_default,
c.character_maximum_length 'length',
c.numeric_precision,
c.numeric_scale,
c.character_set_name,
c.collation_name
FROM INFORMATION_SCHEMA.TABLES t,
INFORMATION_SCHEMA.COLUMNS c
WHERE t.table_name = c.table_name
AND t.table_name = '$table'
AND c.column_name = '$fldname'";
if (!empty($schema)) {
$query .= " AND t.table_schema = '" .$db->quoteIdentifier($schema, true) ."'";
}
$query .= ' ORDER BY t.table_name';
$column = $db->queryRow($query, null, MDB2_FETCHMODE_ASSOC);
if (PEAR::isError($column)) {
return $column;
}
if (empty($column)) {
return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
'it was not specified an existing table column', __FUNCTION__);
}
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
if ($db->options['field_case'] == CASE_LOWER) {
$column['name'] = strtolower($column['name']);
} else {
$column['name'] = strtoupper($column['name']);
}
} else {
$column = array_change_key_case($column, $db->options['field_case']);
}
$mapped_datatype = $db->datatype->mapNativeDatatype($column);
if (PEAR::isError($mapped_datatype)) {
return $mapped_datatype;
}
list($types, $length, $unsigned, $fixed) = $mapped_datatype;
$notnull = true;
if ($column['is_nullable']) {
$notnull = false;
}
$default = false;
if (array_key_exists('column_default', $column)) {
$default = $column['column_default'];
if ((null === $default) && $notnull) {
$default = '';
} elseif (strlen($default) > 4
&& substr($default, 0, 1) == '('
&& substr($default, -1, 1) == ')'
) {
//mssql wraps the default value in parentheses: "((1234))", "(NULL)"
$default = trim($default, '()');
if ($default == 'NULL') {
$default = null;
}
}
}
$definition[0] = array(
'notnull' => $notnull,
'nativetype' => preg_replace('/^([a-z]+)[^a-z].*/i', '\\1', $column['type'])
);
if (null !== $length) {
$definition[0]['length'] = $length;
}
if (null !== $unsigned) {
$definition[0]['unsigned'] = $unsigned;
}
if (null !== $fixed) {
$definition[0]['fixed'] = $fixed;
}
if (false !== $default) {
$definition[0]['default'] = $default;
}
foreach ($types as $key => $type) {
$definition[$key] = $definition[0];
if ($type == 'clob' || $type == 'blob') {
unset($definition[$key]['default']);
}
$definition[$key]['type'] = $type;
$definition[$key]['mdb2type'] = $type;
}
return $definition;
}
// }}}
// {{{ getTableIndexDefinition()
/**
* Get the structure of an index into an array
*
* @param string $table_name name of table that should be used in method
* @param string $index_name name of index that should be used in method
* @return mixed data array on success, a MDB2 error on failure
* @access public
*/
function getTableIndexDefinition($table_name, $index_name)
{
$db = $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
list($schema, $table) = $this->splitTableSchema($table_name);
$table = $db->quoteIdentifier($table, true);
//$idxname = $db->quoteIdentifier($index_name, true);
$query = "SELECT OBJECT_NAME(i.id) tablename,
i.name indexname,
c.name field_name,
CASE INDEXKEY_PROPERTY(i.id, i.indid, ik.keyno, 'IsDescending')
WHEN 1 THEN 'DESC' ELSE 'ASC'
END 'collation',
ik.keyno 'position'
FROM sysindexes i
JOIN sysindexkeys ik ON ik.id = i.id AND ik.indid = i.indid
JOIN syscolumns c ON c.id = ik.id AND c.colid = ik.colid
WHERE OBJECT_NAME(i.id) = '$table'
AND i.name = '%s'
AND NOT EXISTS (
SELECT *
FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE k
WHERE k.table_name = OBJECT_NAME(i.id)
AND k.constraint_name = i.name";
if (!empty($schema)) {
$query .= " AND k.table_schema = '" .$db->quoteIdentifier($schema, true) ."'";
}
$query .= ')
ORDER BY tablename, indexname, ik.keyno';
$index_name_mdb2 = $db->getIndexName($index_name);
$result = $db->queryRow(sprintf($query, $index_name_mdb2));
if (!PEAR::isError($result) && (null !== $result)) {
// apply 'idxname_format' only if the query succeeded, otherwise
// fallback to the given $index_name, without transformation
$index_name = $index_name_mdb2;
}
$result = $db->query(sprintf($query, $index_name));
if (PEAR::isError($result)) {
return $result;
}
$definition = array();
while (is_array($row = $result->fetchRow(MDB2_FETCHMODE_ASSOC))) {
$column_name = $row['field_name'];
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
if ($db->options['field_case'] == CASE_LOWER) {
$column_name = strtolower($column_name);
} else {
$column_name = strtoupper($column_name);
}
}
$definition['fields'][$column_name] = array(
'position' => (int)$row['position'],
);
if (!empty($row['collation'])) {
$definition['fields'][$column_name]['sorting'] = ($row['collation'] == 'ASC'
? 'ascending' : 'descending');
}
}
$result->free();
if (empty($definition['fields'])) {
return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
'it was not specified an existing table index', __FUNCTION__);
}
return $definition;
}
// }}}
// {{{ getTableConstraintDefinition()
/**
* Get the structure of a constraint into an array
*
* @param string $table_name name of table that should be used in method
* @param string $constraint_name name of constraint that should be used in method
* @return mixed data array on success, a MDB2 error on failure
* @access public
*/
function getTableConstraintDefinition($table_name, $constraint_name)
{
$db = $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
list($schema, $table) = $this->splitTableSchema($table_name);
$table = $db->quoteIdentifier($table, true);
$query = "SELECT k.table_name,
k.column_name field_name,
CASE c.constraint_type WHEN 'PRIMARY KEY' THEN 1 ELSE 0 END 'primary',
CASE c.constraint_type WHEN 'UNIQUE' THEN 1 ELSE 0 END 'unique',
CASE c.constraint_type WHEN 'FOREIGN KEY' THEN 1 ELSE 0 END 'foreign',
CASE c.constraint_type WHEN 'CHECK' THEN 1 ELSE 0 END 'check',
CASE c.is_deferrable WHEN 'NO' THEN 0 ELSE 1 END 'deferrable',
CASE c.initially_deferred WHEN 'NO' THEN 0 ELSE 1 END 'initiallydeferred',
rc.match_option 'match',
rc.update_rule 'onupdate',
rc.delete_rule 'ondelete',
kcu.table_name 'references_table',
kcu.column_name 'references_field',
k.ordinal_position 'field_position'
FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE k
LEFT JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS c
ON k.table_name = c.table_name
AND k.table_schema = c.table_schema
AND k.table_catalog = c.table_catalog
AND k.constraint_catalog = c.constraint_catalog
AND k.constraint_name = c.constraint_name
LEFT JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS rc
ON rc.constraint_schema = c.constraint_schema
AND rc.constraint_catalog = c.constraint_catalog
AND rc.constraint_name = c.constraint_name
LEFT JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE kcu
ON rc.unique_constraint_schema = kcu.constraint_schema
AND rc.unique_constraint_catalog = kcu.constraint_catalog
AND rc.unique_constraint_name = kcu.constraint_name
AND k.ordinal_position = kcu.ordinal_position
WHERE k.constraint_catalog = DB_NAME()
AND k.table_name = '$table'
AND k.constraint_name = '%s'";
if (!empty($schema)) {
$query .= " AND k.table_schema = '" .$db->quoteIdentifier($schema, true) ."'";
}
$query .= ' ORDER BY k.constraint_name,
k.ordinal_position';
$constraint_name_mdb2 = $db->getIndexName($constraint_name);
$result = $db->queryRow(sprintf($query, $constraint_name_mdb2));
if (!PEAR::isError($result) && (null !== $result)) {
// apply 'idxname_format' only if the query succeeded, otherwise
// fallback to the given $index_name, without transformation
$constraint_name = $constraint_name_mdb2;
}
$result = $db->query(sprintf($query, $constraint_name));
if (PEAR::isError($result)) {
return $result;
}
$definition = array(
'fields' => array()
);
while (is_array($row = $result->fetchRow(MDB2_FETCHMODE_ASSOC))) {
$row = array_change_key_case($row, CASE_LOWER);
$column_name = $row['field_name'];
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
if ($db->options['field_case'] == CASE_LOWER) {
$column_name = strtolower($column_name);
} else {
$column_name = strtoupper($column_name);
}
}
$definition['fields'][$column_name] = array(
'position' => (int)$row['field_position']
);
if ($row['foreign']) {
$ref_column_name = $row['references_field'];
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
if ($db->options['field_case'] == CASE_LOWER) {
$ref_column_name = strtolower($ref_column_name);
} else {
$ref_column_name = strtoupper($ref_column_name);
}
}
$definition['references']['table'] = $row['references_table'];
$definition['references']['fields'][$ref_column_name] = array(
'position' => (int)$row['field_position']
);
}
//collation?!?
/*
if (!empty($row['collation'])) {
$definition['fields'][$column_name]['sorting'] = ($row['collation'] == 'ASC'
? 'ascending' : 'descending');
}
*/
$lastrow = $row;
// otherwise $row is no longer usable on exit from loop
}
$result->free();
if (empty($definition['fields'])) {
return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
$constraint_name . ' is not an existing table constraint', __FUNCTION__);
}
$definition['primary'] = (boolean)$lastrow['primary'];
$definition['unique'] = (boolean)$lastrow['unique'];
$definition['foreign'] = (boolean)$lastrow['foreign'];
$definition['check'] = (boolean)$lastrow['check'];
$definition['deferrable'] = (boolean)$lastrow['deferrable'];
$definition['initiallydeferred'] = (boolean)$lastrow['initiallydeferred'];
$definition['onupdate'] = $lastrow['onupdate'];
$definition['ondelete'] = $lastrow['ondelete'];
$definition['match'] = $lastrow['match'];
return $definition;
}
// }}}
// {{{ getTriggerDefinition()
/**
* Get the structure of a trigger into an array
*
* EXPERIMENTAL
*
* WARNING: this function is experimental and may change the returned value
* at any time until labelled as non-experimental
*
* @param string $trigger name of trigger that should be used in method
* @return mixed data array on success, a MDB2 error on failure
* @access public
*/
function getTriggerDefinition($trigger)
{
$db = $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
$query = "SELECT sys1.name trigger_name,
sys2.name table_name,
c.text trigger_body,
c.encrypted is_encripted,
CASE
WHEN OBJECTPROPERTY(sys1.id, 'ExecIsTriggerDisabled') = 1
THEN 0 ELSE 1
END trigger_enabled,
CASE
WHEN OBJECTPROPERTY(sys1.id, 'ExecIsInsertTrigger') = 1
THEN 'INSERT'
WHEN OBJECTPROPERTY(sys1.id, 'ExecIsUpdateTrigger') = 1
THEN 'UPDATE'
WHEN OBJECTPROPERTY(sys1.id, 'ExecIsDeleteTrigger') = 1
THEN 'DELETE'
END trigger_event,
CASE WHEN OBJECTPROPERTY(sys1.id, 'ExecIsInsteadOfTrigger') = 1
THEN 'INSTEAD OF' ELSE 'AFTER'
END trigger_type,
'' trigger_comment
FROM sysobjects sys1
JOIN sysobjects sys2 ON sys1.parent_obj = sys2.id
JOIN syscomments c ON sys1.id = c.id
WHERE sys1.xtype = 'TR'
AND sys1.name = ". $db->quote($trigger, 'text');
$types = array(
'trigger_name' => 'text',
'table_name' => 'text',
'trigger_body' => 'text',
'trigger_type' => 'text',
'trigger_event' => 'text',
'trigger_comment' => 'text',
'trigger_enabled' => 'boolean',
'is_encripted' => 'boolean',
);
$def = $db->queryRow($query, $types, MDB2_FETCHMODE_ASSOC);
if (PEAR::isError($def)) {
return $def;
}
$trg_body = $db->queryCol('EXEC sp_helptext '. $db->quote($trigger, 'text'), 'text');
if (!PEAR::isError($trg_body)) {
$def['trigger_body'] = implode(' ', $trg_body);
}
return $def;
}
// }}}
// {{{ tableInfo()
/**
* Returns information about a table or a result set
*
* NOTE: only supports 'table' and 'flags' if <var>$result</var>
* is a table name.
*
* @param object|string $result MDB2_result object from a query or a
* string containing the name of a table.
* While this also accepts a query result
* resource identifier, this behavior is
* deprecated.
* @param int $mode a valid tableInfo mode
*
* @return array an associative array with the information requested.
* A MDB2_Error object on failure.
*
* @see MDB2_Driver_Common::tableInfo()
*/
function tableInfo($result, $mode = null)
{
if (is_string($result)) {
return parent::tableInfo($result, $mode);
}
$db = $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
$resource = MDB2::isResultCommon($result) ? $result->getResource() : $result;
if (!is_resource($resource)) {
return $db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null,
'Could not generate result resource', __FUNCTION__);
}
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
if ($db->options['field_case'] == CASE_LOWER) {
$case_func = 'strtolower';
} else {
$case_func = 'strtoupper';
}
} else {
$case_func = 'strval';
}
$count = @mssql_num_fields($resource);
$res = array();
if ($mode) {
$res['num_fields'] = $count;
}
$db->loadModule('Datatype', null, true);
for ($i = 0; $i < $count; $i++) {
$res[$i] = array(
'table' => '',
'name' => $case_func(@mssql_field_name($resource, $i)),
'type' => @mssql_field_type($resource, $i),
'length' => @mssql_field_length($resource, $i),
'flags' => '',
);
$mdb2type_info = $db->datatype->mapNativeDatatype($res[$i]);
if (PEAR::isError($mdb2type_info)) {
return $mdb2type_info;
}
$res[$i]['mdb2type'] = $mdb2type_info[0][0];
if ($mode & MDB2_TABLEINFO_ORDER) {
$res['order'][$res[$i]['name']] = $i;
}
if ($mode & MDB2_TABLEINFO_ORDERTABLE) {
$res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i;
}
}
return $res;
}
// }}}
// {{{ _mssql_field_flags()
/**
* Get a column's flags
*
* Supports "not_null", "primary_key",
* "auto_increment" (mssql identity), "timestamp" (mssql timestamp),
* "unique_key" (mssql unique index, unique check or primary_key) and
* "multiple_key" (multikey index)
*
* mssql timestamp is NOT similar to the mysql timestamp so this is maybe
* not useful at all - is the behaviour of mysql_field_flags that primary
* keys are alway unique? is the interpretation of multiple_key correct?
*
* @param string $table the table name
* @param string $column the field name
*
* @return string the flags
*
* @access protected
* @author Joern Barthel <j_barthel@web.de>
*/
function _mssql_field_flags($table, $column)
{
$db = $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
static $tableName = null;
static $flags = array();
if ($table != $tableName) {
$flags = array();
$tableName = $table;
// get unique and primary keys
$res = $db->queryAll("EXEC SP_HELPINDEX[$table]", null, MDB2_FETCHMODE_ASSOC);
foreach ($res as $val) {
$val = array_change_key_case($val, CASE_LOWER);
$keys = explode(', ', $val['index_keys']);
if (sizeof($keys) > 1) {
foreach ($keys as $key) {
$this->_add_flag($flags[$key], 'multiple_key');
}
}
if (strpos($val['index_description'], 'primary key')) {
foreach ($keys as $key) {
$this->_add_flag($flags[$key], 'primary_key');
}
} elseif (strpos($val['index_description'], 'unique')) {
foreach ($keys as $key) {
$this->_add_flag($flags[$key], 'unique_key');
}
}
}
// get auto_increment, not_null and timestamp
$res = $db->queryAll("EXEC SP_COLUMNS[$table]", null, MDB2_FETCHMODE_ASSOC);
foreach ($res as $val) {
$val = array_change_key_case($val, CASE_LOWER);
if ($val['nullable'] == '0') {
$this->_add_flag($flags[$val['column_name']], 'not_null');
}
if (strpos($val['type_name'], 'identity')) {
$this->_add_flag($flags[$val['column_name']], 'auto_increment');
}
if (strpos($val['type_name'], 'timestamp')) {
$this->_add_flag($flags[$val['column_name']], 'timestamp');
}
}
}
if (!empty($flags[$column])) {
return(implode(' ', $flags[$column]));
}
return '';
}
// }}}
// {{{ _add_flag()
/**
* Adds a string to the flags array if the flag is not yet in there
* - if there is no flag present the array is created
*
* @param array &$array the reference to the flag-array
* @param string $value the flag value
*
* @return void
*
* @access protected
* @author Joern Barthel <j_barthel@web.de>
*/
function _add_flag(&$array, $value)
{
if (!is_array($array)) {
$array = array($value);
} elseif (!in_array($value, $array)) {
array_push($array, $value);
}
}
// }}}
}
?>

@ -1,546 +0,0 @@
<?php
// +----------------------------------------------------------------------+
// | PHP versions 4 and 5 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1998-2007 Manuel Lemos, Tomas V.V.Cox, |
// | Stig. S. Bakken, Lukas Smith |
// | All rights reserved. |
// +----------------------------------------------------------------------+
// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB |
// | API as well as database abstraction for PHP applications. |
// | This LICENSE is in the BSD license style. |
// | |
// | Redistribution and use in source and binary forms, with or without |
// | modification, are permitted provided that the following conditions |
// | are met: |
// | |
// | Redistributions of source code must retain the above copyright |
// | notice, this list of conditions and the following disclaimer. |
// | |
// | Redistributions in binary form must reproduce the above copyright |
// | notice, this list of conditions and the following disclaimer in the |
// | documentation and/or other materials provided with the distribution. |
// | |
// | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken, |
// | Lukas Smith nor the names of his contributors may be used to endorse |
// | or promote products derived from this software without specific prior|
// | written permission. |
// | |
// | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
// | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
// | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
// | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE |
// | REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, |
// | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
// | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS|
// | OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED |
// | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
// | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY|
// | WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
// | POSSIBILITY OF SUCH DAMAGE. |
// +----------------------------------------------------------------------+
// | Author: Lukas Smith <smith@pooteeweet.org> |
// +----------------------------------------------------------------------+
//
// $Id: mysql.php 295587 2010-02-28 17:16:38Z quipo $
//
require_once 'MDB2/Driver/Reverse/Common.php';
/**
* MDB2 MySQL driver for the schema reverse engineering module
*
* @package MDB2
* @category Database
* @author Lukas Smith <smith@pooteeweet.org>
* @author Lorenzo Alberton <l.alberton@quipo.it>
*/
class MDB2_Driver_Reverse_mysql extends MDB2_Driver_Reverse_Common
{
// {{{ getTableFieldDefinition()
/**
* Get the structure of a field into an array
*
* @param string $table_name name of table that should be used in method
* @param string $field_name name of field that should be used in method
* @return mixed data array on success, a MDB2 error on failure
* @access public
*/
function getTableFieldDefinition($table_name, $field_name)
{
$db = $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
$result = $db->loadModule('Datatype', null, true);
if (PEAR::isError($result)) {
return $result;
}
list($schema, $table) = $this->splitTableSchema($table_name);
$table = $db->quoteIdentifier($table, true);
$query = "SHOW FULL COLUMNS FROM $table LIKE ".$db->quote($field_name);
$columns = $db->queryAll($query, null, MDB2_FETCHMODE_ASSOC);
if (PEAR::isError($columns)) {
return $columns;
}
foreach ($columns as $column) {
$column = array_change_key_case($column, CASE_LOWER);
$column['name'] = $column['field'];
unset($column['field']);
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
if ($db->options['field_case'] == CASE_LOWER) {
$column['name'] = strtolower($column['name']);
} else {
$column['name'] = strtoupper($column['name']);
}
} else {
$column = array_change_key_case($column, $db->options['field_case']);
}
if ($field_name == $column['name']) {
$mapped_datatype = $db->datatype->mapNativeDatatype($column);
if (PEAR::isError($mapped_datatype)) {
return $mapped_datatype;
}
list($types, $length, $unsigned, $fixed) = $mapped_datatype;
$notnull = false;
if (empty($column['null']) || $column['null'] !== 'YES') {
$notnull = true;
}
$default = false;
if (array_key_exists('default', $column)) {
$default = $column['default'];
if ((null === $default) && $notnull) {
$default = '';
}
}
$definition[0] = array(
'notnull' => $notnull,
'nativetype' => preg_replace('/^([a-z]+)[^a-z].*/i', '\\1', $column['type'])
);
$autoincrement = false;
if (!empty($column['extra'])) {
if ($column['extra'] == 'auto_increment') {
$autoincrement = true;
} else {
$definition[0]['extra'] = $column['extra'];
}
}
$collate = null;
if (!empty($column['collation'])) {
$collate = $column['collation'];
$charset = preg_replace('/(.+?)(_.+)?/', '$1', $collate);
}
if (null !== $length) {
$definition[0]['length'] = $length;
}
if (null !== $unsigned) {
$definition[0]['unsigned'] = $unsigned;
}
if (null !== $fixed) {
$definition[0]['fixed'] = $fixed;
}
if ($default !== false) {
$definition[0]['default'] = $default;
}
if ($autoincrement !== false) {
$definition[0]['autoincrement'] = $autoincrement;
}
if (null !== $collate) {
$definition[0]['collate'] = $collate;
$definition[0]['charset'] = $charset;
}
foreach ($types as $key => $type) {
$definition[$key] = $definition[0];
if ($type == 'clob' || $type == 'blob') {
unset($definition[$key]['default']);
} elseif ($type == 'timestamp' && $notnull && empty($definition[$key]['default'])) {
$definition[$key]['default'] = '0000-00-00 00:00:00';
}
$definition[$key]['type'] = $type;
$definition[$key]['mdb2type'] = $type;
}
return $definition;
}
}
return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
'it was not specified an existing table column', __FUNCTION__);
}
// }}}
// {{{ getTableIndexDefinition()
/**
* Get the structure of an index into an array
*
* @param string $table_name name of table that should be used in method
* @param string $index_name name of index that should be used in method
* @return mixed data array on success, a MDB2 error on failure
* @access public
*/
function getTableIndexDefinition($table_name, $index_name)
{
$db = $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
list($schema, $table) = $this->splitTableSchema($table_name);
$table = $db->quoteIdentifier($table, true);
$query = "SHOW INDEX FROM $table /*!50002 WHERE Key_name = %s */";
$index_name_mdb2 = $db->getIndexName($index_name);
$result = $db->queryRow(sprintf($query, $db->quote($index_name_mdb2)));
if (!PEAR::isError($result) && (null !== $result)) {
// apply 'idxname_format' only if the query succeeded, otherwise
// fallback to the given $index_name, without transformation
$index_name = $index_name_mdb2;
}
$result = $db->query(sprintf($query, $db->quote($index_name)));
if (PEAR::isError($result)) {
return $result;
}
$colpos = 1;
$definition = array();
while (is_array($row = $result->fetchRow(MDB2_FETCHMODE_ASSOC))) {
$row = array_change_key_case($row, CASE_LOWER);
$key_name = $row['key_name'];
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
if ($db->options['field_case'] == CASE_LOWER) {
$key_name = strtolower($key_name);
} else {
$key_name = strtoupper($key_name);
}
}
if ($index_name == $key_name) {
if (!$row['non_unique']) {
return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
$index_name . ' is not an existing table index', __FUNCTION__);
}
$column_name = $row['column_name'];
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
if ($db->options['field_case'] == CASE_LOWER) {
$column_name = strtolower($column_name);
} else {
$column_name = strtoupper($column_name);
}
}
$definition['fields'][$column_name] = array(
'position' => $colpos++
);
if (!empty($row['collation'])) {
$definition['fields'][$column_name]['sorting'] = ($row['collation'] == 'A'
? 'ascending' : 'descending');
}
}
}
$result->free();
if (empty($definition['fields'])) {
return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
$index_name . ' is not an existing table index', __FUNCTION__);
}
return $definition;
}
// }}}
// {{{ getTableConstraintDefinition()
/**
* Get the structure of a constraint into an array
*
* @param string $table_name name of table that should be used in method
* @param string $constraint_name name of constraint that should be used in method
* @return mixed data array on success, a MDB2 error on failure
* @access public
*/
function getTableConstraintDefinition($table_name, $constraint_name)
{
$db = $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
list($schema, $table) = $this->splitTableSchema($table_name);
$constraint_name_original = $constraint_name;
$table = $db->quoteIdentifier($table, true);
$query = "SHOW INDEX FROM $table /*!50002 WHERE Key_name = %s */";
if (strtolower($constraint_name) != 'primary') {
$constraint_name_mdb2 = $db->getIndexName($constraint_name);
$result = $db->queryRow(sprintf($query, $db->quote($constraint_name_mdb2)));
if (!PEAR::isError($result) && (null !== $result)) {
// apply 'idxname_format' only if the query succeeded, otherwise
// fallback to the given $index_name, without transformation
$constraint_name = $constraint_name_mdb2;
}
}
$result = $db->query(sprintf($query, $db->quote($constraint_name)));
if (PEAR::isError($result)) {
return $result;
}
$colpos = 1;
//default values, eventually overridden
$definition = array(
'primary' => false,
'unique' => false,
'foreign' => false,
'check' => false,
'fields' => array(),
'references' => array(
'table' => '',
'fields' => array(),
),
'onupdate' => '',
'ondelete' => '',
'match' => '',
'deferrable' => false,
'initiallydeferred' => false,
);
while (is_array($row = $result->fetchRow(MDB2_FETCHMODE_ASSOC))) {
$row = array_change_key_case($row, CASE_LOWER);
$key_name = $row['key_name'];
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
if ($db->options['field_case'] == CASE_LOWER) {
$key_name = strtolower($key_name);
} else {
$key_name = strtoupper($key_name);
}
}
if ($constraint_name == $key_name) {
if ($row['non_unique']) {
//FOREIGN KEY?
return $this->_getTableFKConstraintDefinition($table, $constraint_name_original, $definition);
}
if ($row['key_name'] == 'PRIMARY') {
$definition['primary'] = true;
} elseif (!$row['non_unique']) {
$definition['unique'] = true;
}
$column_name = $row['column_name'];
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
if ($db->options['field_case'] == CASE_LOWER) {
$column_name = strtolower($column_name);
} else {
$column_name = strtoupper($column_name);
}
}
$definition['fields'][$column_name] = array(
'position' => $colpos++
);
if (!empty($row['collation'])) {
$definition['fields'][$column_name]['sorting'] = ($row['collation'] == 'A'
? 'ascending' : 'descending');
}
}
}
$result->free();
if (empty($definition['fields'])) {
return $this->_getTableFKConstraintDefinition($table, $constraint_name_original, $definition);
}
return $definition;
}
// }}}
// {{{ _getTableFKConstraintDefinition()
/**
* Get the FK definition from the CREATE TABLE statement
*
* @param string $table table name
* @param string $constraint_name constraint name
* @param array $definition default values for constraint definition
*
* @return array|PEAR_Error
* @access private
*/
function _getTableFKConstraintDefinition($table, $constraint_name, $definition)
{
$db = $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
//Use INFORMATION_SCHEMA instead?
//SELECT *
// FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS
// WHERE CONSTRAINT_SCHEMA = '$dbname'
// AND TABLE_NAME = '$table'
// AND CONSTRAINT_NAME = '$constraint_name';
$query = 'SHOW CREATE TABLE '. $db->escape($table);
$constraint = $db->queryOne($query, 'text', 1);
if (!PEAR::isError($constraint) && !empty($constraint)) {
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
if ($db->options['field_case'] == CASE_LOWER) {
$constraint = strtolower($constraint);
} else {
$constraint = strtoupper($constraint);
}
}
$constraint_name_original = $constraint_name;
$constraint_name = $db->getIndexName($constraint_name);
$pattern = '/\bCONSTRAINT\s+'.$constraint_name.'\s+FOREIGN KEY\s+\(([^\)]+)\) \bREFERENCES\b ([^\s]+) \(([^\)]+)\)(?: ON DELETE ([^\s]+))?(?: ON UPDATE ([^\s]+))?/i';
if (!preg_match($pattern, str_replace('`', '', $constraint), $matches)) {
//fallback to original constraint name
$pattern = '/\bCONSTRAINT\s+'.$constraint_name_original.'\s+FOREIGN KEY\s+\(([^\)]+)\) \bREFERENCES\b ([^\s]+) \(([^\)]+)\)(?: ON DELETE ([^\s]+))?(?: ON UPDATE ([^\s]+))?/i';
}
if (preg_match($pattern, str_replace('`', '', $constraint), $matches)) {
$definition['foreign'] = true;
$column_names = explode(',', $matches[1]);
$referenced_cols = explode(',', $matches[3]);
$definition['references'] = array(
'table' => $matches[2],
'fields' => array(),
);
$colpos = 1;
foreach ($column_names as $column_name) {
$definition['fields'][trim($column_name)] = array(
'position' => $colpos++
);
}
$colpos = 1;
foreach ($referenced_cols as $column_name) {
$definition['references']['fields'][trim($column_name)] = array(
'position' => $colpos++
);
}
$definition['ondelete'] = empty($matches[4]) ? 'RESTRICT' : strtoupper($matches[4]);
$definition['onupdate'] = empty($matches[5]) ? 'RESTRICT' : strtoupper($matches[5]);
$definition['match'] = 'SIMPLE';
return $definition;
}
}
return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
$constraint_name . ' is not an existing table constraint', __FUNCTION__);
}
// }}}
// {{{ getTriggerDefinition()
/**
* Get the structure of a trigger into an array
*
* EXPERIMENTAL
*
* WARNING: this function is experimental and may change the returned value
* at any time until labelled as non-experimental
*
* @param string $trigger name of trigger that should be used in method
* @return mixed data array on success, a MDB2 error on failure
* @access public
*/
function getTriggerDefinition($trigger)
{
$db = $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
$query = 'SELECT trigger_name,
event_object_table AS table_name,
action_statement AS trigger_body,
action_timing AS trigger_type,
event_manipulation AS trigger_event
FROM information_schema.triggers
WHERE trigger_name = '. $db->quote($trigger, 'text');
$types = array(
'trigger_name' => 'text',
'table_name' => 'text',
'trigger_body' => 'text',
'trigger_type' => 'text',
'trigger_event' => 'text',
);
$def = $db->queryRow($query, $types, MDB2_FETCHMODE_ASSOC);
if (PEAR::isError($def)) {
return $def;
}
$def['trigger_comment'] = '';
$def['trigger_enabled'] = true;
return $def;
}
// }}}
// {{{ tableInfo()
/**
* Returns information about a table or a result set
*
* @param object|string $result MDB2_result object from a query or a
* string containing the name of a table.
* While this also accepts a query result
* resource identifier, this behavior is
* deprecated.
* @param int $mode a valid tableInfo mode
*
* @return array an associative array with the information requested.
* A MDB2_Error object on failure.
*
* @see MDB2_Driver_Common::setOption()
*/
function tableInfo($result, $mode = null)
{
if (is_string($result)) {
return parent::tableInfo($result, $mode);
}
$db = $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
$resource = MDB2::isResultCommon($result) ? $result->getResource() : $result;
if (!is_resource($resource)) {
return $db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null,
'Could not generate result resource', __FUNCTION__);
}
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
if ($db->options['field_case'] == CASE_LOWER) {
$case_func = 'strtolower';
} else {
$case_func = 'strtoupper';
}
} else {
$case_func = 'strval';
}
$count = @mysql_num_fields($resource);
$res = array();
if ($mode) {
$res['num_fields'] = $count;
}
$db->loadModule('Datatype', null, true);
for ($i = 0; $i < $count; $i++) {
$res[$i] = array(
'table' => $case_func(@mysql_field_table($resource, $i)),
'name' => $case_func(@mysql_field_name($resource, $i)),
'type' => @mysql_field_type($resource, $i),
'length' => @mysql_field_len($resource, $i),
'flags' => @mysql_field_flags($resource, $i),
);
if ($res[$i]['type'] == 'string') {
$res[$i]['type'] = 'char';
} elseif ($res[$i]['type'] == 'unknown') {
$res[$i]['type'] = 'decimal';
}
$mdb2type_info = $db->datatype->mapNativeDatatype($res[$i]);
if (PEAR::isError($mdb2type_info)) {
return $mdb2type_info;
}
$res[$i]['mdb2type'] = $mdb2type_info[0][0];
if ($mode & MDB2_TABLEINFO_ORDER) {
$res['order'][$res[$i]['name']] = $i;
}
if ($mode & MDB2_TABLEINFO_ORDERTABLE) {
$res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i;
}
}
return $res;
}
}
?>

@ -1,610 +0,0 @@
<?php
// +----------------------------------------------------------------------+
// | PHP versions 4 and 5 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1998-2007 Manuel Lemos, Tomas V.V.Cox, |
// | Stig. S. Bakken, Lukas Smith |
// | All rights reserved. |
// +----------------------------------------------------------------------+
// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB |
// | API as well as database abstraction for PHP applications. |
// | This LICENSE is in the BSD license style. |
// | |
// | Redistribution and use in source and binary forms, with or without |
// | modification, are permitted provided that the following conditions |
// | are met: |
// | |
// | Redistributions of source code must retain the above copyright |
// | notice, this list of conditions and the following disclaimer. |
// | |
// | Redistributions in binary form must reproduce the above copyright |
// | notice, this list of conditions and the following disclaimer in the |
// | documentation and/or other materials provided with the distribution. |
// | |
// | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken, |
// | Lukas Smith nor the names of his contributors may be used to endorse |
// | or promote products derived from this software without specific prior|
// | written permission. |
// | |
// | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
// | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
// | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
// | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE |
// | REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, |
// | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
// | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS|
// | OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED |
// | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
// | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY|
// | WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
// | POSSIBILITY OF SUCH DAMAGE. |
// +----------------------------------------------------------------------+
// | Author: Lukas Smith <smith@pooteeweet.org> |
// +----------------------------------------------------------------------+
//
// $Id: mysqli.php 295587 2010-02-28 17:16:38Z quipo $
//
require_once 'MDB2/Driver/Reverse/Common.php';
/**
* MDB2 MySQLi driver for the schema reverse engineering module
*
* @package MDB2
* @category Database
* @author Lukas Smith <smith@pooteeweet.org>
* @author Lorenzo Alberton <l.alberton@quipo.it>
*/
class MDB2_Driver_Reverse_mysqli extends MDB2_Driver_Reverse_Common
{
/**
* Array for converting MYSQLI_*_FLAG constants to text values
* @var array
* @access public
*/
var $flags = array(
MYSQLI_NOT_NULL_FLAG => 'not_null',
MYSQLI_PRI_KEY_FLAG => 'primary_key',
MYSQLI_UNIQUE_KEY_FLAG => 'unique_key',
MYSQLI_MULTIPLE_KEY_FLAG => 'multiple_key',
MYSQLI_BLOB_FLAG => 'blob',
MYSQLI_UNSIGNED_FLAG => 'unsigned',
MYSQLI_ZEROFILL_FLAG => 'zerofill',
MYSQLI_AUTO_INCREMENT_FLAG => 'auto_increment',
MYSQLI_TIMESTAMP_FLAG => 'timestamp',
MYSQLI_SET_FLAG => 'set',
// MYSQLI_NUM_FLAG => 'numeric', // unnecessary
// MYSQLI_PART_KEY_FLAG => 'multiple_key', // duplicatvie
MYSQLI_GROUP_FLAG => 'group_by'
);
/**
* Array for converting MYSQLI_TYPE_* constants to text values
* @var array
* @access public
*/
var $types = array(
MYSQLI_TYPE_DECIMAL => 'decimal',
246 => 'decimal',
MYSQLI_TYPE_TINY => 'tinyint',
MYSQLI_TYPE_SHORT => 'int',
MYSQLI_TYPE_LONG => 'int',
MYSQLI_TYPE_FLOAT => 'float',
MYSQLI_TYPE_DOUBLE => 'double',
// MYSQLI_TYPE_NULL => 'DEFAULT NULL', // let flags handle it
MYSQLI_TYPE_TIMESTAMP => 'timestamp',
MYSQLI_TYPE_LONGLONG => 'bigint',
MYSQLI_TYPE_INT24 => 'mediumint',
MYSQLI_TYPE_DATE => 'date',
MYSQLI_TYPE_TIME => 'time',
MYSQLI_TYPE_DATETIME => 'datetime',
MYSQLI_TYPE_YEAR => 'year',
MYSQLI_TYPE_NEWDATE => 'date',
MYSQLI_TYPE_ENUM => 'enum',
MYSQLI_TYPE_SET => 'set',
MYSQLI_TYPE_TINY_BLOB => 'tinyblob',
MYSQLI_TYPE_MEDIUM_BLOB => 'mediumblob',
MYSQLI_TYPE_LONG_BLOB => 'longblob',
MYSQLI_TYPE_BLOB => 'blob',
MYSQLI_TYPE_VAR_STRING => 'varchar',
MYSQLI_TYPE_STRING => 'char',
MYSQLI_TYPE_GEOMETRY => 'geometry',
);
// {{{ getTableFieldDefinition()
/**
* Get the structure of a field into an array
*
* @param string $table_name name of table that should be used in method
* @param string $field_name name of field that should be used in method
* @return mixed data array on success, a MDB2 error on failure
* @access public
*/
function getTableFieldDefinition($table_name, $field_name)
{
$db = $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
$result = $db->loadModule('Datatype', null, true);
if (PEAR::isError($result)) {
return $result;
}
list($schema, $table) = $this->splitTableSchema($table_name);
$table = $db->quoteIdentifier($table, true);
$query = "SHOW FULL COLUMNS FROM $table LIKE ".$db->quote($field_name);
$columns = $db->queryAll($query, null, MDB2_FETCHMODE_ASSOC);
if (PEAR::isError($columns)) {
return $columns;
}
foreach ($columns as $column) {
$column = array_change_key_case($column, CASE_LOWER);
$column['name'] = $column['field'];
unset($column['field']);
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
if ($db->options['field_case'] == CASE_LOWER) {
$column['name'] = strtolower($column['name']);
} else {
$column['name'] = strtoupper($column['name']);
}
} else {
$column = array_change_key_case($column, $db->options['field_case']);
}
if ($field_name == $column['name']) {
$mapped_datatype = $db->datatype->mapNativeDatatype($column);
if (PEAR::isError($mapped_datatype)) {
return $mapped_datatype;
}
list($types, $length, $unsigned, $fixed) = $mapped_datatype;
$notnull = false;
if (empty($column['null']) || $column['null'] !== 'YES') {
$notnull = true;
}
$default = false;
if (array_key_exists('default', $column)) {
$default = $column['default'];
if ((null === $default) && $notnull) {
$default = '';
}
}
$definition[0] = array(
'notnull' => $notnull,
'nativetype' => preg_replace('/^([a-z]+)[^a-z].*/i', '\\1', $column['type'])
);
$autoincrement = false;
if (!empty($column['extra'])) {
if ($column['extra'] == 'auto_increment') {
$autoincrement = true;
} else {
$definition[0]['extra'] = $column['extra'];
}
}
$collate = null;
if (!empty($column['collation'])) {
$collate = $column['collation'];
$charset = preg_replace('/(.+?)(_.+)?/', '$1', $collate);
}
if (null !== $length) {
$definition[0]['length'] = $length;
}
if (null !== $unsigned) {
$definition[0]['unsigned'] = $unsigned;
}
if (null !== $fixed) {
$definition[0]['fixed'] = $fixed;
}
if ($default !== false) {
$definition[0]['default'] = $default;
}
if ($autoincrement !== false) {
$definition[0]['autoincrement'] = $autoincrement;
}
if (null !== $collate) {
$definition[0]['collate'] = $collate;
$definition[0]['charset'] = $charset;
}
foreach ($types as $key => $type) {
$definition[$key] = $definition[0];
if ($type == 'clob' || $type == 'blob') {
unset($definition[$key]['default']);
} elseif ($type == 'timestamp' && $notnull && empty($definition[$key]['default'])) {
$definition[$key]['default'] = '0000-00-00 00:00:00';
}
$definition[$key]['type'] = $type;
$definition[$key]['mdb2type'] = $type;
}
return $definition;
}
}
return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
'it was not specified an existing table column', __FUNCTION__);
}
// }}}
// {{{ getTableIndexDefinition()
/**
* Get the structure of an index into an array
*
* @param string $table_name name of table that should be used in method
* @param string $index_name name of index that should be used in method
* @return mixed data array on success, a MDB2 error on failure
* @access public
*/
function getTableIndexDefinition($table_name, $index_name)
{
$db = $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
list($schema, $table) = $this->splitTableSchema($table_name);
$table = $db->quoteIdentifier($table, true);
$query = "SHOW INDEX FROM $table /*!50002 WHERE Key_name = %s */";
$index_name_mdb2 = $db->getIndexName($index_name);
$result = $db->queryRow(sprintf($query, $db->quote($index_name_mdb2)));
if (!PEAR::isError($result) && (null !== $result)) {
// apply 'idxname_format' only if the query succeeded, otherwise
// fallback to the given $index_name, without transformation
$index_name = $index_name_mdb2;
}
$result = $db->query(sprintf($query, $db->quote($index_name)));
if (PEAR::isError($result)) {
return $result;
}
$colpos = 1;
$definition = array();
while (is_array($row = $result->fetchRow(MDB2_FETCHMODE_ASSOC))) {
$row = array_change_key_case($row, CASE_LOWER);
$key_name = $row['key_name'];
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
if ($db->options['field_case'] == CASE_LOWER) {
$key_name = strtolower($key_name);
} else {
$key_name = strtoupper($key_name);
}
}
if ($index_name == $key_name) {
if (!$row['non_unique']) {
return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
$index_name . ' is not an existing table index', __FUNCTION__);
}
$column_name = $row['column_name'];
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
if ($db->options['field_case'] == CASE_LOWER) {
$column_name = strtolower($column_name);
} else {
$column_name = strtoupper($column_name);
}
}
$definition['fields'][$column_name] = array(
'position' => $colpos++
);
if (!empty($row['collation'])) {
$definition['fields'][$column_name]['sorting'] = ($row['collation'] == 'A'
? 'ascending' : 'descending');
}
}
}
$result->free();
if (empty($definition['fields'])) {
return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
$index_name . ' is not an existing table index', __FUNCTION__);
}
return $definition;
}
// }}}
// {{{ getTableConstraintDefinition()
/**
* Get the structure of a constraint into an array
*
* @param string $table_name name of table that should be used in method
* @param string $constraint_name name of constraint that should be used in method
* @return mixed data array on success, a MDB2 error on failure
* @access public
*/
function getTableConstraintDefinition($table_name, $constraint_name)
{
$db = $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
list($schema, $table) = $this->splitTableSchema($table_name);
$constraint_name_original = $constraint_name;
$table = $db->quoteIdentifier($table, true);
$query = "SHOW INDEX FROM $table /*!50002 WHERE Key_name = %s */";
if (strtolower($constraint_name) != 'primary') {
$constraint_name_mdb2 = $db->getIndexName($constraint_name);
$result = $db->queryRow(sprintf($query, $db->quote($constraint_name_mdb2)));
if (!PEAR::isError($result) && (null !== $result)) {
// apply 'idxname_format' only if the query succeeded, otherwise
// fallback to the given $index_name, without transformation
$constraint_name = $constraint_name_mdb2;
}
}
$result = $db->query(sprintf($query, $db->quote($constraint_name)));
if (PEAR::isError($result)) {
return $result;
}
$colpos = 1;
//default values, eventually overridden
$definition = array(
'primary' => false,
'unique' => false,
'foreign' => false,
'check' => false,
'fields' => array(),
'references' => array(
'table' => '',
'fields' => array(),
),
'onupdate' => '',
'ondelete' => '',
'match' => '',
'deferrable' => false,
'initiallydeferred' => false,
);
while (is_array($row = $result->fetchRow(MDB2_FETCHMODE_ASSOC))) {
$row = array_change_key_case($row, CASE_LOWER);
$key_name = $row['key_name'];
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
if ($db->options['field_case'] == CASE_LOWER) {
$key_name = strtolower($key_name);
} else {
$key_name = strtoupper($key_name);
}
}
if ($constraint_name == $key_name) {
if ($row['non_unique']) {
//FOREIGN KEY?
return $this->_getTableFKConstraintDefinition($table, $constraint_name_original, $definition);
}
if ($row['key_name'] == 'PRIMARY') {
$definition['primary'] = true;
} elseif (!$row['non_unique']) {
$definition['unique'] = true;
}
$column_name = $row['column_name'];
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
if ($db->options['field_case'] == CASE_LOWER) {
$column_name = strtolower($column_name);
} else {
$column_name = strtoupper($column_name);
}
}
$definition['fields'][$column_name] = array(
'position' => $colpos++
);
if (!empty($row['collation'])) {
$definition['fields'][$column_name]['sorting'] = ($row['collation'] == 'A'
? 'ascending' : 'descending');
}
}
}
$result->free();
if (empty($definition['fields'])) {
return $this->_getTableFKConstraintDefinition($table, $constraint_name_original, $definition);
}
return $definition;
}
// }}}
// {{{ _getTableFKConstraintDefinition()
/**
* Get the FK definition from the CREATE TABLE statement
*
* @param string $table table name
* @param string $constraint_name constraint name
* @param array $definition default values for constraint definition
*
* @return array|PEAR_Error
* @access private
*/
function _getTableFKConstraintDefinition($table, $constraint_name, $definition)
{
$db = $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
//Use INFORMATION_SCHEMA instead?
//SELECT *
// FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS
// WHERE CONSTRAINT_SCHEMA = '$dbname'
// AND TABLE_NAME = '$table'
// AND CONSTRAINT_NAME = '$constraint_name';
$query = 'SHOW CREATE TABLE '. $db->escape($table);
$constraint = $db->queryOne($query, 'text', 1);
if (!PEAR::isError($constraint) && !empty($constraint)) {
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
if ($db->options['field_case'] == CASE_LOWER) {
$constraint = strtolower($constraint);
} else {
$constraint = strtoupper($constraint);
}
}
$constraint_name_original = $constraint_name;
$constraint_name = $db->getIndexName($constraint_name);
$pattern = '/\bCONSTRAINT\s+'.$constraint_name.'\s+FOREIGN KEY\s+\(([^\)]+)\) \bREFERENCES\b ([^\s]+) \(([^\)]+)\)(?: ON DELETE ([^\s]+))?(?: ON UPDATE ([^\s]+))?/i';
if (!preg_match($pattern, str_replace('`', '', $constraint), $matches)) {
//fallback to original constraint name
$pattern = '/\bCONSTRAINT\s+'.$constraint_name_original.'\s+FOREIGN KEY\s+\(([^\)]+)\) \bREFERENCES\b ([^\s]+) \(([^\)]+)\)(?: ON DELETE ([^\s]+))?(?: ON UPDATE ([^\s]+))?/i';
}
if (preg_match($pattern, str_replace('`', '', $constraint), $matches)) {
$definition['foreign'] = true;
$column_names = explode(',', $matches[1]);
$referenced_cols = explode(',', $matches[3]);
$definition['references'] = array(
'table' => $matches[2],
'fields' => array(),
);
$colpos = 1;
foreach ($column_names as $column_name) {
$definition['fields'][trim($column_name)] = array(
'position' => $colpos++
);
}
$colpos = 1;
foreach ($referenced_cols as $column_name) {
$definition['references']['fields'][trim($column_name)] = array(
'position' => $colpos++
);
}
$definition['ondelete'] = empty($matches[4]) ? 'RESTRICT' : strtoupper($matches[4]);
$definition['onupdate'] = empty($matches[5]) ? 'RESTRICT' : strtoupper($matches[5]);
$definition['match'] = 'SIMPLE';
return $definition;
}
}
return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
$constraint_name . ' is not an existing table constraint', __FUNCTION__);
}
// }}}
// {{{ getTriggerDefinition()
/**
* Get the structure of a trigger into an array
*
* EXPERIMENTAL
*
* WARNING: this function is experimental and may change the returned value
* at any time until labelled as non-experimental
*
* @param string $trigger name of trigger that should be used in method
* @return mixed data array on success, a MDB2 error on failure
* @access public
*/
function getTriggerDefinition($trigger)
{
$db = $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
$query = 'SELECT trigger_name,
event_object_table AS table_name,
action_statement AS trigger_body,
action_timing AS trigger_type,
event_manipulation AS trigger_event
FROM information_schema.triggers
WHERE trigger_name = '. $db->quote($trigger, 'text');
$types = array(
'trigger_name' => 'text',
'table_name' => 'text',
'trigger_body' => 'text',
'trigger_type' => 'text',
'trigger_event' => 'text',
);
$def = $db->queryRow($query, $types, MDB2_FETCHMODE_ASSOC);
if (PEAR::isError($def)) {
return $def;
}
$def['trigger_comment'] = '';
$def['trigger_enabled'] = true;
return $def;
}
// }}}
// {{{ tableInfo()
/**
* Returns information about a table or a result set
*
* @param object|string $result MDB2_result object from a query or a
* string containing the name of a table.
* While this also accepts a query result
* resource identifier, this behavior is
* deprecated.
* @param int $mode a valid tableInfo mode
*
* @return array an associative array with the information requested.
* A MDB2_Error object on failure.
*
* @see MDB2_Driver_Common::setOption()
*/
function tableInfo($result, $mode = null)
{
if (is_string($result)) {
return parent::tableInfo($result, $mode);
}
$db = $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
$resource = MDB2::isResultCommon($result) ? $result->getResource() : $result;
if (!is_object($resource)) {
return $db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null,
'Could not generate result resource', __FUNCTION__);
}
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
if ($db->options['field_case'] == CASE_LOWER) {
$case_func = 'strtolower';
} else {
$case_func = 'strtoupper';
}
} else {
$case_func = 'strval';
}
$count = @mysqli_num_fields($resource);
$res = array();
if ($mode) {
$res['num_fields'] = $count;
}
$db->loadModule('Datatype', null, true);
for ($i = 0; $i < $count; $i++) {
$tmp = @mysqli_fetch_field($resource);
$flags = '';
foreach ($this->flags as $const => $means) {
if ($tmp->flags & $const) {
$flags.= $means . ' ';
}
}
if ($tmp->def) {
$flags.= 'default_' . rawurlencode($tmp->def);
}
$flags = trim($flags);
$res[$i] = array(
'table' => $case_func($tmp->table),
'name' => $case_func($tmp->name),
'type' => isset($this->types[$tmp->type])
? $this->types[$tmp->type] : 'unknown',
// http://bugs.php.net/?id=36579
'length' => $tmp->length,
'flags' => $flags,
);
$mdb2type_info = $db->datatype->mapNativeDatatype($res[$i]);
if (PEAR::isError($mdb2type_info)) {
return $mdb2type_info;
}
$res[$i]['mdb2type'] = $mdb2type_info[0][0];
if ($mode & MDB2_TABLEINFO_ORDER) {
$res['order'][$res[$i]['name']] = $i;
}
if ($mode & MDB2_TABLEINFO_ORDERTABLE) {
$res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i;
}
}
return $res;
}
}
?>

@ -1,574 +0,0 @@
<?php
// +----------------------------------------------------------------------+
// | PHP versions 4 and 5 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1998-2008 Manuel Lemos, Tomas V.V.Cox, |
// | Stig. S. Bakken, Lukas Smith |
// | All rights reserved. |
// +----------------------------------------------------------------------+
// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB |
// | API as well as database abstraction for PHP applications. |
// | This LICENSE is in the BSD license style. |
// | |
// | Redistribution and use in source and binary forms, with or without |
// | modification, are permitted provided that the following conditions |
// | are met: |
// | |
// | Redistributions of source code must retain the above copyright |
// | notice, this list of conditions and the following disclaimer. |
// | |
// | Redistributions in binary form must reproduce the above copyright |
// | notice, this list of conditions and the following disclaimer in the |
// | documentation and/or other materials provided with the distribution. |
// | |
// | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken, |
// | Lukas Smith nor the names of his contributors may be used to endorse |
// | or promote products derived from this software without specific prior|
// | written permission. |
// | |
// | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
// | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
// | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
// | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE |
// | REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, |
// | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
// | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS|
// | OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED |
// | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
// | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY|
// | WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
// | POSSIBILITY OF SUCH DAMAGE. |
// +----------------------------------------------------------------------+
// | Authors: Paul Cooper <pgc@ucecom.com> |
// | Lorenzo Alberton <l.alberton@quipo.it> |
// +----------------------------------------------------------------------+
//
// $Id: pgsql.php 295587 2010-02-28 17:16:38Z quipo $
require_once 'MDB2/Driver/Reverse/Common.php';
/**
* MDB2 PostGreSQL driver for the schema reverse engineering module
*
* @package MDB2
* @category Database
* @author Paul Cooper <pgc@ucecom.com>
* @author Lorenzo Alberton <l.alberton@quipo.it>
*/
class MDB2_Driver_Reverse_pgsql extends MDB2_Driver_Reverse_Common
{
// {{{ getTableFieldDefinition()
/**
* Get the structure of a field into an array
*
* @param string $table_name name of table that should be used in method
* @param string $field_name name of field that should be used in method
* @return mixed data array on success, a MDB2 error on failure
* @access public
*/
function getTableFieldDefinition($table_name, $field_name)
{
$db = $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
$result = $db->loadModule('Datatype', null, true);
if (PEAR::isError($result)) {
return $result;
}
list($schema, $table) = $this->splitTableSchema($table_name);
$query = "SELECT a.attname AS name,
t.typname AS type,
CASE a.attlen
WHEN -1 THEN
CASE t.typname
WHEN 'numeric' THEN (a.atttypmod / 65536)
WHEN 'decimal' THEN (a.atttypmod / 65536)
WHEN 'money' THEN (a.atttypmod / 65536)
ELSE CASE a.atttypmod
WHEN -1 THEN NULL
ELSE a.atttypmod - 4
END
END
ELSE a.attlen
END AS length,
CASE t.typname
WHEN 'numeric' THEN (a.atttypmod % 65536) - 4
WHEN 'decimal' THEN (a.atttypmod % 65536) - 4
WHEN 'money' THEN (a.atttypmod % 65536) - 4
ELSE 0
END AS scale,
a.attnotnull,
a.atttypmod,
a.atthasdef,
(SELECT substring(pg_get_expr(d.adbin, d.adrelid) for 128)
FROM pg_attrdef d
WHERE d.adrelid = a.attrelid
AND d.adnum = a.attnum
AND a.atthasdef
) as default
FROM pg_attribute a,
pg_class c,
pg_type t
WHERE c.relname = ".$db->quote($table, 'text')."
AND a.atttypid = t.oid
AND c.oid = a.attrelid
AND NOT a.attisdropped
AND a.attnum > 0
AND a.attname = ".$db->quote($field_name, 'text')."
ORDER BY a.attnum";
$column = $db->queryRow($query, null, MDB2_FETCHMODE_ASSOC);
if (PEAR::isError($column)) {
return $column;
}
if (empty($column)) {
return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
'it was not specified an existing table column', __FUNCTION__);
}
$column = array_change_key_case($column, CASE_LOWER);
$mapped_datatype = $db->datatype->mapNativeDatatype($column);
if (PEAR::isError($mapped_datatype)) {
return $mapped_datatype;
}
list($types, $length, $unsigned, $fixed) = $mapped_datatype;
$notnull = false;
if (!empty($column['attnotnull']) && $column['attnotnull'] == 't') {
$notnull = true;
}
$default = null;
if ($column['atthasdef'] === 't'
&& strpos($column['default'], 'NULL') !== 0
&& !preg_match("/nextval\('([^']+)'/", $column['default'])
) {
$pattern = '/^\'(.*)\'::[\w ]+$/i';
$default = $column['default'];#substr($column['adsrc'], 1, -1);
if ((null === $default) && $notnull) {
$default = '';
} elseif (!empty($default) && preg_match($pattern, $default)) {
//remove data type cast
$default = preg_replace ($pattern, '\\1', $default);
}
}
$autoincrement = false;
if (preg_match("/nextval\('([^']+)'/", $column['default'], $nextvals)) {
$autoincrement = true;
}
$definition[0] = array('notnull' => $notnull, 'nativetype' => $column['type']);
if (null !== $length) {
$definition[0]['length'] = $length;
}
if (null !== $unsigned) {
$definition[0]['unsigned'] = $unsigned;
}
if (null !== $fixed) {
$definition[0]['fixed'] = $fixed;
}
if ($default !== false) {
$definition[0]['default'] = $default;
}
if ($autoincrement !== false) {
$definition[0]['autoincrement'] = $autoincrement;
}
foreach ($types as $key => $type) {
$definition[$key] = $definition[0];
if ($type == 'clob' || $type == 'blob') {
unset($definition[$key]['default']);
}
$definition[$key]['type'] = $type;
$definition[$key]['mdb2type'] = $type;
}
return $definition;
}
// }}}
// {{{ getTableIndexDefinition()
/**
* Get the structure of an index into an array
*
* @param string $table_name name of table that should be used in method
* @param string $index_name name of index that should be used in method
* @return mixed data array on success, a MDB2 error on failure
* @access public
*/
function getTableIndexDefinition($table_name, $index_name)
{
$db = $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
list($schema, $table) = $this->splitTableSchema($table_name);
$query = 'SELECT relname, indkey FROM pg_index, pg_class';
$query.= ' WHERE pg_class.oid = pg_index.indexrelid';
$query.= " AND indisunique != 't' AND indisprimary != 't'";
$query.= ' AND pg_class.relname = %s';
$index_name_mdb2 = $db->getIndexName($index_name);
$row = $db->queryRow(sprintf($query, $db->quote($index_name_mdb2, 'text')), null, MDB2_FETCHMODE_ASSOC);
if (PEAR::isError($row) || empty($row)) {
// fallback to the given $index_name, without transformation
$row = $db->queryRow(sprintf($query, $db->quote($index_name, 'text')), null, MDB2_FETCHMODE_ASSOC);
}
if (PEAR::isError($row)) {
return $row;
}
if (empty($row)) {
return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
'it was not specified an existing table index', __FUNCTION__);
}
$row = array_change_key_case($row, CASE_LOWER);
$db->loadModule('Manager', null, true);
$columns = $db->manager->listTableFields($table_name);
$definition = array();
$index_column_numbers = explode(' ', $row['indkey']);
$colpos = 1;
foreach ($index_column_numbers as $number) {
$definition['fields'][$columns[($number - 1)]] = array(
'position' => $colpos++,
'sorting' => 'ascending',
);
}
return $definition;
}
// }}}
// {{{ getTableConstraintDefinition()
/**
* Get the structure of a constraint into an array
*
* @param string $table_name name of table that should be used in method
* @param string $constraint_name name of constraint that should be used in method
* @return mixed data array on success, a MDB2 error on failure
* @access public
*/
function getTableConstraintDefinition($table_name, $constraint_name)
{
$db = $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
list($schema, $table) = $this->splitTableSchema($table_name);
$query = "SELECT c.oid,
c.conname AS constraint_name,
CASE WHEN c.contype = 'c' THEN 1 ELSE 0 END AS \"check\",
CASE WHEN c.contype = 'f' THEN 1 ELSE 0 END AS \"foreign\",
CASE WHEN c.contype = 'p' THEN 1 ELSE 0 END AS \"primary\",
CASE WHEN c.contype = 'u' THEN 1 ELSE 0 END AS \"unique\",
CASE WHEN c.condeferrable = 'f' THEN 0 ELSE 1 END AS deferrable,
CASE WHEN c.condeferred = 'f' THEN 0 ELSE 1 END AS initiallydeferred,
--array_to_string(c.conkey, ' ') AS constraint_key,
t.relname AS table_name,
t2.relname AS references_table,
CASE confupdtype
WHEN 'a' THEN 'NO ACTION'
WHEN 'r' THEN 'RESTRICT'
WHEN 'c' THEN 'CASCADE'
WHEN 'n' THEN 'SET NULL'
WHEN 'd' THEN 'SET DEFAULT'
END AS onupdate,
CASE confdeltype
WHEN 'a' THEN 'NO ACTION'
WHEN 'r' THEN 'RESTRICT'
WHEN 'c' THEN 'CASCADE'
WHEN 'n' THEN 'SET NULL'
WHEN 'd' THEN 'SET DEFAULT'
END AS ondelete,
CASE confmatchtype
WHEN 'u' THEN 'UNSPECIFIED'
WHEN 'f' THEN 'FULL'
WHEN 'p' THEN 'PARTIAL'
END AS match,
--array_to_string(c.confkey, ' ') AS fk_constraint_key,
consrc
FROM pg_constraint c
LEFT JOIN pg_class t ON c.conrelid = t.oid
LEFT JOIN pg_class t2 ON c.confrelid = t2.oid
WHERE c.conname = %s
AND t.relname = " . $db->quote($table, 'text');
$constraint_name_mdb2 = $db->getIndexName($constraint_name);
$row = $db->queryRow(sprintf($query, $db->quote($constraint_name_mdb2, 'text')), null, MDB2_FETCHMODE_ASSOC);
if (PEAR::isError($row) || empty($row)) {
// fallback to the given $index_name, without transformation
$constraint_name_mdb2 = $constraint_name;
$row = $db->queryRow(sprintf($query, $db->quote($constraint_name_mdb2, 'text')), null, MDB2_FETCHMODE_ASSOC);
}
if (PEAR::isError($row)) {
return $row;
}
$uniqueIndex = false;
if (empty($row)) {
// We might be looking for a UNIQUE index that was not created
// as a constraint but should be treated as such.
$query = 'SELECT relname AS constraint_name,
indkey,
0 AS "check",
0 AS "foreign",
0 AS "primary",
1 AS "unique",
0 AS deferrable,
0 AS initiallydeferred,
NULL AS references_table,
NULL AS onupdate,
NULL AS ondelete,
NULL AS match
FROM pg_index, pg_class
WHERE pg_class.oid = pg_index.indexrelid
AND indisunique = \'t\'
AND pg_class.relname = %s';
$constraint_name_mdb2 = $db->getIndexName($constraint_name);
$row = $db->queryRow(sprintf($query, $db->quote($constraint_name_mdb2, 'text')), null, MDB2_FETCHMODE_ASSOC);
if (PEAR::isError($row) || empty($row)) {
// fallback to the given $index_name, without transformation
$constraint_name_mdb2 = $constraint_name;
$row = $db->queryRow(sprintf($query, $db->quote($constraint_name_mdb2, 'text')), null, MDB2_FETCHMODE_ASSOC);
}
if (PEAR::isError($row)) {
return $row;
}
if (empty($row)) {
return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
$constraint_name . ' is not an existing table constraint', __FUNCTION__);
}
$uniqueIndex = true;
}
$row = array_change_key_case($row, CASE_LOWER);
$definition = array(
'primary' => (boolean)$row['primary'],
'unique' => (boolean)$row['unique'],
'foreign' => (boolean)$row['foreign'],
'check' => (boolean)$row['check'],
'fields' => array(),
'references' => array(
'table' => $row['references_table'],
'fields' => array(),
),
'deferrable' => (boolean)$row['deferrable'],
'initiallydeferred' => (boolean)$row['initiallydeferred'],
'onupdate' => $row['onupdate'],
'ondelete' => $row['ondelete'],
'match' => $row['match'],
);
if ($uniqueIndex) {
$db->loadModule('Manager', null, true);
$columns = $db->manager->listTableFields($table_name);
$index_column_numbers = explode(' ', $row['indkey']);
$colpos = 1;
foreach ($index_column_numbers as $number) {
$definition['fields'][$columns[($number - 1)]] = array(
'position' => $colpos++,
'sorting' => 'ascending',
);
}
return $definition;
}
$query = 'SELECT a.attname
FROM pg_constraint c
LEFT JOIN pg_class t ON c.conrelid = t.oid
LEFT JOIN pg_attribute a ON a.attrelid = t.oid AND a.attnum = ANY(c.conkey)
WHERE c.conname = %s
AND t.relname = ' . $db->quote($table, 'text');
$fields = $db->queryCol(sprintf($query, $db->quote($constraint_name_mdb2, 'text')), null);
if (PEAR::isError($fields)) {
return $fields;
}
$colpos = 1;
foreach ($fields as $field) {
$definition['fields'][$field] = array(
'position' => $colpos++,
'sorting' => 'ascending',
);
}
if ($definition['foreign']) {
$query = 'SELECT a.attname
FROM pg_constraint c
LEFT JOIN pg_class t ON c.confrelid = t.oid
LEFT JOIN pg_attribute a ON a.attrelid = t.oid AND a.attnum = ANY(c.confkey)
WHERE c.conname = %s
AND t.relname = ' . $db->quote($definition['references']['table'], 'text');
$foreign_fields = $db->queryCol(sprintf($query, $db->quote($constraint_name_mdb2, 'text')), null);
if (PEAR::isError($foreign_fields)) {
return $foreign_fields;
}
$colpos = 1;
foreach ($foreign_fields as $foreign_field) {
$definition['references']['fields'][$foreign_field] = array(
'position' => $colpos++,
);
}
}
if ($definition['check']) {
$check_def = $db->queryOne("SELECT pg_get_constraintdef(" . $row['oid'] . ", 't')");
// ...
}
return $definition;
}
// }}}
// {{{ getTriggerDefinition()
/**
* Get the structure of a trigger into an array
*
* EXPERIMENTAL
*
* WARNING: this function is experimental and may change the returned value
* at any time until labelled as non-experimental
*
* @param string $trigger name of trigger that should be used in method
* @return mixed data array on success, a MDB2 error on failure
* @access public
*
* @TODO: add support for plsql functions and functions with args
*/
function getTriggerDefinition($trigger)
{
$db = $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
$query = "SELECT trg.tgname AS trigger_name,
tbl.relname AS table_name,
CASE
WHEN p.proname IS NOT NULL THEN 'EXECUTE PROCEDURE ' || p.proname || '();'
ELSE ''
END AS trigger_body,
CASE trg.tgtype & cast(2 as int2)
WHEN 0 THEN 'AFTER'
ELSE 'BEFORE'
END AS trigger_type,
CASE trg.tgtype & cast(28 as int2)
WHEN 16 THEN 'UPDATE'
WHEN 8 THEN 'DELETE'
WHEN 4 THEN 'INSERT'
WHEN 20 THEN 'INSERT, UPDATE'
WHEN 28 THEN 'INSERT, UPDATE, DELETE'
WHEN 24 THEN 'UPDATE, DELETE'
WHEN 12 THEN 'INSERT, DELETE'
END AS trigger_event,
CASE trg.tgenabled
WHEN 'O' THEN 't'
ELSE trg.tgenabled
END AS trigger_enabled,
obj_description(trg.oid, 'pg_trigger') AS trigger_comment
FROM pg_trigger trg,
pg_class tbl,
pg_proc p
WHERE trg.tgrelid = tbl.oid
AND trg.tgfoid = p.oid
AND trg.tgname = ". $db->quote($trigger, 'text');
$types = array(
'trigger_name' => 'text',
'table_name' => 'text',
'trigger_body' => 'text',
'trigger_type' => 'text',
'trigger_event' => 'text',
'trigger_comment' => 'text',
'trigger_enabled' => 'boolean',
);
return $db->queryRow($query, $types, MDB2_FETCHMODE_ASSOC);
}
// }}}
// {{{ tableInfo()
/**
* Returns information about a table or a result set
*
* NOTE: only supports 'table' and 'flags' if <var>$result</var>
* is a table name.
*
* @param object|string $result MDB2_result object from a query or a
* string containing the name of a table.
* While this also accepts a query result
* resource identifier, this behavior is
* deprecated.
* @param int $mode a valid tableInfo mode
*
* @return array an associative array with the information requested.
* A MDB2_Error object on failure.
*
* @see MDB2_Driver_Common::tableInfo()
*/
function tableInfo($result, $mode = null)
{
if (is_string($result)) {
return parent::tableInfo($result, $mode);
}
$db = $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
$resource = MDB2::isResultCommon($result) ? $result->getResource() : $result;
if (!is_resource($resource)) {
return $db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null,
'Could not generate result resource', __FUNCTION__);
}
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
if ($db->options['field_case'] == CASE_LOWER) {
$case_func = 'strtolower';
} else {
$case_func = 'strtoupper';
}
} else {
$case_func = 'strval';
}
$count = @pg_num_fields($resource);
$res = array();
if ($mode) {
$res['num_fields'] = $count;
}
$db->loadModule('Datatype', null, true);
for ($i = 0; $i < $count; $i++) {
$res[$i] = array(
'table' => function_exists('pg_field_table') ? @pg_field_table($resource, $i) : '',
'name' => $case_func(@pg_field_name($resource, $i)),
'type' => @pg_field_type($resource, $i),
'length' => @pg_field_size($resource, $i),
'flags' => '',
);
$mdb2type_info = $db->datatype->mapNativeDatatype($res[$i]);
if (PEAR::isError($mdb2type_info)) {
return $mdb2type_info;
}
$res[$i]['mdb2type'] = $mdb2type_info[0][0];
if ($mode & MDB2_TABLEINFO_ORDER) {
$res['order'][$res[$i]['name']] = $i;
}
if ($mode & MDB2_TABLEINFO_ORDERTABLE) {
$res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i;
}
}
return $res;
}
}
?>

@ -1,609 +0,0 @@
<?php
// +----------------------------------------------------------------------+
// | PHP versions 4 and 5 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1998-2007 Manuel Lemos, Tomas V.V.Cox, |
// | Stig. S. Bakken, Lukas Smith, Lorenzo Alberton |
// | All rights reserved. |
// +----------------------------------------------------------------------+
// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB |
// | API as well as database abstraction for PHP applications. |
// | This LICENSE is in the BSD license style. |
// | |
// | Redistribution and use in source and binary forms, with or without |
// | modification, are permitted provided that the following conditions |
// | are met: |
// | |
// | Redistributions of source code must retain the above copyright |
// | notice, this list of conditions and the following disclaimer. |
// | |
// | Redistributions in binary form must reproduce the above copyright |
// | notice, this list of conditions and the following disclaimer in the |
// | documentation and/or other materials provided with the distribution. |
// | |
// | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken, |
// | Lukas Smith nor the names of his contributors may be used to endorse |
// | or promote products derived from this software without specific prior|
// | written permission. |
// | |
// | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
// | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
// | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
// | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE |
// | REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, |
// | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
// | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS|
// | OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED |
// | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
// | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY|
// | WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
// | POSSIBILITY OF SUCH DAMAGE. |
// +----------------------------------------------------------------------+
// | Authors: Lukas Smith <smith@pooteeweet.org> |
// | Lorenzo Alberton <l.alberton@quipo.it> |
// +----------------------------------------------------------------------+
//
// $Id: sqlite.php 295587 2010-02-28 17:16:38Z quipo $
//
require_once 'MDB2/Driver/Reverse/Common.php';
/**
* MDB2 SQlite driver for the schema reverse engineering module
*
* @package MDB2
* @category Database
* @author Lukas Smith <smith@pooteeweet.org>
*/
class MDB2_Driver_Reverse_sqlite extends MDB2_Driver_Reverse_Common
{
/**
* Remove SQL comments from the field definition
*
* @access private
*/
function _removeComments($sql) {
$lines = explode("\n", $sql);
foreach ($lines as $k => $line) {
$pieces = explode('--', $line);
if (count($pieces) > 1 && (substr_count($pieces[0], '\'') % 2) == 0) {
$lines[$k] = substr($line, 0, strpos($line, '--'));
}
}
return implode("\n", $lines);
}
/**
*
*/
function _getTableColumns($sql)
{
$db = $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
$start_pos = strpos($sql, '(');
$end_pos = strrpos($sql, ')');
$column_def = substr($sql, $start_pos+1, $end_pos-$start_pos-1);
// replace the decimal length-places-separator with a colon
$column_def = preg_replace('/(\d),(\d)/', '\1:\2', $column_def);
$column_def = $this->_removeComments($column_def);
$column_sql = explode(',', $column_def);
$columns = array();
$count = count($column_sql);
if ($count == 0) {
return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
'unexpected empty table column definition list', __FUNCTION__);
}
$regexp = '/^\s*([^\s]+) +(CHAR|VARCHAR|VARCHAR2|TEXT|BOOLEAN|SMALLINT|INT|INTEGER|DECIMAL|TINYINT|BIGINT|DOUBLE|FLOAT|DATETIME|DATE|TIME|LONGTEXT|LONGBLOB)( ?\(([1-9][0-9]*)(:([1-9][0-9]*))?\))?( NULL| NOT NULL)?( UNSIGNED)?( NULL| NOT NULL)?( PRIMARY KEY)?( DEFAULT (\'[^\']*\'|[^ ]+))?( NULL| NOT NULL)?( PRIMARY KEY)?(\s*\-\-.*)?$/i';
$regexp2 = '/^\s*([^ ]+) +(PRIMARY|UNIQUE|CHECK)$/i';
for ($i=0, $j=0; $i<$count; ++$i) {
if (!preg_match($regexp, trim($column_sql[$i]), $matches)) {
if (!preg_match($regexp2, trim($column_sql[$i]))) {
continue;
}
return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
'unexpected table column SQL definition: "'.$column_sql[$i].'"', __FUNCTION__);
}
$columns[$j]['name'] = trim($matches[1], implode('', $db->identifier_quoting));
$columns[$j]['type'] = strtolower($matches[2]);
if (isset($matches[4]) && strlen($matches[4])) {
$columns[$j]['length'] = $matches[4];
}
if (isset($matches[6]) && strlen($matches[6])) {
$columns[$j]['decimal'] = $matches[6];
}
if (isset($matches[8]) && strlen($matches[8])) {
$columns[$j]['unsigned'] = true;
}
if (isset($matches[9]) && strlen($matches[9])) {
$columns[$j]['autoincrement'] = true;
}
if (isset($matches[12]) && strlen($matches[12])) {
$default = $matches[12];
if (strlen($default) && $default[0]=="'") {
$default = str_replace("''", "'", substr($default, 1, strlen($default)-2));
}
if ($default === 'NULL') {
$default = null;
}
$columns[$j]['default'] = $default;
}
if (isset($matches[7]) && strlen($matches[7])) {
$columns[$j]['notnull'] = ($matches[7] === ' NOT NULL');
} else if (isset($matches[9]) && strlen($matches[9])) {
$columns[$j]['notnull'] = ($matches[9] === ' NOT NULL');
} else if (isset($matches[13]) && strlen($matches[13])) {
$columns[$j]['notnull'] = ($matches[13] === ' NOT NULL');
}
++$j;
}
return $columns;
}
// {{{ getTableFieldDefinition()
/**
* Get the stucture of a field into an array
*
* @param string $table_name name of table that should be used in method
* @param string $field_name name of field that should be used in method
* @return mixed data array on success, a MDB2 error on failure.
* The returned array contains an array for each field definition,
* with (some of) these indices:
* [notnull] [nativetype] [length] [fixed] [default] [type] [mdb2type]
* @access public
*/
function getTableFieldDefinition($table_name, $field_name)
{
$db = $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
list($schema, $table) = $this->splitTableSchema($table_name);
$result = $db->loadModule('Datatype', null, true);
if (PEAR::isError($result)) {
return $result;
}
$query = "SELECT sql FROM sqlite_master WHERE type='table' AND ";
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
$query.= 'LOWER(name)='.$db->quote(strtolower($table), 'text');
} else {
$query.= 'name='.$db->quote($table, 'text');
}
$sql = $db->queryOne($query);
if (PEAR::isError($sql)) {
return $sql;
}
$columns = $this->_getTableColumns($sql);
foreach ($columns as $column) {
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
if ($db->options['field_case'] == CASE_LOWER) {
$column['name'] = strtolower($column['name']);
} else {
$column['name'] = strtoupper($column['name']);
}
} else {
$column = array_change_key_case($column, $db->options['field_case']);
}
if ($field_name == $column['name']) {
$mapped_datatype = $db->datatype->mapNativeDatatype($column);
if (PEAR::isError($mapped_datatype)) {
return $mapped_datatype;
}
list($types, $length, $unsigned, $fixed) = $mapped_datatype;
$notnull = false;
if (!empty($column['notnull'])) {
$notnull = $column['notnull'];
}
$default = false;
if (array_key_exists('default', $column)) {
$default = $column['default'];
if ((null === $default) && $notnull) {
$default = '';
}
}
$autoincrement = false;
if (!empty($column['autoincrement'])) {
$autoincrement = true;
}
$definition[0] = array(
'notnull' => $notnull,
'nativetype' => preg_replace('/^([a-z]+)[^a-z].*/i', '\\1', $column['type'])
);
if (null !== $length) {
$definition[0]['length'] = $length;
}
if (null !== $unsigned) {
$definition[0]['unsigned'] = $unsigned;
}
if (null !== $fixed) {
$definition[0]['fixed'] = $fixed;
}
if ($default !== false) {
$definition[0]['default'] = $default;
}
if ($autoincrement !== false) {
$definition[0]['autoincrement'] = $autoincrement;
}
foreach ($types as $key => $type) {
$definition[$key] = $definition[0];
if ($type == 'clob' || $type == 'blob') {
unset($definition[$key]['default']);
}
$definition[$key]['type'] = $type;
$definition[$key]['mdb2type'] = $type;
}
return $definition;
}
}
return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
'it was not specified an existing table column', __FUNCTION__);
}
// }}}
// {{{ getTableIndexDefinition()
/**
* Get the stucture of an index into an array
*
* @param string $table_name name of table that should be used in method
* @param string $index_name name of index that should be used in method
* @return mixed data array on success, a MDB2 error on failure
* @access public
*/
function getTableIndexDefinition($table_name, $index_name)
{
$db = $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
list($schema, $table) = $this->splitTableSchema($table_name);
$query = "SELECT sql FROM sqlite_master WHERE type='index' AND ";
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
$query.= 'LOWER(name)=%s AND LOWER(tbl_name)=' . $db->quote(strtolower($table), 'text');
} else {
$query.= 'name=%s AND tbl_name=' . $db->quote($table, 'text');
}
$query.= ' AND sql NOT NULL ORDER BY name';
$index_name_mdb2 = $db->getIndexName($index_name);
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
$qry = sprintf($query, $db->quote(strtolower($index_name_mdb2), 'text'));
} else {
$qry = sprintf($query, $db->quote($index_name_mdb2, 'text'));
}
$sql = $db->queryOne($qry, 'text');
if (PEAR::isError($sql) || empty($sql)) {
// fallback to the given $index_name, without transformation
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
$qry = sprintf($query, $db->quote(strtolower($index_name), 'text'));
} else {
$qry = sprintf($query, $db->quote($index_name, 'text'));
}
$sql = $db->queryOne($qry, 'text');
}
if (PEAR::isError($sql)) {
return $sql;
}
if (!$sql) {
return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
'it was not specified an existing table index', __FUNCTION__);
}
$sql = strtolower($sql);
$start_pos = strpos($sql, '(');
$end_pos = strrpos($sql, ')');
$column_names = substr($sql, $start_pos+1, $end_pos-$start_pos-1);
$column_names = explode(',', $column_names);
if (preg_match("/^create unique/", $sql)) {
return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
'it was not specified an existing table index', __FUNCTION__);
}
$definition = array();
$count = count($column_names);
for ($i=0; $i<$count; ++$i) {
$column_name = strtok($column_names[$i], ' ');
$collation = strtok(' ');
$definition['fields'][$column_name] = array(
'position' => $i+1
);
if (!empty($collation)) {
$definition['fields'][$column_name]['sorting'] =
($collation=='ASC' ? 'ascending' : 'descending');
}
}
if (empty($definition['fields'])) {
return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
'it was not specified an existing table index', __FUNCTION__);
}
return $definition;
}
// }}}
// {{{ getTableConstraintDefinition()
/**
* Get the stucture of a constraint into an array
*
* @param string $table_name name of table that should be used in method
* @param string $constraint_name name of constraint that should be used in method
* @return mixed data array on success, a MDB2 error on failure
* @access public
*/
function getTableConstraintDefinition($table_name, $constraint_name)
{
$db = $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
list($schema, $table) = $this->splitTableSchema($table_name);
$query = "SELECT sql FROM sqlite_master WHERE type='index' AND ";
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
$query.= 'LOWER(name)=%s AND LOWER(tbl_name)=' . $db->quote(strtolower($table), 'text');
} else {
$query.= 'name=%s AND tbl_name=' . $db->quote($table, 'text');
}
$query.= ' AND sql NOT NULL ORDER BY name';
$constraint_name_mdb2 = $db->getIndexName($constraint_name);
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
$qry = sprintf($query, $db->quote(strtolower($constraint_name_mdb2), 'text'));
} else {
$qry = sprintf($query, $db->quote($constraint_name_mdb2, 'text'));
}
$sql = $db->queryOne($qry, 'text');
if (PEAR::isError($sql) || empty($sql)) {
// fallback to the given $index_name, without transformation
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
$qry = sprintf($query, $db->quote(strtolower($constraint_name), 'text'));
} else {
$qry = sprintf($query, $db->quote($constraint_name, 'text'));
}
$sql = $db->queryOne($qry, 'text');
}
if (PEAR::isError($sql)) {
return $sql;
}
//default values, eventually overridden
$definition = array(
'primary' => false,
'unique' => false,
'foreign' => false,
'check' => false,
'fields' => array(),
'references' => array(
'table' => '',
'fields' => array(),
),
'onupdate' => '',
'ondelete' => '',
'match' => '',
'deferrable' => false,
'initiallydeferred' => false,
);
if (!$sql) {
$query = "SELECT sql FROM sqlite_master WHERE type='table' AND ";
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
$query.= 'LOWER(name)='.$db->quote(strtolower($table), 'text');
} else {
$query.= 'name='.$db->quote($table, 'text');
}
$query.= " AND sql NOT NULL ORDER BY name";
$sql = $db->queryOne($query, 'text');
if (PEAR::isError($sql)) {
return $sql;
}
if ($constraint_name == 'primary') {
// search in table definition for PRIMARY KEYs
if (preg_match("/\bPRIMARY\s+KEY\b\s*\(([^)]+)/i", $sql, $tmp)) {
$definition['primary'] = true;
$definition['fields'] = array();
$column_names = explode(',', $tmp[1]);
$colpos = 1;
foreach ($column_names as $column_name) {
$definition['fields'][trim($column_name)] = array(
'position' => $colpos++
);
}
return $definition;
}
if (preg_match("/\"([^\"]+)\"[^\,\"]+\bPRIMARY\s+KEY\b[^\,\)]*/i", $sql, $tmp)) {
$definition['primary'] = true;
$definition['fields'] = array();
$column_names = explode(',', $tmp[1]);
$colpos = 1;
foreach ($column_names as $column_name) {
$definition['fields'][trim($column_name)] = array(
'position' => $colpos++
);
}
return $definition;
}
} else {
// search in table definition for FOREIGN KEYs
$pattern = "/\bCONSTRAINT\b\s+%s\s+
\bFOREIGN\s+KEY\b\s*\(([^\)]+)\)\s*
\bREFERENCES\b\s+([^\s]+)\s*\(([^\)]+)\)\s*
(?:\bMATCH\s*([^\s]+))?\s*
(?:\bON\s+UPDATE\s+([^\s,\)]+))?\s*
(?:\bON\s+DELETE\s+([^\s,\)]+))?\s*
/imsx";
$found_fk = false;
if (preg_match(sprintf($pattern, $constraint_name_mdb2), $sql, $tmp)) {
$found_fk = true;
} elseif (preg_match(sprintf($pattern, $constraint_name), $sql, $tmp)) {
$found_fk = true;
}
if ($found_fk) {
$definition['foreign'] = true;
$definition['match'] = 'SIMPLE';
$definition['onupdate'] = 'NO ACTION';
$definition['ondelete'] = 'NO ACTION';
$definition['references']['table'] = $tmp[2];
$column_names = explode(',', $tmp[1]);
$colpos = 1;
foreach ($column_names as $column_name) {
$definition['fields'][trim($column_name)] = array(
'position' => $colpos++
);
}
$referenced_cols = explode(',', $tmp[3]);
$colpos = 1;
foreach ($referenced_cols as $column_name) {
$definition['references']['fields'][trim($column_name)] = array(
'position' => $colpos++
);
}
if (isset($tmp[4])) {
$definition['match'] = $tmp[4];
}
if (isset($tmp[5])) {
$definition['onupdate'] = $tmp[5];
}
if (isset($tmp[6])) {
$definition['ondelete'] = $tmp[6];
}
return $definition;
}
}
$sql = false;
}
if (!$sql) {
return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
$constraint_name . ' is not an existing table constraint', __FUNCTION__);
}
$sql = strtolower($sql);
$start_pos = strpos($sql, '(');
$end_pos = strrpos($sql, ')');
$column_names = substr($sql, $start_pos+1, $end_pos-$start_pos-1);
$column_names = explode(',', $column_names);
if (!preg_match("/^create unique/", $sql)) {
return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
$constraint_name . ' is not an existing table constraint', __FUNCTION__);
}
$definition['unique'] = true;
$count = count($column_names);
for ($i=0; $i<$count; ++$i) {
$column_name = strtok($column_names[$i]," ");
$collation = strtok(" ");
$definition['fields'][$column_name] = array(
'position' => $i+1
);
if (!empty($collation)) {
$definition['fields'][$column_name]['sorting'] =
($collation=='ASC' ? 'ascending' : 'descending');
}
}
if (empty($definition['fields'])) {
return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
$constraint_name . ' is not an existing table constraint', __FUNCTION__);
}
return $definition;
}
// }}}
// {{{ getTriggerDefinition()
/**
* Get the structure of a trigger into an array
*
* EXPERIMENTAL
*
* WARNING: this function is experimental and may change the returned value
* at any time until labelled as non-experimental
*
* @param string $trigger name of trigger that should be used in method
* @return mixed data array on success, a MDB2 error on failure
* @access public
*/
function getTriggerDefinition($trigger)
{
$db = $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
$query = "SELECT name as trigger_name,
tbl_name AS table_name,
sql AS trigger_body,
NULL AS trigger_type,
NULL AS trigger_event,
NULL AS trigger_comment,
1 AS trigger_enabled
FROM sqlite_master
WHERE type='trigger'";
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
$query.= ' AND LOWER(name)='.$db->quote(strtolower($trigger), 'text');
} else {
$query.= ' AND name='.$db->quote($trigger, 'text');
}
$types = array(
'trigger_name' => 'text',
'table_name' => 'text',
'trigger_body' => 'text',
'trigger_type' => 'text',
'trigger_event' => 'text',
'trigger_comment' => 'text',
'trigger_enabled' => 'boolean',
);
$def = $db->queryRow($query, $types, MDB2_FETCHMODE_ASSOC);
if (PEAR::isError($def)) {
return $def;
}
if (empty($def)) {
return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
'it was not specified an existing trigger', __FUNCTION__);
}
if (preg_match("/^create\s+(?:temp|temporary)?trigger\s+(?:if\s+not\s+exists\s+)?.*(before|after)?\s+(insert|update|delete)/Uims", $def['trigger_body'], $tmp)) {
$def['trigger_type'] = strtoupper($tmp[1]);
$def['trigger_event'] = strtoupper($tmp[2]);
}
return $def;
}
// }}}
// {{{ tableInfo()
/**
* Returns information about a table
*
* @param string $result a string containing the name of a table
* @param int $mode a valid tableInfo mode
*
* @return array an associative array with the information requested.
* A MDB2_Error object on failure.
*
* @see MDB2_Driver_Common::tableInfo()
* @since Method available since Release 1.7.0
*/
function tableInfo($result, $mode = null)
{
if (is_string($result)) {
return parent::tableInfo($result, $mode);
}
$db = $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
return $db->raiseError(MDB2_ERROR_NOT_CAPABLE, null, null,
'This DBMS can not obtain tableInfo from result sets', __FUNCTION__);
}
}
?>

@ -1,653 +0,0 @@
<?php
// +----------------------------------------------------------------------+
// | PHP versions 4 and 5 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1998-2007 Manuel Lemos, Tomas V.V.Cox, |
// | Stig. S. Bakken, Lukas Smith, Frank M. Kromann, Lorenzo Alberton |
// | All rights reserved. |
// +----------------------------------------------------------------------+
// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB |
// | API as well as database abstraction for PHP applications. |
// | This LICENSE is in the BSD license style. |
// | |
// | Redistribution and use in source and binary forms, with or without |
// | modification, are permitted provided that the following conditions |
// | are met: |
// | |
// | Redistributions of source code must retain the above copyright |
// | notice, this list of conditions and the following disclaimer. |
// | |
// | Redistributions in binary form must reproduce the above copyright |
// | notice, this list of conditions and the following disclaimer in the |
// | documentation and/or other materials provided with the distribution. |
// | |
// | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken, |
// | Lukas Smith nor the names of his contributors may be used to endorse |
// | or promote products derived from this software without specific prior|
// | written permission. |
// | |
// | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
// | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
// | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
// | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE |
// | REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, |
// | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
// | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS|
// | OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED |
// | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
// | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY|
// | WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
// | POSSIBILITY OF SUCH DAMAGE. |
// +----------------------------------------------------------------------+
// | Authors: Lukas Smith <smith@pooteeweet.org> |
// | Lorenzo Alberton <l.alberton@quipo.it> |
// +----------------------------------------------------------------------+
require_once 'MDB2/Driver/Reverse/Common.php';
/**
* MDB2 MSSQL driver for the schema reverse engineering module
*
* @package MDB2
* @category Database
* @author Lukas Smith <smith@dybnet.de>
* @author Lorenzo Alberton <l.alberton@quipo.it>
*/
class MDB2_Driver_Reverse_sqlsrv extends MDB2_Driver_Reverse_Common
{
// {{{ getTableFieldDefinition()
/**
* Get the structure of a field into an array
*
* @param string $table_name name of table that should be used in method
* @param string $field_name name of field that should be used in method
* @return mixed data array on success, a MDB2 error on failure
* @access public
*/
function getTableFieldDefinition($table_name, $field_name)
{
$db = $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
$result = $db->loadModule('Datatype', null, true);
if (PEAR::isError($result)) {
return $result;
}
list($schema, $table) = $this->splitTableSchema($table_name);
$table = $db->quoteIdentifier($table, true);
$fldname = $db->quoteIdentifier($field_name, true);
$query = "SELECT t.table_name,
c.column_name 'name',
c.data_type 'type',
CASE c.is_nullable WHEN 'YES' THEN 1 ELSE 0 END AS 'is_nullable',
c.column_default,
c.character_maximum_length 'length',
c.numeric_precision,
c.numeric_scale,
c.character_set_name,
c.collation_name
FROM INFORMATION_SCHEMA.TABLES t,
INFORMATION_SCHEMA.COLUMNS c
WHERE t.table_name = c.table_name
AND t.table_name = '$table'
AND c.column_name = '$fldname'";
if (!empty($schema)) {
$query .= " AND t.table_schema = '" .$db->quoteIdentifier($schema, true) ."'";
}
$query .= ' ORDER BY t.table_name';
$column = $db->queryRow($query, null, MDB2_FETCHMODE_ASSOC);
if (PEAR::isError($column)) {
return $column;
}
if (empty($column)) {
return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
'it was not specified an existing table column', __FUNCTION__);
}
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
if ($db->options['field_case'] == CASE_LOWER) {
$column['name'] = strtolower($column['name']);
} else {
$column['name'] = strtoupper($column['name']);
}
} else {
$column = array_change_key_case($column, $db->options['field_case']);
}
$mapped_datatype = $db->datatype->mapNativeDatatype($column);
if (PEAR::isError($mapped_datatype)) {
return $mapped_datatype;
}
list($types, $length, $unsigned, $fixed) = $mapped_datatype;
$notnull = true;
if ($column['is_nullable']) {
$notnull = false;
}
$default = false;
if (array_key_exists('column_default', $column)) {
$default = $column['column_default'];
if ((null === $default) && $notnull) {
$default = '';
} elseif (strlen($default) > 4
&& substr($default, 0, 1) == '('
&& substr($default, -1, 1) == ')'
) {
//mssql wraps the default value in parentheses: "((1234))", "(NULL)"
$default = trim($default, '()');
if ($default == 'NULL') {
$default = null;
}
}
}
$definition[0] = array(
'notnull' => $notnull,
'nativetype' => preg_replace('/^([a-z]+)[^a-z].*/i', '\\1', $column['type'])
);
if (null !== $length) {
$definition[0]['length'] = $length;
}
if (null !== $unsigned) {
$definition[0]['unsigned'] = $unsigned;
}
if (null !== $fixed) {
$definition[0]['fixed'] = $fixed;
}
if ($default !== false) {
$definition[0]['default'] = $default;
}
foreach ($types as $key => $type) {
$definition[$key] = $definition[0];
if ($type == 'clob' || $type == 'blob') {
unset($definition[$key]['default']);
}
$definition[$key]['type'] = $type;
$definition[$key]['mdb2type'] = $type;
}
return $definition;
}
// }}}
// {{{ getTableIndexDefinition()
/**
* Get the structure of an index into an array
*
* @param string $table_name name of table that should be used in method
* @param string $index_name name of index that should be used in method
* @return mixed data array on success, a MDB2 error on failure
* @access public
*/
function getTableIndexDefinition($table_name, $index_name)
{
$db = $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
list($schema, $table) = $this->splitTableSchema($table_name);
$table = $db->quoteIdentifier($table, true);
//$idxname = $db->quoteIdentifier($index_name, true);
$query = "SELECT OBJECT_NAME(i.id) tablename,
i.name indexname,
c.name field_name,
CASE INDEXKEY_PROPERTY(i.id, i.indid, ik.keyno, 'IsDescending')
WHEN 1 THEN 'DESC' ELSE 'ASC'
END 'collation',
ik.keyno 'position'
FROM sysindexes i
JOIN sysindexkeys ik ON ik.id = i.id AND ik.indid = i.indid
JOIN syscolumns c ON c.id = ik.id AND c.colid = ik.colid
WHERE OBJECT_NAME(i.id) = '$table'
AND i.name = '%s'
AND NOT EXISTS (
SELECT *
FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE k
WHERE k.table_name = OBJECT_NAME(i.id)
AND k.constraint_name = i.name";
if (!empty($schema)) {
$query .= " AND k.table_schema = '" .$db->quoteIdentifier($schema, true) ."'";
}
$query .= ')
ORDER BY tablename, indexname, ik.keyno';
$index_name_mdb2 = $db->getIndexName($index_name);
$result = $db->queryRow(sprintf($query, $index_name_mdb2));
if (!PEAR::isError($result) && (null !== $result)) {
// apply 'idxname_format' only if the query succeeded, otherwise
// fallback to the given $index_name, without transformation
$index_name = $index_name_mdb2;
}
$result = $db->query(sprintf($query, $index_name));
if (PEAR::isError($result)) {
return $result;
}
$definition = array();
while (is_array($row = $result->fetchRow(MDB2_FETCHMODE_ASSOC))) {
$column_name = $row['field_name'];
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
if ($db->options['field_case'] == CASE_LOWER) {
$column_name = strtolower($column_name);
} else {
$column_name = strtoupper($column_name);
}
}
$definition['fields'][$column_name] = array(
'position' => (int)$row['position'],
);
if (!empty($row['collation'])) {
$definition['fields'][$column_name]['sorting'] = ($row['collation'] == 'ASC'
? 'ascending' : 'descending');
}
}
$result->free();
if (empty($definition['fields'])) {
return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
'it was not specified an existing table index', __FUNCTION__);
}
return $definition;
}
// }}}
// {{{ getTableConstraintDefinition()
/**
* Get the structure of a constraint into an array
*
* @param string $table_name name of table that should be used in method
* @param string $constraint_name name of constraint that should be used in method
* @return mixed data array on success, a MDB2 error on failure
* @access public
*/
function getTableConstraintDefinition($table_name, $constraint_name)
{
$db = $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
list($schema, $table) = $this->splitTableSchema($table_name);
$table = $db->quoteIdentifier($table, true);
$query = "SELECT k.table_name,
k.column_name field_name,
CASE c.constraint_type WHEN 'PRIMARY KEY' THEN 1 ELSE 0 END 'primary',
CASE c.constraint_type WHEN 'UNIQUE' THEN 1 ELSE 0 END 'unique',
CASE c.constraint_type WHEN 'FOREIGN KEY' THEN 1 ELSE 0 END 'foreign',
CASE c.constraint_type WHEN 'CHECK' THEN 1 ELSE 0 END 'check',
CASE c.is_deferrable WHEN 'NO' THEN 0 ELSE 1 END 'deferrable',
CASE c.initially_deferred WHEN 'NO' THEN 0 ELSE 1 END 'initiallydeferred',
rc.match_option 'match',
rc.update_rule 'onupdate',
rc.delete_rule 'ondelete',
kcu.table_name 'references_table',
kcu.column_name 'references_field',
k.ordinal_position 'field_position'
FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE k
LEFT JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS c
ON k.table_name = c.table_name
AND k.table_schema = c.table_schema
AND k.table_catalog = c.table_catalog
AND k.constraint_catalog = c.constraint_catalog
AND k.constraint_name = c.constraint_name
LEFT JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS rc
ON rc.constraint_schema = c.constraint_schema
AND rc.constraint_catalog = c.constraint_catalog
AND rc.constraint_name = c.constraint_name
LEFT JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE kcu
ON rc.unique_constraint_schema = kcu.constraint_schema
AND rc.unique_constraint_catalog = kcu.constraint_catalog
AND rc.unique_constraint_name = kcu.constraint_name
AND k.ordinal_position = kcu.ordinal_position
WHERE k.constraint_catalog = DB_NAME()
AND k.table_name = '$table'
AND k.constraint_name = '%s'";
if (!empty($schema)) {
$query .= " AND k.table_schema = '" .$db->quoteIdentifier($schema, true) ."'";
}
$query .= ' ORDER BY k.constraint_name,
k.ordinal_position';
$constraint_name_mdb2 = $db->getIndexName($constraint_name);
$result = $db->queryRow(sprintf($query, $constraint_name_mdb2));
if (!PEAR::isError($result) && (null !== $result)) {
// apply 'idxname_format' only if the query succeeded, otherwise
// fallback to the given $index_name, without transformation
$constraint_name = $constraint_name_mdb2;
}
$result = $db->query(sprintf($query, $constraint_name));
if (PEAR::isError($result)) {
return $result;
}
$definition = array(
'fields' => array()
);
while (is_array($row = $result->fetchRow(MDB2_FETCHMODE_ASSOC))) {
$row = array_change_key_case($row, CASE_LOWER);
$column_name = $row['field_name'];
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
if ($db->options['field_case'] == CASE_LOWER) {
$column_name = strtolower($column_name);
} else {
$column_name = strtoupper($column_name);
}
}
$definition['fields'][$column_name] = array(
'position' => (int)$row['field_position']
);
if ($row['foreign']) {
$ref_column_name = $row['references_field'];
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
if ($db->options['field_case'] == CASE_LOWER) {
$ref_column_name = strtolower($ref_column_name);
} else {
$ref_column_name = strtoupper($ref_column_name);
}
}
$definition['references']['table'] = $row['references_table'];
$definition['references']['fields'][$ref_column_name] = array(
'position' => (int)$row['field_position']
);
}
//collation?!?
/*
if (!empty($row['collation'])) {
$definition['fields'][$column_name]['sorting'] = ($row['collation'] == 'ASC'
? 'ascending' : 'descending');
}
*/
$lastrow = $row;
// otherwise $row is no longer usable on exit from loop
}
$result->free();
if (empty($definition['fields'])) {
return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
$constraint_name . ' is not an existing table constraint', __FUNCTION__);
}
$definition['primary'] = (boolean)$lastrow['primary'];
$definition['unique'] = (boolean)$lastrow['unique'];
$definition['foreign'] = (boolean)$lastrow['foreign'];
$definition['check'] = (boolean)$lastrow['check'];
$definition['deferrable'] = (boolean)$lastrow['deferrable'];
$definition['initiallydeferred'] = (boolean)$lastrow['initiallydeferred'];
$definition['onupdate'] = $lastrow['onupdate'];
$definition['ondelete'] = $lastrow['ondelete'];
$definition['match'] = $lastrow['match'];
return $definition;
}
// }}}
// {{{ getTriggerDefinition()
/**
* Get the structure of a trigger into an array
*
* EXPERIMENTAL
*
* WARNING: this function is experimental and may change the returned value
* at any time until labelled as non-experimental
*
* @param string $trigger name of trigger that should be used in method
* @return mixed data array on success, a MDB2 error on failure
* @access public
*/
function getTriggerDefinition($trigger)
{
$db = $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
$query = "SELECT sys1.name trigger_name,
sys2.name table_name,
c.text trigger_body,
c.encrypted is_encripted,
CASE
WHEN OBJECTPROPERTY(sys1.id, 'ExecIsTriggerDisabled') = 1
THEN 0 ELSE 1
END trigger_enabled,
CASE
WHEN OBJECTPROPERTY(sys1.id, 'ExecIsInsertTrigger') = 1
THEN 'INSERT'
WHEN OBJECTPROPERTY(sys1.id, 'ExecIsUpdateTrigger') = 1
THEN 'UPDATE'
WHEN OBJECTPROPERTY(sys1.id, 'ExecIsDeleteTrigger') = 1
THEN 'DELETE'
END trigger_event,
CASE WHEN OBJECTPROPERTY(sys1.id, 'ExecIsInsteadOfTrigger') = 1
THEN 'INSTEAD OF' ELSE 'AFTER'
END trigger_type,
'' trigger_comment
FROM sysobjects sys1
JOIN sysobjects sys2 ON sys1.parent_obj = sys2.id
JOIN syscomments c ON sys1.id = c.id
WHERE sys1.xtype = 'TR'
AND sys1.name = ". $db->quote($trigger, 'text');
$types = array(
'trigger_name' => 'text',
'table_name' => 'text',
'trigger_body' => 'text',
'trigger_type' => 'text',
'trigger_event' => 'text',
'trigger_comment' => 'text',
'trigger_enabled' => 'boolean',
'is_encripted' => 'boolean',
);
$def = $db->queryRow($query, $types, MDB2_FETCHMODE_ASSOC);
if (PEAR::isError($def)) {
return $def;
}
$trg_body = $db->queryCol('EXEC sp_helptext '. $db->quote($trigger, 'text'), 'text');
if (!PEAR::isError($trg_body)) {
$def['trigger_body'] = implode(' ', $trg_body);
}
return $def;
}
// }}}
// {{{ tableInfo()
/**
* Returns information about a table or a result set
*
* NOTE: only supports 'table' and 'flags' if <var>$result</var>
* is a table name.
*
* @param object|string $result MDB2_result object from a query or a
* string containing the name of a table.
* While this also accepts a query result
* resource identifier, this behavior is
* deprecated.
* @param int $mode a valid tableInfo mode
*
* @return array an associative array with the information requested.
* A MDB2_Error object on failure.
*
* @see MDB2_Driver_Common::tableInfo()
*/
function tableInfo($result, $mode = null)
{
if (is_string($result)) {
return parent::tableInfo($result, $mode);
}
$db = $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
$resource = MDB2::isResultCommon($result) ? $result->getResource() : $result;
if (!is_resource($resource)) {
return $db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null,
'Could not generate result resource', __FUNCTION__);
}
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
if ($db->options['field_case'] == CASE_LOWER) {
$case_func = 'strtolower';
} else {
$case_func = 'strtoupper';
}
} else {
$case_func = 'strval';
}
$meta = @sqlsrv_field_metadata($resource);
$count = count($meta);
$res = array();
if ($mode) {
$res['num_fields'] = $count;
}
$db->loadModule('Datatype', null, true);
for ($i = 0; $i < $count; $i++) {
$res[$i] = array(
'table' => '',
'name' => $case_func($meta[$i]['Name']),
'type' => $meta[$i]['Type'],
'length' => $meta[$i]['Size'],
'numeric_precision' => $meta[$i]['Precision'],
'numeric_scale' => $meta[$i]['Scale'],
'flags' => ''
);
$mdb2type_info = $db->datatype->mapNativeDatatype($res[$i]);
if (PEAR::isError($mdb2type_info)) {
return $mdb2type_info;
}
$res[$i]['mdb2type'] = $mdb2type_info[0][0];
if ($mode & MDB2_TABLEINFO_ORDER) {
$res['order'][$res[$i]['name']] = $i;
}
if ($mode & MDB2_TABLEINFO_ORDERTABLE) {
$res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i;
}
}
return $res;
}
// }}}
// {{{ _mssql_field_flags()
/**
* Get a column's flags
*
* Supports "not_null", "primary_key",
* "auto_increment" (mssql identity), "timestamp" (mssql timestamp),
* "unique_key" (mssql unique index, unique check or primary_key) and
* "multiple_key" (multikey index)
*
* mssql timestamp is NOT similar to the mysql timestamp so this is maybe
* not useful at all - is the behaviour of mysql_field_flags that primary
* keys are alway unique? is the interpretation of multiple_key correct?
*
* @param string $table the table name
* @param string $column the field name
*
* @return string the flags
*
* @access protected
* @author Joern Barthel <j_barthel@web.de>
*/
function _mssql_field_flags($table, $column)
{
$db = $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
static $tableName = null;
static $flags = array();
if ($table != $tableName) {
$flags = array();
$tableName = $table;
// get unique and primary keys
$res = $db->queryAll("EXEC SP_HELPINDEX[$table]", null, MDB2_FETCHMODE_ASSOC);
foreach ($res as $val) {
$val = array_change_key_case($val, CASE_LOWER);
$keys = explode(', ', $val['index_keys']);
if (sizeof($keys) > 1) {
foreach ($keys as $key) {
$this->_add_flag($flags[$key], 'multiple_key');
}
}
if (strpos($val['index_description'], 'primary key')) {
foreach ($keys as $key) {
$this->_add_flag($flags[$key], 'primary_key');
}
} elseif (strpos($val['index_description'], 'unique')) {
foreach ($keys as $key) {
$this->_add_flag($flags[$key], 'unique_key');
}
}
}
// get auto_increment, not_null and timestamp
$res = $db->queryAll("EXEC SP_COLUMNS[$table]", null, MDB2_FETCHMODE_ASSOC);
foreach ($res as $val) {
$val = array_change_key_case($val, CASE_LOWER);
if ($val['nullable'] == '0') {
$this->_add_flag($flags[$val['column_name']], 'not_null');
}
if (strpos($val['type_name'], 'identity')) {
$this->_add_flag($flags[$val['column_name']], 'auto_increment');
}
if (strpos($val['type_name'], 'timestamp')) {
$this->_add_flag($flags[$val['column_name']], 'timestamp');
}
}
}
if (!empty($flags[$column])) {
return(implode(' ', $flags[$column]));
}
return '';
}
// }}}
// {{{ _add_flag()
/**
* Adds a string to the flags array if the flag is not yet in there
* - if there is no flag present the array is created
*
* @param array &$array the reference to the flag-array
* @param string $value the flag value
*
* @return void
*
* @access protected
* @author Joern Barthel <j_barthel@web.de>
*/
function _add_flag(&$array, $value)
{
if (!is_array($array)) {
$array = array($value);
} elseif (!in_array($value, $array)) {
array_push($array, $value);
}
}
// }}}
}
?>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -1,721 +0,0 @@
<?php
// +----------------------------------------------------------------------+
// | PHP versions 4 and 5 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1998-2006 Manuel Lemos, Tomas V.V.Cox, |
// | Stig. S. Bakken, Lukas Smith |
// | All rights reserved. |
// +----------------------------------------------------------------------+
// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB |
// | API as well as database abstraction for PHP applications. |
// | This LICENSE is in the BSD license style. |
// | |
// | Redistribution and use in source and binary forms, with or without |
// | modification, are permitted provided that the following conditions |
// | are met: |
// | |
// | Redistributions of source code must retain the above copyright |
// | notice, this list of conditions and the following disclaimer. |
// | |
// | Redistributions in binary form must reproduce the above copyright |
// | notice, this list of conditions and the following disclaimer in the |
// | documentation and/or other materials provided with the distribution. |
// | |
// | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken, |
// | Lukas Smith nor the names of his contributors may be used to endorse |
// | or promote products derived from this software without specific prior|
// | written permission. |
// | |
// | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
// | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
// | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
// | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE |
// | REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, |
// | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
// | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS|
// | OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED |
// | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
// | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY|
// | WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
// | POSSIBILITY OF SUCH DAMAGE. |
// +----------------------------------------------------------------------+
// | Author: Lukas Smith <smith@pooteeweet.org> |
// +----------------------------------------------------------------------+
//
// $Id: Extended.php 292715 2009-12-28 14:06:34Z quipo $
/**
* @package MDB2
* @category Database
* @author Lukas Smith <smith@pooteeweet.org>
*/
/**
* Used by autoPrepare()
*/
define('MDB2_AUTOQUERY_INSERT', 1);
define('MDB2_AUTOQUERY_UPDATE', 2);
define('MDB2_AUTOQUERY_DELETE', 3);
define('MDB2_AUTOQUERY_SELECT', 4);
/**
* MDB2_Extended: class which adds several high level methods to MDB2
*
* @package MDB2
* @category Database
* @author Lukas Smith <smith@pooteeweet.org>
*/
class MDB2_Extended extends MDB2_Module_Common
{
// {{{ autoPrepare()
/**
* Generate an insert, update or delete query and call prepare() on it
*
* @param string table
* @param array the fields names
* @param int type of query to build
* MDB2_AUTOQUERY_INSERT
* MDB2_AUTOQUERY_UPDATE
* MDB2_AUTOQUERY_DELETE
* MDB2_AUTOQUERY_SELECT
* @param string (in case of update and delete queries, this string will be put after the sql WHERE statement)
* @param array that contains the types of the placeholders
* @param mixed array that contains the types of the columns in
* the result set or MDB2_PREPARE_RESULT, if set to
* MDB2_PREPARE_MANIP the query is handled as a manipulation query
*
* @return resource handle for the query
* @see buildManipSQL
* @access public
*/
function autoPrepare($table, $table_fields, $mode = MDB2_AUTOQUERY_INSERT,
$where = false, $types = null, $result_types = MDB2_PREPARE_MANIP)
{
$query = $this->buildManipSQL($table, $table_fields, $mode, $where);
if (PEAR::isError($query)) {
return $query;
}
$db =& $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
$lobs = array();
foreach ((array)$types as $param => $type) {
if (($type == 'clob') || ($type == 'blob')) {
$lobs[$param] = $table_fields[$param];
}
}
return $db->prepare($query, $types, $result_types, $lobs);
}
// }}}
// {{{ autoExecute()
/**
* Generate an insert, update or delete query and call prepare() and execute() on it
*
* @param string name of the table
* @param array assoc ($key=>$value) where $key is a field name and $value its value
* @param int type of query to build
* MDB2_AUTOQUERY_INSERT
* MDB2_AUTOQUERY_UPDATE
* MDB2_AUTOQUERY_DELETE
* MDB2_AUTOQUERY_SELECT
* @param string (in case of update and delete queries, this string will be put after the sql WHERE statement)
* @param array that contains the types of the placeholders
* @param string which specifies which result class to use
* @param mixed array that contains the types of the columns in
* the result set or MDB2_PREPARE_RESULT, if set to
* MDB2_PREPARE_MANIP the query is handled as a manipulation query
*
* @return bool|MDB2_Error true on success, a MDB2 error on failure
* @see buildManipSQL
* @see autoPrepare
* @access public
*/
function &autoExecute($table, $fields_values, $mode = MDB2_AUTOQUERY_INSERT,
$where = false, $types = null, $result_class = true, $result_types = MDB2_PREPARE_MANIP)
{
$fields_values = (array)$fields_values;
if ($mode == MDB2_AUTOQUERY_SELECT) {
if (is_array($result_types)) {
$keys = array_keys($result_types);
} elseif (!empty($fields_values)) {
$keys = $fields_values;
} else {
$keys = array();
}
} else {
$keys = array_keys($fields_values);
}
$params = array_values($fields_values);
if (empty($params)) {
$query = $this->buildManipSQL($table, $keys, $mode, $where);
$db =& $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
if ($mode == MDB2_AUTOQUERY_SELECT) {
$result =& $db->query($query, $result_types, $result_class);
} else {
$result = $db->exec($query);
}
} else {
$stmt = $this->autoPrepare($table, $keys, $mode, $where, $types, $result_types);
if (PEAR::isError($stmt)) {
return $stmt;
}
$result =& $stmt->execute($params, $result_class);
$stmt->free();
}
return $result;
}
// }}}
// {{{ buildManipSQL()
/**
* Make automaticaly an sql query for prepare()
*
* Example : buildManipSQL('table_sql', array('field1', 'field2', 'field3'), MDB2_AUTOQUERY_INSERT)
* will return the string : INSERT INTO table_sql (field1,field2,field3) VALUES (?,?,?)
* NB : - This belongs more to a SQL Builder class, but this is a simple facility
* - Be carefull ! If you don't give a $where param with an UPDATE/DELETE query, all
* the records of the table will be updated/deleted !
*
* @param string name of the table
* @param ordered array containing the fields names
* @param int type of query to build
* MDB2_AUTOQUERY_INSERT
* MDB2_AUTOQUERY_UPDATE
* MDB2_AUTOQUERY_DELETE
* MDB2_AUTOQUERY_SELECT
* @param string (in case of update and delete queries, this string will be put after the sql WHERE statement)
*
* @return string sql query for prepare()
* @access public
*/
function buildManipSQL($table, $table_fields, $mode, $where = false)
{
$db =& $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
if ($db->options['quote_identifier']) {
$table = $db->quoteIdentifier($table);
}
if (!empty($table_fields) && $db->options['quote_identifier']) {
foreach ($table_fields as $key => $field) {
$table_fields[$key] = $db->quoteIdentifier($field);
}
}
if ((false !== $where) && (null !== $where)) {
if (is_array($where)) {
$where = implode(' AND ', $where);
}
$where = ' WHERE '.$where;
}
switch ($mode) {
case MDB2_AUTOQUERY_INSERT:
if (empty($table_fields)) {
return $db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null,
'Insert requires table fields', __FUNCTION__);
}
$cols = implode(', ', $table_fields);
$values = '?'.str_repeat(', ?', (count($table_fields) - 1));
return 'INSERT INTO '.$table.' ('.$cols.') VALUES ('.$values.')';
break;
case MDB2_AUTOQUERY_UPDATE:
if (empty($table_fields)) {
return $db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null,
'Update requires table fields', __FUNCTION__);
}
$set = implode(' = ?, ', $table_fields).' = ?';
$sql = 'UPDATE '.$table.' SET '.$set.$where;
return $sql;
break;
case MDB2_AUTOQUERY_DELETE:
$sql = 'DELETE FROM '.$table.$where;
return $sql;
break;
case MDB2_AUTOQUERY_SELECT:
$cols = !empty($table_fields) ? implode(', ', $table_fields) : '*';
$sql = 'SELECT '.$cols.' FROM '.$table.$where;
return $sql;
break;
}
return $db->raiseError(MDB2_ERROR_SYNTAX, null, null,
'Non existant mode', __FUNCTION__);
}
// }}}
// {{{ limitQuery()
/**
* Generates a limited query
*
* @param string query
* @param array that contains the types of the columns in the result set
* @param integer the numbers of rows to fetch
* @param integer the row to start to fetching
* @param string which specifies which result class to use
* @param mixed string which specifies which class to wrap results in
*
* @return MDB2_Result|MDB2_Error result set on success, a MDB2 error on failure
* @access public
*/
function &limitQuery($query, $types, $limit, $offset = 0, $result_class = true,
$result_wrap_class = false)
{
$db =& $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
$result = $db->setLimit($limit, $offset);
if (PEAR::isError($result)) {
return $result;
}
$result =& $db->query($query, $types, $result_class, $result_wrap_class);
return $result;
}
// }}}
// {{{ execParam()
/**
* Execute a parameterized DML statement.
*
* @param string the SQL query
* @param array if supplied, prepare/execute will be used
* with this array as execute parameters
* @param array that contains the types of the values defined in $params
*
* @return int|MDB2_Error affected rows on success, a MDB2 error on failure
* @access public
*/
function execParam($query, $params = array(), $param_types = null)
{
$db =& $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
settype($params, 'array');
if (empty($params)) {
return $db->exec($query);
}
$stmt = $db->prepare($query, $param_types, MDB2_PREPARE_MANIP);
if (PEAR::isError($stmt)) {
return $stmt;
}
$result = $stmt->execute($params);
if (PEAR::isError($result)) {
return $result;
}
$stmt->free();
return $result;
}
// }}}
// {{{ getOne()
/**
* Fetch the first column of the first row of data returned from a query.
* Takes care of doing the query and freeing the results when finished.
*
* @param string the SQL query
* @param string that contains the type of the column in the result set
* @param array if supplied, prepare/execute will be used
* with this array as execute parameters
* @param array that contains the types of the values defined in $params
* @param int|string which column to return
*
* @return scalar|MDB2_Error data on success, a MDB2 error on failure
* @access public
*/
function getOne($query, $type = null, $params = array(),
$param_types = null, $colnum = 0)
{
$db =& $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
settype($params, 'array');
settype($type, 'array');
if (empty($params)) {
return $db->queryOne($query, $type, $colnum);
}
$stmt = $db->prepare($query, $param_types, $type);
if (PEAR::isError($stmt)) {
return $stmt;
}
$result = $stmt->execute($params);
if (!MDB2::isResultCommon($result)) {
return $result;
}
$one = $result->fetchOne($colnum);
$stmt->free();
$result->free();
return $one;
}
// }}}
// {{{ getRow()
/**
* Fetch the first row of data returned from a query. Takes care
* of doing the query and freeing the results when finished.
*
* @param string the SQL query
* @param array that contains the types of the columns in the result set
* @param array if supplied, prepare/execute will be used
* with this array as execute parameters
* @param array that contains the types of the values defined in $params
* @param int the fetch mode to use
*
* @return array|MDB2_Error data on success, a MDB2 error on failure
* @access public
*/
function getRow($query, $types = null, $params = array(),
$param_types = null, $fetchmode = MDB2_FETCHMODE_DEFAULT)
{
$db =& $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
settype($params, 'array');
if (empty($params)) {
return $db->queryRow($query, $types, $fetchmode);
}
$stmt = $db->prepare($query, $param_types, $types);
if (PEAR::isError($stmt)) {
return $stmt;
}
$result = $stmt->execute($params);
if (!MDB2::isResultCommon($result)) {
return $result;
}
$row = $result->fetchRow($fetchmode);
$stmt->free();
$result->free();
return $row;
}
// }}}
// {{{ getCol()
/**
* Fetch a single column from a result set and return it as an
* indexed array.
*
* @param string the SQL query
* @param string that contains the type of the column in the result set
* @param array if supplied, prepare/execute will be used
* with this array as execute parameters
* @param array that contains the types of the values defined in $params
* @param int|string which column to return
*
* @return array|MDB2_Error data on success, a MDB2 error on failure
* @access public
*/
function getCol($query, $type = null, $params = array(),
$param_types = null, $colnum = 0)
{
$db =& $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
settype($params, 'array');
settype($type, 'array');
if (empty($params)) {
return $db->queryCol($query, $type, $colnum);
}
$stmt = $db->prepare($query, $param_types, $type);
if (PEAR::isError($stmt)) {
return $stmt;
}
$result = $stmt->execute($params);
if (!MDB2::isResultCommon($result)) {
return $result;
}
$col = $result->fetchCol($colnum);
$stmt->free();
$result->free();
return $col;
}
// }}}
// {{{ getAll()
/**
* Fetch all the rows returned from a query.
*
* @param string the SQL query
* @param array that contains the types of the columns in the result set
* @param array if supplied, prepare/execute will be used
* with this array as execute parameters
* @param array that contains the types of the values defined in $params
* @param int the fetch mode to use
* @param bool if set to true, the $all will have the first
* column as its first dimension
* @param bool $force_array used only when the query returns exactly
* two columns. If true, the values of the returned array will be
* one-element arrays instead of scalars.
* @param bool $group if true, the values of the returned array is
* wrapped in another array. If the same key value (in the first
* column) repeats itself, the values will be appended to this array
* instead of overwriting the existing values.
*
* @return array|MDB2_Error data on success, a MDB2 error on failure
* @access public
*/
function getAll($query, $types = null, $params = array(),
$param_types = null, $fetchmode = MDB2_FETCHMODE_DEFAULT,
$rekey = false, $force_array = false, $group = false)
{
$db =& $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
settype($params, 'array');
if (empty($params)) {
return $db->queryAll($query, $types, $fetchmode, $rekey, $force_array, $group);
}
$stmt = $db->prepare($query, $param_types, $types);
if (PEAR::isError($stmt)) {
return $stmt;
}
$result = $stmt->execute($params);
if (!MDB2::isResultCommon($result)) {
return $result;
}
$all = $result->fetchAll($fetchmode, $rekey, $force_array, $group);
$stmt->free();
$result->free();
return $all;
}
// }}}
// {{{ getAssoc()
/**
* Fetch the entire result set of a query and return it as an
* associative array using the first column as the key.
*
* If the result set contains more than two columns, the value
* will be an array of the values from column 2-n. If the result
* set contains only two columns, the returned value will be a
* scalar with the value of the second column (unless forced to an
* array with the $force_array parameter). A MDB2 error code is
* returned on errors. If the result set contains fewer than two
* columns, a MDB2_ERROR_TRUNCATED error is returned.
*
* For example, if the table 'mytable' contains:
* <pre>
* ID TEXT DATE
* --------------------------------
* 1 'one' 944679408
* 2 'two' 944679408
* 3 'three' 944679408
* </pre>
* Then the call getAssoc('SELECT id,text FROM mytable') returns:
* <pre>
* array(
* '1' => 'one',
* '2' => 'two',
* '3' => 'three',
* )
* </pre>
* ...while the call getAssoc('SELECT id,text,date FROM mytable') returns:
* <pre>
* array(
* '1' => array('one', '944679408'),
* '2' => array('two', '944679408'),
* '3' => array('three', '944679408')
* )
* </pre>
*
* If the more than one row occurs with the same value in the
* first column, the last row overwrites all previous ones by
* default. Use the $group parameter if you don't want to
* overwrite like this. Example:
* <pre>
* getAssoc('SELECT category,id,name FROM mytable', null, null
* MDB2_FETCHMODE_ASSOC, false, true) returns:
* array(
* '1' => array(array('id' => '4', 'name' => 'number four'),
* array('id' => '6', 'name' => 'number six')
* ),
* '9' => array(array('id' => '4', 'name' => 'number four'),
* array('id' => '6', 'name' => 'number six')
* )
* )
* </pre>
*
* Keep in mind that database functions in PHP usually return string
* values for results regardless of the database's internal type.
*
* @param string the SQL query
* @param array that contains the types of the columns in the result set
* @param array if supplied, prepare/execute will be used
* with this array as execute parameters
* @param array that contains the types of the values defined in $params
* @param bool $force_array used only when the query returns
* exactly two columns. If TRUE, the values of the returned array
* will be one-element arrays instead of scalars.
* @param bool $group if TRUE, the values of the returned array
* is wrapped in another array. If the same key value (in the first
* column) repeats itself, the values will be appended to this array
* instead of overwriting the existing values.
*
* @return array|MDB2_Error data on success, a MDB2 error on failure
* @access public
*/
function getAssoc($query, $types = null, $params = array(), $param_types = null,
$fetchmode = MDB2_FETCHMODE_DEFAULT, $force_array = false, $group = false)
{
$db =& $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
settype($params, 'array');
if (empty($params)) {
return $db->queryAll($query, $types, $fetchmode, true, $force_array, $group);
}
$stmt = $db->prepare($query, $param_types, $types);
if (PEAR::isError($stmt)) {
return $stmt;
}
$result = $stmt->execute($params);
if (!MDB2::isResultCommon($result)) {
return $result;
}
$all = $result->fetchAll($fetchmode, true, $force_array, $group);
$stmt->free();
$result->free();
return $all;
}
// }}}
// {{{ executeMultiple()
/**
* This function does several execute() calls on the same statement handle.
* $params must be an array indexed numerically from 0, one execute call is
* done for every 'row' in the array.
*
* If an error occurs during execute(), executeMultiple() does not execute
* the unfinished rows, but rather returns that error.
*
* @param resource query handle from prepare()
* @param array numeric array containing the data to insert into the query
*
* @return bool|MDB2_Error true on success, a MDB2 error on failure
* @access public
* @see prepare(), execute()
*/
function executeMultiple(&$stmt, $params = null)
{
for ($i = 0, $j = count($params); $i < $j; $i++) {
$result = $stmt->execute($params[$i]);
if (PEAR::isError($result)) {
return $result;
}
}
return MDB2_OK;
}
// }}}
// {{{ getBeforeID()
/**
* Returns the next free id of a sequence if the RDBMS
* does not support auto increment
*
* @param string name of the table into which a new row was inserted
* @param string name of the field into which a new row was inserted
* @param bool when true the sequence is automatic created, if it not exists
* @param bool if the returned value should be quoted
*
* @return int|MDB2_Error id on success, a MDB2 error on failure
* @access public
*/
function getBeforeID($table, $field = null, $ondemand = true, $quote = true)
{
$db =& $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
if ($db->supports('auto_increment') !== true) {
$seq = $table.(empty($field) ? '' : '_'.$field);
$id = $db->nextID($seq, $ondemand);
if (!$quote || PEAR::isError($id)) {
return $id;
}
return $db->quote($id, 'integer');
} elseif (!$quote) {
return null;
}
return 'NULL';
}
// }}}
// {{{ getAfterID()
/**
* Returns the autoincrement ID if supported or $id
*
* @param mixed value as returned by getBeforeId()
* @param string name of the table into which a new row was inserted
* @param string name of the field into which a new row was inserted
*
* @return int|MDB2_Error id on success, a MDB2 error on failure
* @access public
*/
function getAfterID($id, $table, $field = null)
{
$db =& $this->getDBInstance();
if (PEAR::isError($db)) {
return $db;
}
if ($db->supports('auto_increment') !== true) {
return $id;
}
return $db->lastInsertID($table, $field);
}
// }}}
}
?>

@ -1,259 +0,0 @@
<?php
// +----------------------------------------------------------------------+
// | PHP version 5 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1998-2006 Manuel Lemos, Tomas V.V.Cox, |
// | Stig. S. Bakken, Lukas Smith |
// | All rights reserved. |
// +----------------------------------------------------------------------+
// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB |
// | API as well as database abstraction for PHP applications. |
// | This LICENSE is in the BSD license style. |
// | |
// | Redistribution and use in source and binary forms, with or without |
// | modification, are permitted provided that the following conditions |
// | are met: |
// | |
// | Redistributions of source code must retain the above copyright |
// | notice, this list of conditions and the following disclaimer. |
// | |
// | Redistributions in binary form must reproduce the above copyright |
// | notice, this list of conditions and the following disclaimer in the |
// | documentation and/or other materials provided with the distribution. |
// | |
// | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken, |
// | Lukas Smith nor the names of his contributors may be used to endorse |
// | or promote products derived from this software without specific prior|
// | written permission. |
// | |
// | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
// | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
// | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
// | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE |
// | REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, |
// | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
// | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS|
// | OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED |
// | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
// | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY|
// | WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
// | POSSIBILITY OF SUCH DAMAGE. |
// +----------------------------------------------------------------------+
// | Author: Lukas Smith <smith@pooteeweet.org> |
// +----------------------------------------------------------------------+
//
// $Id: Iterator.php 295586 2010-02-28 17:04:17Z quipo $
/**
* PHP5 Iterator
*
* @package MDB2
* @category Database
* @author Lukas Smith <smith@pooteeweet.org>
*/
class MDB2_Iterator implements Iterator
{
protected $fetchmode;
protected $result;
protected $row;
// {{{ constructor
/**
* Constructor
*/
public function __construct($result, $fetchmode = MDB2_FETCHMODE_DEFAULT)
{
$this->result = $result;
$this->fetchmode = $fetchmode;
}
// }}}
// {{{ seek()
/**
* Seek forward to a specific row in a result set
*
* @param int number of the row where the data can be found
*
* @return void
* @access public
*/
public function seek($rownum)
{
$this->row = null;
if ($this->result) {
$this->result->seek($rownum);
}
}
// }}}
// {{{ next()
/**
* Fetch next row of data
*
* @return void
* @access public
*/
public function next()
{
$this->row = null;
}
// }}}
// {{{ current()
/**
* return a row of data
*
* @return void
* @access public
*/
public function current()
{
if (null === $this->row) {
$row = $this->result->fetchRow($this->fetchmode);
if (PEAR::isError($row)) {
$row = false;
}
$this->row = $row;
}
return $this->row;
}
// }}}
// {{{ valid()
/**
* Check if the end of the result set has been reached
*
* @return bool true/false, false is also returned on failure
* @access public
*/
public function valid()
{
return (bool)$this->current();
}
// }}}
// {{{ free()
/**
* Free the internal resources associated with result.
*
* @return bool|MDB2_Error true on success, false|MDB2_Error if result is invalid
* @access public
*/
public function free()
{
if ($this->result) {
return $this->result->free();
}
$this->result = false;
$this->row = null;
return false;
}
// }}}
// {{{ key()
/**
* Returns the row number
*
* @return int|bool|MDB2_Error true on success, false|MDB2_Error if result is invalid
* @access public
*/
public function key()
{
if ($this->result) {
return $this->result->rowCount();
}
return false;
}
// }}}
// {{{ rewind()
/**
* Seek to the first row in a result set
*
* @return void
* @access public
*/
public function rewind()
{
}
// }}}
// {{{ destructor
/**
* Destructor
*/
public function __destruct()
{
$this->free();
}
// }}}
}
/**
* PHP5 buffered Iterator
*
* @package MDB2
* @category Database
* @author Lukas Smith <smith@pooteeweet.org>
*/
class MDB2_BufferedIterator extends MDB2_Iterator implements SeekableIterator
{
// {{{ valid()
/**
* Check if the end of the result set has been reached
*
* @return bool|MDB2_Error true on success, false|MDB2_Error if result is invalid
* @access public
*/
public function valid()
{
if ($this->result) {
return $this->result->valid();
}
return false;
}
// }}}
// {{{count()
/**
* Returns the number of rows in a result object
*
* @return int|MDB2_Error number of rows, false|MDB2_Error if result is invalid
* @access public
*/
public function count()
{
if ($this->result) {
return $this->result->numRows();
}
return false;
}
// }}}
// {{{ rewind()
/**
* Seek to the first row in a result set
*
* @return void
* @access public
*/
public function rewind()
{
$this->seek(0);
}
// }}}
}
?>

@ -1,264 +0,0 @@
<?php
// +----------------------------------------------------------------------+
// | PHP version 5 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1998-2006 Manuel Lemos, Tomas V.V.Cox, |
// | Stig. S. Bakken, Lukas Smith |
// | All rights reserved. |
// +----------------------------------------------------------------------+
// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB |
// | API as well as database abstraction for PHP applications. |
// | This LICENSE is in the BSD license style. |
// | |
// | Redistribution and use in source and binary forms, with or without |
// | modification, are permitted provided that the following conditions |
// | are met: |
// | |
// | Redistributions of source code must retain the above copyright |
// | notice, this list of conditions and the following disclaimer. |
// | |
// | Redistributions in binary form must reproduce the above copyright |
// | notice, this list of conditions and the following disclaimer in the |
// | documentation and/or other materials provided with the distribution. |
// | |
// | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken, |
// | Lukas Smith nor the names of his contributors may be used to endorse |
// | or promote products derived from this software without specific prior|
// | written permission. |
// | |
// | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
// | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
// | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
// | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE |
// | REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, |
// | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
// | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS|
// | OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED |
// | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
// | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY|
// | WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
// | POSSIBILITY OF SUCH DAMAGE. |
// +----------------------------------------------------------------------+
// | Author: Lukas Smith <smith@pooteeweet.org> |
// +----------------------------------------------------------------------+
//
// $Id: LOB.php 222350 2006-10-25 11:52:21Z lsmith $
/**
* @package MDB2
* @category Database
* @author Lukas Smith <smith@pooteeweet.org>
*/
require_once 'MDB2.php';
/**
* MDB2_LOB: user land stream wrapper implementation for LOB support
*
* @package MDB2
* @category Database
* @author Lukas Smith <smith@pooteeweet.org>
*/
class MDB2_LOB
{
/**
* contains the key to the global MDB2 instance array of the associated
* MDB2 instance
*
* @var integer
* @access protected
*/
var $db_index;
/**
* contains the key to the global MDB2_LOB instance array of the associated
* MDB2_LOB instance
*
* @var integer
* @access protected
*/
var $lob_index;
// {{{ stream_open()
/**
* open stream
*
* @param string specifies the URL that was passed to fopen()
* @param string the mode used to open the file
* @param int holds additional flags set by the streams API
* @param string not used
*
* @return bool
* @access public
*/
function stream_open($path, $mode, $options, &$opened_path)
{
if (!preg_match('/^rb?\+?$/', $mode)) {
return false;
}
$url = parse_url($path);
if (empty($url['host'])) {
return false;
}
$this->db_index = (int)$url['host'];
if (!isset($GLOBALS['_MDB2_databases'][$this->db_index])) {
return false;
}
$db =& $GLOBALS['_MDB2_databases'][$this->db_index];
$this->lob_index = (int)$url['user'];
if (!isset($db->datatype->lobs[$this->lob_index])) {
return false;
}
return true;
}
// }}}
// {{{ stream_read()
/**
* read stream
*
* @param int number of bytes to read
*
* @return string
* @access public
*/
function stream_read($count)
{
if (isset($GLOBALS['_MDB2_databases'][$this->db_index])) {
$db =& $GLOBALS['_MDB2_databases'][$this->db_index];
$db->datatype->_retrieveLOB($db->datatype->lobs[$this->lob_index]);
$data = $db->datatype->_readLOB($db->datatype->lobs[$this->lob_index], $count);
$length = strlen($data);
if ($length == 0) {
$db->datatype->lobs[$this->lob_index]['endOfLOB'] = true;
}
$db->datatype->lobs[$this->lob_index]['position'] += $length;
return $data;
}
}
// }}}
// {{{ stream_write()
/**
* write stream, note implemented
*
* @param string data
*
* @return int
* @access public
*/
function stream_write($data)
{
return 0;
}
// }}}
// {{{ stream_tell()
/**
* return the current position
*
* @return int current position
* @access public
*/
function stream_tell()
{
if (isset($GLOBALS['_MDB2_databases'][$this->db_index])) {
$db =& $GLOBALS['_MDB2_databases'][$this->db_index];
return $db->datatype->lobs[$this->lob_index]['position'];
}
}
// }}}
// {{{ stream_eof()
/**
* Check if stream reaches EOF
*
* @return bool
* @access public
*/
function stream_eof()
{
if (!isset($GLOBALS['_MDB2_databases'][$this->db_index])) {
return true;
}
$db =& $GLOBALS['_MDB2_databases'][$this->db_index];
$result = $db->datatype->_endOfLOB($db->datatype->lobs[$this->lob_index]);
if (version_compare(phpversion(), "5.0", ">=")
&& version_compare(phpversion(), "5.1", "<")
) {
return !$result;
}
return $result;
}
// }}}
// {{{ stream_seek()
/**
* Seek stream, not implemented
*
* @param int offset
* @param int whence
*
* @return bool
* @access public
*/
function stream_seek($offset, $whence)
{
return false;
}
// }}}
// {{{ stream_stat()
/**
* return information about stream
*
* @access public
*/
function stream_stat()
{
if (isset($GLOBALS['_MDB2_databases'][$this->db_index])) {
$db =& $GLOBALS['_MDB2_databases'][$this->db_index];
return array(
'db_index' => $this->db_index,
'lob_index' => $this->lob_index,
);
}
}
// }}}
// {{{ stream_close()
/**
* close stream
*
* @access public
*/
function stream_close()
{
if (isset($GLOBALS['_MDB2_databases'][$this->db_index])) {
$db =& $GLOBALS['_MDB2_databases'][$this->db_index];
if (isset($db->datatype->lobs[$this->lob_index])) {
$db->datatype->_destroyLOB($db->datatype->lobs[$this->lob_index]);
unset($db->datatype->lobs[$this->lob_index]);
}
}
}
// }}}
}
// register streams wrapper
if (!stream_wrapper_register("MDB2LOB", "MDB2_LOB")) {
MDB2::raiseError();
return false;
}
?>
Loading…
Cancel
Save