Suppression de PEAR.

Le mode de connexion ldap reste a tester.
This commit is contained in:
Laurent Destailleur 2007-12-31 03:20:11 +00:00
parent 5910c05845
commit cf51602bb5
45 changed files with 0 additions and 31426 deletions

View File

@ -1,818 +0,0 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4: */
// +----------------------------------------------------------------------+
// | PHP Version 4 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1997-2003 The PHP Group |
// +----------------------------------------------------------------------+
// | This source file is subject to version 2.02 of the PHP license, |
// | that is bundled with this package in the file LICENSE, and is |
// | available at through the world-wide-web at |
// | http://www.php.net/license/2_02.txt. |
// | If you did not receive a copy of the PHP license and are unable to |
// | obtain it through the world-wide-web, please send a note to |
// | license@php.net so we can mail you a copy immediately. |
// +----------------------------------------------------------------------+
// | Authors: Martin Jansen <mj@php.net> |
// +----------------------------------------------------------------------+
//
// $Id$
//
//require_once "PEAR.php";
require_once PEAR_PATH."/PEAR.php";
define("AUTH_IDLED", -1);
define("AUTH_EXPIRED", -2);
define("AUTH_WRONG_LOGIN", -3);
/**
* PEAR::Auth
*
* The PEAR::Auth class provides methods for creating an
* authentication system using PHP.
*
* @author Martin Jansen <mj@php.net>
* @package Auth
* @version $Revision$
*/
class DOLIAuth {
/**
* Auth lifetime in seconds
*
* If this variable is set to 0, auth never expires
*
* @var integer
* @see setExpire(), checkAuth()
*/
var $expire = 0;
/**
* Has the auth session expired?
*
* @var bool
* @see checkAuth(), drawLogin()
*/
var $expired = false;
/**
* Maximum time of idleness in seconds
*
* The difference to $expire is, that the idletime gets
* refreshed each time, checkAuth() is called. If this
* variable is set to 0, idle time is never checked.
*
* @var integer
* @see setIdle(), checkAuth()
*/
var $idle = 0;
/**
* Is the maximum idletime over?
*
* @var boolean
* @see checkAuth(), drawLogin();
*/
var $idled = false;
/**
* Storage object
*
* @var object
* @see Auth(), validateLogin()
*/
var $storage = "";
/**
* function defined by the user, that creates the login screen
*
* @var string
*/
var $loginfunction = "";
/**
* Should the login form be displayed?
*
* @var bool
* @see setShowlogin()
*/
var $showLogin = true;
/**
* Current authentication status
*
* @var string
*/
var $status = "";
/**
* Username
*
* @var string
*/
var $username = "";
/**
* Password
*
* @var string
*/
var $password = "";
/**
* Login callback function name
*
* @var string
* @see setLoginCallback()
*/
var $loginCallback = "";
/**
* Logout callback function name
*
* @var string
* @see setLogoutCallback()
*/
var $logoutCallback = "";
// {{{ Constructor
/**
* Constructor
*
* Set up the storage driver.
*
* @param string Type of the storage driver
* @param mixed Additional options for the storage driver
* (example: if you are using DB as the storage
* driver, you have to pass the dsn string here)
*
* @param string Name of the function that creates the login form
* @param boolean Should the login form be displayed if neccessary?
* @return void
*/
function DOLIAuth($storageDriver, $options = "", $loginfunction = "", $showLogin = true)
{
if ($loginfunction != "" && function_exists($loginfunction)) {
$this->loginfunction = $loginfunction;
}
if (is_bool($showLogin)) {
$this->showLogin = $showLogin;
}
if (is_object($storageDriver)) {
$this->storage =& $storageDriver;
}
else{
$this->storage = $this->_factory($storageDriver, $options);
}
}
// }}}
// {{{ _factory()
/**
* Return a storage driver based on $driver and $options
*
* @access private
* @static
* @param string $driver Type of storage class to return
* @param string $options Optional parameters for the storage class
* @return object Object Storage object
*/
function _factory($driver, $options = "")
{
$storage_path = "Auth/Container/" . $driver . ".php";
$storage_class = "Auth_Container_" . $driver;
require_once PEAR_PATH."/".$storage_path;
return new $storage_class($options);
}
// }}}
// {{{ assignData()
/**
* Assign data from login form to internal values
*
* This function takes the values for username and password
* from $HTTP_POST_VARS and assigns them to internal variables.
* If you wish to use another source apart from $HTTP_POST_VARS,
* you have to derive this function.
*
* @access private
* @global $HTTP_POST_VARS
* @see Auth
* @return void
*/
function assignData()
{
$post = &$this->_importGlobalVariable("post");
if (isset($post['username']) && $post['username'] != "") {
$this->username = (get_magic_quotes_gpc() == 1 ? stripslashes($post['username']) : $post['username']);
}
if (isset($post['password']) && $post['password'] != "") {
$this->password = (get_magic_quotes_gpc() == 1 ? stripslashes($post['password']) : $post['password'] );
}
}
// }}}
// {{{ start()
/**
* Start new auth session
*
* @access public
* @return void
*/
function start()
{
$this->assignData();
session_start();
if (!$this->checkAuth()) {
$this->login();
}
}
// }}}
// {{{ login()
/**
* Login function
*
* @access private
* @return void
*/
function login()
{
$login_ok = false;
/**
* When the user has already entered a username,
* we have to validate it.
*/
if (!empty($this->username)) {
if (true === $this->storage->fetchData($this->username, $this->password)) {
$login_ok = true;
}
}
if (!empty($this->username) && $login_ok) {
$this->setAuth($this->username);
if (!empty($this->loginCallback)) {
call_user_func($this->loginCallback,$this->username);
}
}
/**
* If the login failed or the user entered no username,
* output the login screen again.
*/
if (!empty($this->username) && !$login_ok) {
$this->status = AUTH_WRONG_LOGIN;
}
if ((empty($this->username) || !$login_ok) && $this->showLogin) {
$this->drawLogin($this->storage->activeUser);
return;
}
}
// }}}
// {{{ setExpire()
/**
* Set the maximum expire time
*
* @access public
* @param integer time in seconds
* @param bool add time to current expire time or not
* @return void
*/
function setExpire($time, $add = false)
{
if ($add) {
$this->expire += $time;
} else {
$this->expire = $time;
}
}
// }}}
// {{{ setIdle()
/**
* Set the maximum idle time
*
* @access public
* @param integer time in seconds
* @param bool add time to current maximum idle time or not
* @return void
*/
function setIdle($time, $add = false)
{
if ($add) {
$this->idle += $time;
} else {
$this->idle = $time;
}
}
// }}}
// {{{ setSessionname()
/**
* Set name of the session to a customized value.
*
* If you are using multiple instances of PEAR::Auth
* on the same domain, you can change the name of
* session per application via this function.
*
* @access public
* @param string New name for the session
* @return void
*/
function setSessionname($name = "PHPSESSID")
{
@session_name($name);
}
// }}}
// {{{ setShowLogin()
/**
* Should the login form be displayed if neccessary?
*
* @access public
* @param bool show login form or not
* @return void
*/
function setShowLogin($showLogin = true)
{
$this->showLogin = $showLogin;
}
/**
* Register a callback function to be called on user login.
* The function will receive a single parameter, the username.
*
* @access public
* @param string callback function name
* @return void
* @see setLogoutCallback()
*/
function setLoginCallback($loginCallback)
{
$this->loginCallback = $loginCallback;
}
/**
* Register a callback function to be called on user logout.
* The function will receive a single parameter, the username.
*
* @access public
* @param string callback function name
* @return void
* @see setLoginCallback()
*/
function setLogoutCallback($logoutCallback)
{
$this->logoutCallback = $logoutCallback;
}
// }}}
// {{{ setAuthData()
/**
* Register additional information that is to be stored
* in the session.
*
* @access public
* @param string Name of the data field
* @param mixed Value of the data field
* @param boolean Should existing data be overwritten? (default
* is true)
* @return void
*/
function setAuthData($name, $value, $overwrite = true)
{
$session = &DOLIAuth::_importGlobalVariable("session");
if (!empty($session['auth']['data'][$name]) && $overwrite == false) {
return;
}
$session['auth']['data'][$name] = $value;
}
// }}}
// {{{ getAuthData()
/**
* Get additional information that is stored in the session.
*
* If no value for the first parameter is passed, the method will
* return all data that is currently stored.
*
* @access public
* @param string Name of the data field
* @return mixed Value of the data field.
*/
function getAuthData($name = null)
{
$session = &DOLIAuth::_importGlobalVariable("session");
if (is_null($name)) {
return $session['auth']['data'];
}
if (isset($session['auth']['data'][$name])) {
return $session['auth']['data'][$name];
} else {
return null;
}
}
// }}}
// {{{ setAuth()
/**
* Register variable in a session telling that the user
* has logged in successfully
*
* @access public
* @param string Username
* @return void
*/
function setAuth($username)
{
$session = &DOLIAuth::_importGlobalVariable("session");
if (!isset($session['auth']) && !isset($_SESSION)) {
session_register("auth");
}
if (!isset($session['auth']) || !is_array($session['auth'])) {
$session['auth'] = array();
}
if(!isset($session['auth']['data'])){
$session['auth']['data'] = array();
}
$session['auth']['registered'] = true;
$session['auth']['username'] = $username;
$session['auth']['timestamp'] = time();
$session['auth']['idle'] = time();
}
// }}}
// {{{ checkAuth()
/**
* Checks if there is a session with valid auth information.
*
* @access private
* @return boolean Whether or not the user is authenticated.
*/
function checkAuth()
{
$session = &$this->_importGlobalVariable("session");
if (isset($session['auth'])) {
/** Check if authentication session is expired */
if ($this->expire > 0 &&
isset($session['auth']['timestamp']) &&
($session['auth']['timestamp'] + $this->expire) < time()) {
$this->logout();
$this->expired = true;
$this->status = AUTH_EXPIRED;
return false;
}
/** Check if maximum idle time is reached */
if ($this->idle > 0 &&
isset($session['auth']['idle']) &&
($session['auth']['idle'] + $this->idle) < time()) {
$this->logout();
$this->idled = true;
$this->status = AUTH_IDLED;
return false;
}
if (isset($session['auth']['registered']) &&
isset($session['auth']['username']) &&
$session['auth']['registered'] == true &&
$session['auth']['username'] != "") {
DOLIAuth::updateIdle();
return true;
}
}
return false;
}
// }}}
// {{{ getAuth()
/**
* Has the user been authenticated?
*
* @access public
* @return bool True if the user is logged in, otherwise false.
*/
function getAuth()
{
$session = &$this->_importGlobalVariable("session");
if (!empty($session) &&
(isset($session['auth']['registered']) &&
$session['auth']['registered'] === true))
{
return true;
} else {
return false;
}
}
// }}}
// {{{ drawLogin()
/**
* Draw the login form
*
* Normally you will not use this output in your application,
* because you can pass a different function name to the
* constructor. For more information on this, please
* consult the documentation.
*
* @access private
* @param string Username if already entered
* @return void
*/
function drawLogin($username = "")
{
if ($this->loginfunction != "") {
call_user_func($this->loginfunction, $username, $this->status);
} else {
$server = &$this->_importGlobalVariable("server");
echo "<center>\n";
if (!empty($this->status) && $this->status == AUTH_EXPIRED) {
echo "<i>Your session expired. Please login again!</i>\n";
} else if (!empty($this->status) && $this->status == AUTH_IDLED) {
echo "<i>You have been idle for too long. Please login again!</i>\n";
} else if (!empty ($this->status) && $this->status == AUTH_WRONG_LOGIN) {
echo "<i>Wrong login data!</i>\n";
}
DOLIPEAR::raiseError("You are using the built-in login screen of PEAR::Auth.<br/>See the <a href=\"http://pear.php.net/manual/\">manual</a> for details on how to create your own login function.", null);
echo "<form method=\"post\" action=\"" . $server['PHP_SELF'] . "\">\n";
echo "<table border=\"0\" cellpadding=\"2\" cellspacing=\"0\">\n";
echo "<tr>\n";
echo " <td colspan=\"2\" bgcolor=\"#eeeeee\"><b>Login:</b></td>\n";
echo "</tr>\n";
echo "<tr>\n";
echo " <td>Username:</td>\n";
echo " <td><input type=\"text\" name=\"username\" value=\"" . $username . "\"></td>\n";
echo "</tr>\n";
echo "<tr>\n";
echo " <td>Password:</td>\n";
echo " <td><input type=\"password\" name=\"password\"></td>\n";
echo "</tr>\n";
echo "<tr>\n";
echo " <td colspan=\"2\" bgcolor=\"#eeeeee\"><input type=\"submit\"></td>\n";
echo "</tr>\n";
echo "</table>\n";
echo "</form>\n";
echo "</center>\n\n";
}
}
// }}}
// {{{ logout()
/**
* Logout function
*
* This function clears any auth tokens in the currently
* active session and executes the logout callback function,
* if any
*
* @access public
* @return void
*/
function logout()
{
$session = &$this->_importGlobalVariable("session");
if (!empty($this->logoutCallback)) {
call_user_func($this->logoutCallback, $session['auth']['username']);
}
$this->username = "";
$this->password = "";
$session['auth'] = array();
if (isset($_SESSION)) {
unset($session['auth']);
} else {
session_unregister("auth");
}
}
// }}}
// {{{ updateIdle()
/**
* Update the idletime
*
* @access private
* @return void
*/
function updateIdle()
{
$session = &$this->_importGlobalVariable("session");
$session['auth']['idle'] = time();
}
// }}}
// {{{ getUsername()
/**
* Get the username
*
* @access public
* @return string
*/
function getUsername()
{
$session = &$this->_importGlobalVariable("session");
if (!isset($session['auth']['username'])) {
return "";
}
return $session['auth']['username'];
}
// }}}
// {{{ getStatus()
/**
* Get the current status
*
* @access public
* @return string
*/
function getStatus()
{
return $this->status;
}
// }}}
// {{{ sessionValidThru()
/**
* Returns the time up to the session is valid
*
* @access public
* @return integer
*/
function sessionValidThru()
{
$session = &$this->_importGlobalVariable("session");
if (!isset($session['auth']['idle'])) {
return 0;
}
return ($session['auth']['idle'] + $this->idle);
}
// }}}
// {{{ listUsers()
/**
* List all users that are currently available in the storage
* container
*
* @access public
* @return array
*/
function listUsers()
{
return $this->storage->listUsers();
}
// }}}
// {{{ addUser()
/**
* Add user to the storage container
*
* @access public
* @param string Username
* @param string Password
* @param mixed Additional parameters
* @return mixed True on success, PEAR error object on error
* and AUTH_METHOD_NOT_SUPPORTED otherwise.
*/
function addUser($username, $password, $additional = "")
{
return $this->storage->addUser($username, $password, $additional);
}
// }}}
// {{{ removeUser()
/**
* Remove user from the storage container
*
* @access public
* @param string Username
* @return mixed True on success, PEAR error object on error
* and AUTH_METHOD_NOT_SUPPORTED otherwise.
*/
function removeUser($username)
{
return $this->storage->removeUser($username);
}
// }}}
// {{{ _importGlobalVariable()
/**
* Import variables from special namespaces.
*
* @access private
* @param string Type of variable (server, session, post)
* @return array
*/
function &_importGlobalVariable($variable)
{
$var = null;
switch (strtolower($variable)) {
case "server" :
if (isset($_SERVER)) {
$var = &$_SERVER;
} else {
$var = &$GLOBALS['HTTP_SERVER_VARS'];
}
break;
case "session" :
if (isset($_SESSION)) {
$var = &$_SESSION;
} else {
$var = &$GLOBALS['HTTP_SESSION_VARS'];
}
break;
case "post" :
if (isset($_POST)) {
$var = &$_POST;
} else {
$var = &$GLOBALS['HTTP_POST_VARS'];
}
break;
case "cookie" :
if (isset($_COOKIE)) {
$var = &$_COOKIE;
} else {
$var = &$GLOBALS['HTTP_COOKIE_VARS'];
}
break;
case "get" :
if (isset($_GET)) {
$var = &$_GET;
} else {
$var = &$GLOBALS['HTTP_GET_VARS'];
}
break;
default:
break;
}
return $var;
}
// }}}
}
?>

View File

@ -1,152 +0,0 @@
<?php
//
// +----------------------------------------------------------------------+
// | PHP Version 4 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1997-2003 The PHP Group |
// +----------------------------------------------------------------------+
// | This source file is subject to version 2.02 of the PHP license, |
// | that is bundled with this package in the file LICENSE, and is |
// | available at through the world-wide-web at |
// | http://www.php.net/license/2_02.txt. |
// | If you did not receive a copy of the PHP license and are unable to |
// | obtain it through the world-wide-web, please send a note to |
// | license@php.net so we can mail you a copy immediately. |
// +----------------------------------------------------------------------+
// | Authors: Martin Jansen <mj@php.net> |
// +----------------------------------------------------------------------+
//
// $Id$
//
define("AUTH_METHOD_NOT_SUPPORTED", -4);
/**
* Storage class for fetching login data
*
* @author Martin Jansen <mj@php.net>
* @package Auth
*/
class Auth_Container
{
/**
* User that is currently selected from the storage container.
*
* @access public
*/
var $activeUser = "";
// {{{ Constructor
/**
* Constructor
*
* Has to be overwritten by each storage class
*
* @access public
*/
function Auth_Container()
{
}
// }}}
// {{{ fetchData()
/**
* Fetch data from storage container
*
* Has to be overwritten by each storage class
*
* @access public
*/
function fetchData()
{
}
// }}}
// {{{ verifyPassword()
/**
* Crypt and verfiy the entered password
*
* @param string Entered password
* @param string Password from the data container (usually this password
* is already encrypted.
* @param string Type of algorithm with which the password from
* the container has been crypted. (md5, crypt etc.)
* Defaults to "md5".
* @return bool True, if the passwords match
*/
function verifyPassword($password1, $password2, $cryptType = "md5")
{
switch ($cryptType) {
case "crypt" :
return (($password2 == "**" . $password1) ||
(crypt($password1, $password2) == $password2)
);
break;
case "none" :
return ($password1 == $password2);
break;
case "md5" :
return (md5($password1) == $password2);
break;
default :
if (function_exists($cryptType)) {
return ($cryptType($password1) == $password2);
} else {
return false;
}
break;
}
}
// }}}
// {{{ listUsers()
/**
* List all users that are available from the storage container
*/
function listUsers()
{
return AUTH_METHOD_NOT_SUPPORTED;
}
// }}}
// {{{ addUser()
/**
* Add a new user to the storage container
*
* @param string Username
* @param string Password
* @param array Additional information
*
* @return boolean
*/
function addUser($username, $password, $additional=null)
{
return AUTH_METHOD_NOT_SUPPORTED;
}
// }}}
// {{{ removeUser()
/**
* Remove user from the storage container
*
* @param string Username
*/
function removeUser($username)
{
return AUTH_METHOD_NOT_SUPPORTED;
}
// }}}
}
?>

View File

@ -1,394 +0,0 @@
<?php
//
// +----------------------------------------------------------------------+
// | PHP Version 4 |
// +----------------------------------------------------------------------+
// | |
// +----------------------------------------------------------------------+
// | This source file is subject to version 2.02 of the PHP license, |
// | that is bundled with this package in the file LICENSE, and is |
// | available at through the world-wide-web at |
// | http://www.php.net/license/2_02.txt. |
// | If you did not receive a copy of the PHP license and are unable to |
// | obtain it through the world-wide-web, please send a note to |
// | license@php.net so we can mail you a copy immediately. |
// +----------------------------------------------------------------------+
// | Authors: Martin Jansen <mj@php.net> |
// +----------------------------------------------------------------------+
//
// $Id$
//
//require_once 'Auth/Container.php';
require_once PEAR_PATH."/Auth/Container.php";
//require_once 'DB.php';
require_once PEAR_PATH."/DB.php";
/**
* Storage driver for fetching login data from a database
*
* This storage driver can use all databases which are supported
* by the PEAR DB abstraction layer to fetch login data.
*
* @author Martin Jansen <mj@php.net>
* @package Auth
* @version $Revision$
*/
class Auth_Container_DB extends Auth_Container
{
/**
* Additional options for the storage container
* @var array
*/
var $options = array();
/**
* DB object
* @var object
*/
var $db = null;
var $dsn = '';
/**
* User that is currently selected from the DB.
* @var string
*/
var $activeUser = '';
// {{{ Constructor
/**
* Constructor of the container class
*
* Initate connection to the database via PEAR::DB
*
* @param string Connection data or DB object
* @return object Returns an error object if something went wrong
*/
function Auth_Container_DB($dsn)
{
$this->_setDefaults();
if (is_array($dsn)) {
$this->_parseOptions($dsn);
if (empty($this->options['dsn'])) {
DOLIPEAR::raiseError('No connection parameters specified!');
}
} else {
$this->options['dsn'] = $dsn;
}
}
// }}}
// {{{ _connect()
/**
* Connect to database by using the given DSN string
*
* @access private
* @param string DSN string
* @return mixed Object on error, otherwise bool
*/
function _connect($dsn)
{
if (is_string($dsn) || is_array($dsn)) {
$this->db = DB::Connect($dsn);
} elseif (get_parent_class($dsn) == "db_common") {
$this->db = $dsn;
} elseif (DB::isError($dsn)) {
return DOLIPEAR::raiseError($dsn->getMessage(), $dsn->getCode());
} else {
return DOLIPEAR::raiseError('The given dsn was not valid in file ' . __FILE__ . ' at line ' . __LINE__,
41,
DOLIPEAR_ERROR_RETURN,
null,
null
);
}
if (DB::isError($this->db) || DOLIPEAR::isError($this->db)) {
return DOLIPEAR::raiseError($this->db->getMessage(), $this->db->getCode());
} else {
return true;
}
}
// }}}
// {{{ _prepare()
/**
* Prepare database connection
*
* This function checks if we have already opened a connection to
* the database. If that's not the case, a new connection is opened.
*
* @access private
* @return mixed True or a DB error object.
*/
function _prepare()
{
if (!DB::isConnection($this->db)) {
$res = $this->_connect($this->options['dsn']);
if(DB::isError($res) || DOLIPEAR::isError($res)){
return $res;
}
}
return true;
}
// }}}
// {{{ query()
/**
* Prepare query to the database
*
* This function checks if we have already opened a connection to
* the database. If that's not the case, a new connection is opened.
* After that the query is passed to the database.
*
* @access public
* @param string Query string
* @return mixed a DB_result object or DB_OK on success, a DB
* or PEAR error on failure
*/
function query($query)
{
$err = $this->_prepare();
if ($err !== true) {
return $err;
}
return $this->db->query($query);
}
// }}}
// {{{ _setDefaults()
/**
* Set some default options
*
* @access private
* @return void
*/
function _setDefaults()
{
$this->options['table'] = 'auth';
$this->options['usernamecol'] = 'username';
$this->options['passwordcol'] = 'password';
$this->options['dsn'] = '';
$this->options['db_fields'] = '';
$this->options['cryptType'] = 'md5';
}
// }}}
// {{{ _parseOptions()
/**
* Parse options passed to the container class
*
* @access private
* @param array
*/
function _parseOptions($array)
{
foreach ($array as $key => $value) {
if (isset($this->options[$key])) {
$this->options[$key] = $value;
}
}
/* Include additional fields if they exist */
if(!empty($this->options['db_fields'])){
if(is_array($this->options['db_fields'])){
$this->options['db_fields'] = join($this->options['db_fields'], ', ');
}
$this->options['db_fields'] = ', '.$this->options['db_fields'];
}
}
// }}}
// {{{ fetchData()
/**
* Get user information from database
*
* This function uses the given username to fetch
* the corresponding login data from the database
* table. If an account that matches the passed username
* and password is found, the function returns true.
* Otherwise it returns false.
*
* @param string Username
* @param string Password
* @return mixed Error object or boolean
*/
function fetchData($username, $password)
{
// Prepare for a database query
$err = $this->_prepare();
if ($err !== true) {
return DOLIPEAR::raiseError($err->getMessage(), $err->getCode());
}
// Find if db_fileds contains a *, i so assume all col are selected
if(strstr($this->options['db_fields'], '*')){
$sql_from = "*";
}
else{
$sql_from = $this->options['usernamecol'] . ", ".$this->options['passwordcol'].$this->options['db_fields'];
}
$query = "SELECT ! FROM ! WHERE ! = ?";
$query_params = array(
$sql_from,
$this->options['table'],
$this->options['usernamecol'],
$username
);
$res = $this->db->getRow($query, $query_params, DB_FETCHMODE_ASSOC);
if (DB::isError($res)) {
return DOLIPEAR::raiseError($res->getMessage(), $res->getCode());
}
if (!is_array($res)) {
$this->activeUser = '';
return false;
}
if ($this->verifyPassword(trim($password),
trim($res[$this->options['passwordcol']]),
$this->options['cryptType'])) {
// Store additional field values in the session
foreach ($res as $key => $value) {
if ($key == $this->options['passwordcol'] ||
$key == $this->options['usernamecol']) {
continue;
}
Auth::setAuthData($key, $value);
}
return true;
}
$this->activeUser = $res[$this->options['usernamecol']];
return false;
}
// }}}
// {{{ listUsers()
function listUsers()
{
$err = $this->_prepare();
if ($err !== true) {
return DOLIPEAR::raiseError($err->getMessage(), $err->getCode());
}
$retVal = array();
// Find if db_fileds contains a *, i so assume all col are selected
if(strstr($this->options['db_fields'], '*') || empty($this->options['db_fields'])){
$sql_from = "*";
}
else{
$sql_from = $this->options['usernamecol'] . ", ".$this->options['passwordcol'].$this->options['db_fields'];
}
$query = sprintf("SELECT %s FROM %s",
$sql_from,
$this->options['table']
);
$res = $this->db->getAll($query, null, DB_FETCHMODE_ASSOC);
if (DB::isError($res)) {
return DOLIPEAR::raiseError($res->getMessage(), $res->getCode());
} else {
foreach ($res as $user) {
$user['username'] = $user[$this->options['usernamecol']];
$retVal[] = $user;
}
}
return $retVal;
}
// }}}
// {{{ addUser()
/**
* Add user to the storage container
*
* @access public
* @param string Username
* @param string Password
* @param mixed Additional information that are stored in the DB
*
* @return mixed True on success, otherwise error object
*/
function addUser($username, $password, $additional = "")
{
if (function_exists($this->options['cryptType'])) {
$cryptfunction = $this->options['cryptType'];
} else {
$cryptfunction = 'md5';
}
$additional_key = '';
$additional_value = '';
if (is_array($additional)) {
foreach ($additional as $key => $value) {
$additional_key .= ', ' . $key;
$additional_value .= ", '" . $value . "'";
}
}
$query = sprintf("INSERT INTO %s (%s, %s%s) VALUES ('%s', '%s'%s)",
$this->options['table'],
$this->options['usernamecol'],
$this->options['passwordcol'],
$additional_key,
$username,
$cryptfunction($password),
$additional_value
);
$res = $this->query($query);
if (DB::isError($res)) {
return DOLIPEAR::raiseError($res->getMessage(), $res->getCode());
} else {
return true;
}
}
// }}}
// {{{ removeUser()
/**
* Remove user from the storage container
*
* @access public
* @param string Username
*
* @return mixed True on success, otherwise error object
*/
function removeUser($username)
{
$query = sprintf("DELETE FROM %s WHERE %s = '%s'",
$this->options['table'],
$this->options['usernamecol'],
$username
);
$res = $this->query($query);
if (DB::isError($res)) {
return DOLIPEAR::raiseError($res->getMessage(), $res->getCode());
} else {
return true;
}
}
// }}}
}
?>

View File

@ -1,527 +0,0 @@
<?php
//
// +----------------------------------------------------------------------+
// | PHP Version 4 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1997-2003 The PHP Group |
// +----------------------------------------------------------------------+
// | This source file is subject to version 2.02 of the PHP license, |
// | that is bundled with this package in the file LICENSE, and is |
// | available at through the world-wide-web at |
// | http://www.php.net/license/2_02.txt. |
// | If you did not receive a copy of the PHP license and are unable to |
// | obtain it through the world-wide-web, please send a note to |
// | license <at> php <dot> net so we can mail you a copy immediately. |
// +----------------------------------------------------------------------+
// | Authors: Jan Wagner <wagner <at> netsols <dot> de> |
// +----------------------------------------------------------------------+
//
// $Id$
//
// require_once 'PEAR.php';
// require_once 'Auth/Container.php';
require_once PEAR_PATH."/PEAR.php";
require_once PEAR_PATH."/Auth/Container.php";
/**
* Storage driver for fetching login data from LDAP
*
* This class is heavily based on the DB and File containers. By default it
* connects to localhost:389 and searches for uid=$username with the scope
* "sub". If no search base is specified, it will try to determine it via
* the namingContexts attribute. It takes its parameters in a hash, connects
* to the ldap server, binds anonymously, searches for the user, and tries
* to bind as the user with the supplied password. When a group was set, it
* will look for group membership of the authenticated user. If all goes
* well the authentication was successful.
*
* Parameters:
*
* host: localhost (default), ldap.netsols.de or 127.0.0.1
* port: 389 (default) or 636 or whereever your server runs
* url: ldap://localhost:389/
* useful for ldaps://, works only with openldap2 ?
* it will be preferred over host and port
* version: LDAP version to use, ususally 2 (default) or 3,
* must be an integer!
* binddn: If set, searching for user will be done after binding
* as this user, if not set the bind will be anonymous.
* This is reported to make the container work with MS
* Active Directory, but should work with any server that
* is configured this way.
* This has to be a complete dn for now (basedn and
* userdn will not be appended).
* bindpw: The password to use for binding with binddn
* basedn: the base dn of your server
* userdn: gets prepended to basedn when searching for user
* userscope: Scope for user searching: one, sub (default), or base
* userattr: the user attribute to search for (default: uid)
* userfilter: filter that will be added to the search filter
* this way: (&(userattr=username)(userfilter))
* default: (objectClass=posixAccount)
* attributes: array of additional attributes to fetch from entry.
* these will added to auth data and can be retrieved via
* Auth::getAuthData(). An empty array will fetch all attributes,
* array('') will fetch no attributes at all (default)
* groupdn: gets prepended to basedn when searching for group
* groupattr: the group attribute to search for (default: cn)
* groupfilter: filter that will be added to the search filter when
* searching for a group:
* (&(groupattr=group)(memberattr=username)(groupfilter))
* default: (objectClass=groupOfUniqueNames)
* memberattr : the attribute of the group object where the user dn
* may be found (default: uniqueMember)
* memberisdn: whether the memberattr is the dn of the user (default)
* or the value of userattr (usually uid)
* group: the name of group to search for
* groupscope: Scope for group searching: one, sub (default), or base
* debug: Enable/Disable debugging output (default: false)
*
* To use this storage container, you have to use the following syntax:
*
* <?php
* ...
*
* $a = new Auth("LDAP", array(
* 'host' => 'localhost',
* 'port' => '389',
* 'version' => 3,
* 'basedn' => 'o=netsols, c=de',
* 'userattr' => 'uid'
* 'binddn' => 'cn=admin, o=netsols, c=de',
* 'bindpw' => 'password'));
*
* $a2 = new Auth('LDAP', array(
* 'url' => 'ldaps://ldap.netsols.de',
* 'basedn' => 'o=netsols, c=de',
* 'userscope' => 'one',
* 'userdn' => 'ou=People',
* 'groupdn' => 'ou=Groups',
* 'groupfilter' => '(objectClass=posixGroup)',
* 'memberattr' => 'memberUid',
* 'memberisdn' => false,
* 'group' => 'admin'
* ));
*
* This is a full blown example with user/group checking to an Active Directory
*
* $a3 = new Auth('LDAP', array(
* 'host' => 'ldap.netsols.de',
* 'port' => 389,
* 'version' => 3,
* 'basedn' => 'dc=netsols, dc=de',
* 'binddn' => 'cn=Jan Wagner, cn=Users, dc=netsols, dc=de',
* 'bindpw' => 'password',
* 'userattr' => 'samAccountName',
* 'userfilter' => '(objectClass=user)',
* 'attributes' => array(''),
* 'group' => 'testing',
* 'groupattr' => 'samAccountName',
* 'groupfilter' => '(objectClass=group)',
* 'memberattr' => 'member',
* 'memberisdn' => true,
* 'groupdn' => 'cn=Users',
* 'groupscope' => 'one',
* 'debug' => true);
*
* The parameter values have to correspond
* to the ones for your LDAP server of course.
*
* When talking to a Microsoft ActiveDirectory server you have to
* use 'samaccountname' as the 'userattr' and follow special rules
* to translate the ActiveDirectory directory names into 'basedn'.
* The 'basedn' for the default 'Users' folder on an ActiveDirectory
* server for the ActiveDirectory Domain (which is not related to
* its DNS name) "win2000.example.org" would be:
* "CN=Users, DC=win2000, DC=example, DC=org'
* where every component of the domain name becomes a DC attribute
* of its own. If you want to use a custom users folder you have to
* replace "CN=Users" with a sequence of "OU" attributes that specify
* the path to your custom folder in reverse order.
* So the ActiveDirectory folder
* "win2000.example.org\Custom\Accounts"
* would become
* "OU=Accounts, OU=Custom, DC=win2000, DC=example, DC=org'
*
* It seems that binding anonymously to an Active Directory
* is not allowed, so you have to set binddn and bindpw for
* user searching,
*
* Example a3 shows a tested example for connenction to Windows 2000
* Active Directory
*
* @author Jan Wagner <wagner <at> netsols <dot> de>
* @package Auth
* @version $Revision$
*/
class Auth_Container_LDAP extends Auth_Container
{
/**
* Options for the class
* @var array
*/
var $options = array();
/**
* Connection ID of LDAP Link
* @var string
*/
var $conn_id = false;
/**
* Constructor of the container class
*
* @param $params, associative hash with host, port, basedn and userattr key
* @return object Returns an error object if something went wrong
*/
function Auth_Container_LDAP($params)
{
if (false === extension_loaded('ldap')) {
return DOLIPEAR::raiseError('Auth_Container_LDAP: LDAP Extension not loaded', 41, PEAR_ERROR_DIE);
}
$this->_setDefaults();
if (is_array($params)) {
$this->_parseOptions($params);
}
}
// }}}
// {{{ _connect()
/**
* Connect to the LDAP server using the global options
*
* @access private
* @return object Returns a PEAR error object if an error occurs.
*/
function _connect()
{
// connect
if (isset($this->options['url']) && $this->options['url'] != '') {
$this->_debug('Connecting with URL', __LINE__);
$conn_params = array($this->options['url']);
} else {
$this->_debug('Connecting with host:port', __LINE__);
$conn_params = array($this->options['host'], $this->options['port']);
}
if (($this->conn_id = @call_user_func_array('ldap_connect', $conn_params)) === false) {
return DOLIPEAR::raiseError('Auth_Container_LDAP: Could not connect to server.', 41, PEAR_ERROR_DIE);
}
$this->_debug('Successfully connected to server', __LINE__);
// switch LDAP version
if (is_int($this->options['version']) && $this->options['version'] > 2) {
$this->_debug("Switching to LDAP version {$this->options['version']}", __LINE__);
@ldap_set_option($this->conn_id, LDAP_OPT_PROTOCOL_VERSION, $this->options['version']);
}
// bind with credentials or anonymously
if ($this->options['binddn'] && $this->options['bindpw']) {
$this->_debug('Binding with credentials', __LINE__);
$bind_params = array($this->conn_id, $this->options['binddn'], $this->options['bindpw']);
} else {
$this->_debug('Binding anonymously', __LINE__);
$bind_params = array($this->conn_id);
}
// bind for searching
if ((@call_user_func_array('ldap_bind', $bind_params)) == false) {
$this->_debug();
$this->_disconnect();
return DOLIPEAR::raiseError("Auth_Container_LDAP: Could not bind to LDAP server.", 41, PEAR_ERROR_DIE);
}
$this->_debug('Binding was successful', __LINE__);
}
/**
* Disconnects (unbinds) from ldap server
*
* @access private
*/
function _disconnect()
{
if ($this->_isValidLink()) {
$this->_debug('disconnecting from server');
@ldap_unbind($this->conn_id);
}
}
/**
* Tries to find Basedn via namingContext Attribute
*
* @access private
*/
function _getBaseDN()
{
if ($this->options['basedn'] == "" && $this->_isValidLink()) {
$this->_debug("basedn not set, searching via namingContexts.", __LINE__);
$result_id = @ldap_read($this->conn_id, "", "(objectclass=*)", array("namingContexts"));
if (@ldap_count_entries($this->conn_id, $result_id) == 1) {
$this->_debug("got result for namingContexts", __LINE__);
$entry_id = @ldap_first_entry($this->conn_id, $result_id);
$attrs = @ldap_get_attributes($this->conn_id, $entry_id);
$basedn = $attrs['namingContexts'][0];
if ($basedn != "") {
$this->_debug("result for namingContexts was $basedn", __LINE__);
$this->options['basedn'] = $basedn;
}
}
@ldap_free_result($result_id);
}
// if base ist still not set, raise error
if ($this->options['basedn'] == "") {
return DOLIPEAR::raiseError("Auth_Container_LDAP: LDAP search base not specified!", 41, PEAR_ERROR_DIE);
}
return true;
}
/**
* determines whether there is a valid ldap conenction or not
*
* @accessd private
* @return boolean
*/
function _isValidLink()
{
if (is_resource($this->conn_id)) {
if (get_resource_type($this->conn_id) == 'ldap link') {
return true;
}
}
return false;
}
/**
* Set some default options
*
* @access private
*/
function _setDefaults()
{
$this->options['url'] = '';
$this->options['host'] = 'localhost';
$this->options['port'] = '389';
$this->options['version'] = 2;
$this->options['binddn'] = '';
$this->options['bindpw'] = '';
$this->options['basedn'] = '';
$this->options['userdn'] = '';
$this->options['userscope'] = 'sub';
$this->options['userattr'] = "uid";
$this->options['userfilter'] = '(objectClass=posixAccount)';
$this->options['attributes'] = array(''); // no attributes
$this->options['group'] = '';
$this->options['groupdn'] = '';
$this->options['groupscope'] = 'sub';
$this->options['groupattr'] = 'cn';
$this->options['groupfilter'] = '(objectClass=groupOfUniqueNames)';
$this->options['memberattr'] = 'uniqueMember';
$this->options['memberisdn'] = true;
$this->options['debug'] = false;
}
/**
* Parse options passed to the container class
*
* @access private
* @param array
*/
function _parseOptions($array)
{
foreach ($array as $key => $value) {
if (array_key_exists($key, $this->options)) {
$this->options[$key] = $value;
}
}
}
/**
* Get search function for scope
*
* @param string scope
* @return string ldap search function
*/
function _scope2function($scope)
{
switch($scope) {
case 'one':
$function = 'ldap_list';
break;
case 'base':
$function = 'ldap_read';
break;
default:
$function = 'ldap_search';
break;
}
return $function;
}
/**
* Fetch data from LDAP server
*
* Searches the LDAP server for the given username/password
* combination.
*
* @param string Username
* @param string Password
* @return boolean
*/
function fetchData($username, $password)
{
$this->_connect();
$this->_getBaseDN();
// UTF8 Encode username for LDAPv3
if (@ldap_get_option($this->conn_id, LDAP_OPT_PROTOCOL_VERSION, $ver) && $ver == 3) {
$this->_debug('UTF8 encoding username for LDAPv3', __LINE__);
$username = utf8_encode($username);
}
// make search filter
$filter = sprintf('(&(%s=%s)%s)',
$this->options['userattr'],
$username,
$this->options['userfilter']);
// make search base dn
$search_basedn = $this->options['userdn'];
if ($search_basedn != '' && substr($search_basedn, -1) != ', ') {
$search_basedn .= ', ';
}
$search_basedn .= $this->options['basedn'];
// attributes
$attributes = $this->options['attributes'];
// make functions params array
$func_params = array($this->conn_id, $search_basedn, $filter, $attributes);
// search function to use
$func_name = $this->_scope2function($this->options['userscope']);
$this->_debug("Searching with $func_name and filter $filter in $search_basedn", __LINE__);
// search
if (($result_id = @call_user_func_array($func_name, $func_params)) == false) {
$this->_debug('User not found', __LINE__);
} elseif (@ldap_count_entries($this->conn_id, $result_id) == 1) { // did we get just one entry?
$this->_debug('User was found', __LINE__);
// then get the user dn
$entry_id = @ldap_first_entry($this->conn_id, $result_id);
$user_dn = @ldap_get_dn($this->conn_id, $entry_id);
// fetch attributes
if ($attributes = @ldap_get_attributes($this->conn_id, $entry_id)) {
if (is_array($attributes) && isset($attributes['count']) &&
$attributes['count'] > 0)
{
$this->_debug('Saving attributes to Auth data', __LINE__);
DOLIAuth::setAuthData('attributes', $attributes);
}
}
@ldap_free_result($result_id);
// need to catch an empty password as openldap seems to return TRUE
// if anonymous binding is allowed
if ($password != "") {
$this->_debug("Bind as $user_dn", __LINE__);
// try binding as this user with the supplied password
if (@ldap_bind($this->conn_id, $user_dn, $password)) {
$this->_debug('Bind successful', __LINE__);
// check group if appropiate
if (strlen($this->options['group'])) {
// decide whether memberattr value is a dn or the username
$this->_debug('Checking group membership', __LINE__);
return $this->checkGroup(($this->options['memberisdn']) ? $user_dn : $username);
} else {
$this->_debug('Authenticated', __LINE__);
$this->_disconnect();
return true; // user authenticated
} // checkGroup
} // bind
} // non-empty password
} // one entry
// default
$this->_debug('NOT authenticated!', __LINE__);
$this->_disconnect();
return false;
}
/**
* Validate group membership
*
* Searches the LDAP server for group membership of the
* authenticated user
*
* @param string Distinguished Name of the authenticated User
* @return boolean
*/
function checkGroup($user)
{
// make filter
$filter = sprintf('(&(%s=%s)(%s=%s)%s)',
$this->options['groupattr'],
$this->options['group'],
$this->options['memberattr'],
$user,
$this->options['groupfilter']);
// make search base dn
$search_basedn = $this->options['groupdn'];
if ($search_basedn != '' && substr($search_basedn, -1) != ', ') {
$search_basedn .= ', ';
}
$search_basedn .= $this->options['basedn'];
$func_params = array($this->conn_id, $search_basedn, $filter,
array($this->options['memberattr']));
$func_name = $this->_scope2function($this->options['groupscope']);
$this->_debug("Searching with $func_name and filter $filter in $search_basedn", __LINE__);
// search
if (($result_id = @call_user_func_array($func_name, $func_params)) != false) {
if (@ldap_count_entries($this->conn_id, $result_id) == 1) {
@ldap_free_result($result_id);
$this->_debug('User is member of group', __LINE__);
$this->_disconnect();
return true;
}
}
// default
$this->_debug('User is NOT member of group', __LINE__);
$this->_disconnect();
return false;
}
/**
* Outputs debugging messages
*
* @access private
* @param string Debugging Message
* @param integer Line number
*/
function _debug($msg = '', $line = 0)
{
if ($this->options['debug'] === true) {
if ($msg == '' && $this->_isValidLink()) {
$msg = 'LDAP_Error: ' . @ldap_err2str(@ldap_errno($this->_conn_id));
}
print("$line: $msg <br />");
}
}
}
?>

View File

@ -1,548 +0,0 @@
<?php
/**
* Storage driver for use against PEAR MDB2
*
* PHP versions 4 and 5
*
* LICENSE: This source file is subject to version 3.01 of the PHP license
* that is available through the world-wide-web at the following URI:
* http://www.php.net/license/3_01.txt. If you did not receive a copy of
* the PHP License and are unable to obtain it through the web, please
* send a note to license@php.net so we can mail you a copy immediately.
*
* @category Authentication
* @package Auth
* @author Lorenzo Alberton <l.alberton@quipo.it>
* @author Adam Ashley <aashley@php.net>
* @copyright 2001-2006 The PHP Group
* @license http://www.php.net/license/3_01.txt PHP License 3.01
* @version CVS: $Id$
* @link http://pear.php.net/package/Auth
* @since File available since Release 1.3.0
*/
/**
* Include Auth_Container base class
*/
//require_once 'Auth/Container.php';
require_once PEAR_PATH."/Auth/Container.php";
/**
* Include PEAR MDB2 package
*/
//require_once 'MDB2.php';
require_once PEAR_PATH."/MDB2.php";
/**
* Storage driver for fetching login data from a database
*
* This storage driver can use all databases which are supported
* by the PEAR MDB2 abstraction layer to fetch login data.
*
* @category Authentication
* @package Auth
* @author Lorenzo Alberton <l.alberton@quipo.it>
* @author Adam Ashley <aashley@php.net>
* @copyright 2001-2006 The PHP Group
* @license http://www.php.net/license/3_01.txt PHP License 3.01
* @version Release: @package_version@ File: $Revision$
* @link http://pear.php.net/package/Auth
* @since Class available since Release 1.3.0
*/
class Auth_Container_MDB2 extends Auth_Container
{
// {{{ properties
/**
* Additional options for the storage container
* @var array
*/
var $options = array();
/**
* MDB object
* @var object
*/
var $db = null;
var $dsn = '';
/**
* User that is currently selected from the DB.
* @var string
*/
var $activeUser = '';
// }}}
// {{{ Auth_Container_MDB2() [constructor]
/**
* Constructor of the container class
*
* Initate connection to the database via PEAR::MDB2
*
* @param string Connection data or MDB2 object
* @return object Returns an error object if something went wrong
*/
function Auth_Container_MDB2($dsn)
{
$this->_setDefaults();
if (is_array($dsn)) {
$this->_parseOptions($dsn);
if (empty($this->options['dsn'])) {
DOLIPEAR::raiseError('No connection parameters specified!');
}
} else {
$this->options['dsn'] = $dsn;
}
}
// }}}
// {{{ _connect()
/**
* Connect to database by using the given DSN string
*
* @access private
* @param mixed DSN string | array | mdb object
* @return mixed Object on error, otherwise bool
*/
function _connect($dsn)
{
if (is_string($dsn) || is_array($dsn)) {
$this->db =& MDB2::connect($dsn, $this->options['db_options']);
} elseif (is_subclass_of($dsn, 'MDB2_Driver_Common')) {
$this->db = $dsn;
} elseif (is_object($dsn) && MDB2::isError($dsn)) {
return DOLIPEAR::raiseError($dsn->getMessage(), $dsn->code);
} else {
return DOLIPEAR::raiseError('The given dsn was not valid in file ' . __FILE__ . ' at line ' . __LINE__,
41,
DOLIPEAR_ERROR_RETURN,
null,
null
);
}
if (MDB2::isError($this->db) || DOLIPEAR::isError($this->db)) {
return DOLIPEAR::raiseError($this->db->getMessage(), $this->db->code);
}
return true;
}
// }}}
// {{{ _prepare()
/**
* Prepare database connection
*
* This function checks if we have already opened a connection to
* the database. If that's not the case, a new connection is opened.
*
* @access private
* @return mixed True or a MDB error object.
*/
function _prepare()
{
if (is_subclass_of($this->db, 'MDB2_Driver_Common')) {
return true;
}
return $this->_connect($this->options['dsn']);
}
// }}}
// {{{ query()
/**
* Prepare query to the database
*
* This function checks if we have already opened a connection to
* the database. If that's not the case, a new connection is opened.
* After that the query is passed to the database.
*
* @access public
* @param string Query string
* @return mixed a MDB_result object or MDB_OK on success, a MDB
* or PEAR error on failure
*/
function query($query)
{
$err = $this->_prepare();
if ($err !== true) {
return $err;
}
return $this->db->exec($query);
}
// }}}
// {{{ _setDefaults()
/**
* Set some default options
*
* @access private
* @return void
*/
function _setDefaults()
{
$this->options['table'] = 'auth';
$this->options['usernamecol'] = 'username';
$this->options['passwordcol'] = 'password';
$this->options['dsn'] = '';
$this->options['db_fields'] = '';
$this->options['cryptType'] = 'md5';
$this->options['db_options'] = array();
}
// }}}
// {{{ _parseOptions()
/**
* Parse options passed to the container class
*
* @access private
* @param array
*/
function _parseOptions($array)
{
foreach ($array as $key => $value) {
if (isset($this->options[$key])) {
$this->options[$key] = $value;
}
}
}
// }}}
// {{{ _quoteDBFields()
/**
* Quote the db_fields option to avoid the possibility of SQL injection.
*
* @access private
* @return string A properly quoted string that can be concatenated into a
* SELECT clause.
*/
function _quoteDBFields()
{
if (isset($this->options['db_fields'])) {
if (is_array($this->options['db_fields'])) {
$fields = array();
foreach ($this->options['db_fields'] as $field) {
$fields[] = $this->db->quoteIdentifier($field, true);
}
return implode(', ', $fields);
} else {
if (strlen($this->options['db_fields']) > 0) {
return $this->db->quoteIdentifier($this->options['db_fields'], true);
}
}
}
return '';
}
// }}}
// {{{ fetchData()
/**
* Get user information from database
*
* This function uses the given username to fetch
* the corresponding login data from the database
* table. If an account that matches the passed username
* and password is found, the function returns true.
* Otherwise it returns false.
*
* @param string Username
* @param string Password
* @param boolean If true password is secured using a md5 hash
* the frontend and auth are responsible for making sure the container supports
* challenge response password authentication
* @return mixed Error object or boolean
*/
function fetchData($username, $password, $isChallengeResponse=false)
{
// Prepare for a database query
$err = $this->_prepare();
if ($err !== true) {
return DOLIPEAR::raiseError($err->getMessage(), $err->getCode());
}
//Check if db_fields contains a *, if so assume all columns are selected
if (is_string($this->options['db_fields'])
&& strstr($this->options['db_fields'], '*')) {
$sql_from = '*';
} else {
$sql_from = $this->db->quoteIdentifier($this->options['usernamecol'], true).
", ".$this->db->quoteIdentifier($this->options['passwordcol'], true);
if (strlen($fields = $this->_quoteDBFields()) > 0) {
$sql_from .= ', '.$fields;
}
}
$query = sprintf("SELECT %s FROM %s WHERE %s = %s",
$sql_from,
$this->db->quoteIdentifier($this->options['table'], true),
$this->db->quoteIdentifier($this->options['usernamecol'], true),
$this->db->quote($username, 'text')
);
$res = $this->db->queryRow($query, null, MDB2_FETCHMODE_ASSOC);
if (MDB2::isError($res) || DOLIPEAR::isError($res)) {
return DOLIPEAR::raiseError($res->getMessage(), $res->getCode());
}
if (!is_array($res)) {
$this->activeUser = '';
return false;
}
// Perform trimming here before the hashing
$password = trim($password, "\r\n");
$res[$this->options['passwordcol']] = trim($res[$this->options['passwordcol']], "\r\n");
// If using Challenge Response md5 the pass with the secret
if ($isChallengeResponse) {
$res[$this->options['passwordcol']] =
md5($res[$this->options['passwordcol']].$this->_auth_obj->session['loginchallenege']);
// UGLY cannot avoid without modifying verifyPassword
if ($this->options['cryptType'] == 'md5') {
$res[$this->options['passwordcol']] = md5($res[$this->options['passwordcol']]);
}
}
if ($this->verifyPassword($password,
$res[$this->options['passwordcol']],
$this->options['cryptType'])) {
// Store additional field values in the session
foreach ($res as $key => $value) {
if ($key == $this->options['passwordcol'] ||
$key == $this->options['usernamecol']) {
continue;
}
// Use reference to the auth object if exists
// This is because the auth session variable can change so a static call to setAuthData does not make sense
$this->_auth_obj->setAuthData($key, $value);
}
return true;
}
$this->activeUser = $res[$this->options['usernamecol']];
return false;
}
// }}}
// {{{ listUsers()
/**
* Returns a list of users from the container
*
* @return mixed array|PEAR_Error
* @access public
*/
function listUsers()
{
$err = $this->_prepare();
if ($err !== true) {
return DOLIPEAR::raiseError($err->getMessage(), $err->getCode());
}
$retVal = array();
//Check if db_fields contains a *, if so assume all columns are selected
if (strstr($this->options['db_fields'], '*')) {
$sql_from = '*';
} else {
$sql_from = $this->db->quoteIdentifier($this->options['usernamecol'], true).
", ".$this->db->quoteIdentifier($this->options['passwordcol'], true);
if (strlen($fields = $this->_quoteDBFields()) > 0) {
$sql_from .= ', '.$fields;
}
}
$query = sprintf('SELECT %s FROM %s',
$sql_from,
$this->db->quoteIdentifier($this->options['table'], true)
);
$res = $this->db->queryAll($query, null, MDB2_FETCHMODE_ASSOC);
if (MDB2::isError($res)) {
return DOLIPEAR::raiseError($res->getMessage(), $res->getCode());
} else {
foreach ($res as $user) {
$user['username'] = $user[$this->options['usernamecol']];
$retVal[] = $user;
}
}
return $retVal;
}
// }}}
// {{{ addUser()
/**
* Add user to the storage container
*
* @access public
* @param string Username
* @param string Password
* @param mixed Additional information that are stored in the DB
*
* @return mixed True on success, otherwise error object
*/
function addUser($username, $password, $additional = "")
{
// Prepare for a database query
$err = $this->_prepare();
if ($err !== true) {
return DOLIPEAR::raiseError($err->getMessage(), $err->getCode());
}
if (isset($this->options['cryptType']) && $this->options['cryptType'] == 'none') {
$cryptFunction = 'strval';
} elseif (isset($this->options['cryptType']) && function_exists($this->options['cryptType'])) {
$cryptFunction = $this->options['cryptType'];
} else {
$cryptFunction = 'md5';
}
$password = $cryptFunction($password);
$additional_key = '';
$additional_value = '';
if (is_array($additional)) {
foreach ($additional as $key => $value) {
$additional_key .= ', ' . $this->db->quoteIdentifier($key, true);
$additional_value .= ', ' . $this->db->quote($value, 'text');
}
}
$query = sprintf("INSERT INTO %s (%s, %s%s) VALUES (%s, %s%s)",
$this->db->quoteIdentifier($this->options['table'], true),
$this->db->quoteIdentifier($this->options['usernamecol'], true),
$this->db->quoteIdentifier($this->options['passwordcol'], true),
$additional_key,
$this->db->quote($username, 'text'),
$this->db->quote($password, 'text'),
$additional_value
);
$res = $this->query($query);
if (MDB2::isError($res)) {
return DOLIPEAR::raiseError($res->getMessage(), $res->code);
}
return true;
}
// }}}
// {{{ removeUser()
/**
* Remove user from the storage container
*
* @access public
* @param string Username
*
* @return mixed True on success, otherwise error object
*/
function removeUser($username)
{
// Prepare for a database query
$err = $this->_prepare();
if ($err !== true) {
return DOLIPEAR::raiseError($err->getMessage(), $err->getCode());
}
$query = sprintf("DELETE FROM %s WHERE %s = %s",
$this->db->quoteIdentifier($this->options['table'], true),
$this->db->quoteIdentifier($this->options['usernamecol'], true),
$this->db->quote($username, 'text')
);
$res = $this->query($query);
if (MDB2::isError($res)) {
return DOLIPEAR::raiseError($res->getMessage(), $res->code);
}
return true;
}
// }}}
// {{{ changePassword()
/**
* Change password for user in the storage container
*
* @param string Username
* @param string The new password (plain text)
*/
function changePassword($username, $password)
{
// Prepare for a database query
$err = $this->_prepare();
if ($err !== true) {
return DOLIPEAR::raiseError($err->getMessage(), $err->getCode());
}
if (isset($this->options['cryptType']) && $this->options['cryptType'] == 'none') {
$cryptFunction = 'strval';
} elseif (isset($this->options['cryptType']) && function_exists($this->options['cryptType'])) {
$cryptFunction = $this->options['cryptType'];
} else {
$cryptFunction = 'md5';
}
$password = $cryptFunction($password);
$query = sprintf("UPDATE %s SET %s = %s WHERE %s = %s",
$this->db->quoteIdentifier($this->options['table'], true),
$this->db->quoteIdentifier($this->options['passwordcol'], true),
$this->db->quote($password, 'text'),
$this->db->quoteIdentifier($this->options['usernamecol'], true),
$this->db->quote($username, 'text')
);
$res = $this->query($query);
if (MDB2::isError($res)) {
return DOLIPEAR::raiseError($res->getMessage(), $res->code);
}
return true;
}
// }}}
// {{{ supportsChallengeResponse()
/**
* Determine if this container supports
* password authentication with challenge response
*
* @return bool
* @access public
*/
function supportsChallengeResponse()
{
return in_array($this->options['cryptType'], array('md5', 'none', ''));
}
// }}}
// {{{ getCryptType()
/**
* Returns the selected crypt type for this container
*
* @return string Function used to crypt the password
*/
function getCryptType()
{
return $this->options['cryptType'];
}
// }}}
}
?>

View File

@ -1,949 +0,0 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 foldmethod=marker: */
// +----------------------------------------------------------------------+
// | PHP Version 4 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1997-2003 The PHP Group |
// +----------------------------------------------------------------------+
// | This source file is subject to version 2.02 of the PHP license, |
// | that is bundled with this package in the file LICENSE, and is |
// | available at through the world-wide-web at |
// | http://www.php.net/license/2_02.txt. |
// | If you did not receive a copy of the PHP license and are unable to |
// | obtain it through the world-wide-web, please send a note to |
// | license@php.net so we can mail you a copy immediately. |
// +----------------------------------------------------------------------+
// | Authors: Stig Bakken <ssb@php.net> |
// | Tomas V.V.Cox <cox@idecnet.com> |
// +----------------------------------------------------------------------+
//
// $Id$
//
// Database independent query interface.
//
//require_once "PEAR.php";
require_once PEAR_PATH."/PEAR.php";
// {{{ constants
// {{{ error codes
/*
* The method mapErrorCode in each DB_dbtype implementation maps
* native error codes to one of these.
*
* If you add an error code here, make sure you also add a textual
* version of it in DB::errorMessage().
*/
define("DB_OK", 1);
define("DB_ERROR", -1);
define("DB_ERROR_SYNTAX", -2);
define("DB_ERROR_CONSTRAINT", -3);
define("DB_ERROR_NOT_FOUND", -4);
define("DB_ERROR_ALREADY_EXISTS", -5);
define("DB_ERROR_UNSUPPORTED", -6);
define("DB_ERROR_MISMATCH", -7);
define("DB_ERROR_INVALID", -8);
define("DB_ERROR_NOT_CAPABLE", -9);
define("DB_ERROR_TRUNCATED", -10);
define("DB_ERROR_INVALID_NUMBER", -11);
define("DB_ERROR_INVALID_DATE", -12);
define("DB_ERROR_DIVZERO", -13);
define("DB_ERROR_NODBSELECTED", -14);
define("DB_ERROR_CANNOT_CREATE", -15);
define("DB_ERROR_CANNOT_DELETE", -16);
define("DB_ERROR_CANNOT_DROP", -17);
define("DB_ERROR_NOSUCHTABLE", -18);
define("DB_ERROR_NOSUCHFIELD", -19);
define("DB_ERROR_NEED_MORE_DATA", -20);
define("DB_ERROR_NOT_LOCKED", -21);
define("DB_ERROR_VALUE_COUNT_ON_ROW", -22);
define("DB_ERROR_INVALID_DSN", -23);
define("DB_ERROR_CONNECT_FAILED", -24);
define("DB_ERROR_EXTENSION_NOT_FOUND",-25);
define("DB_ERROR_ACCESS_VIOLATION", -26);
define("DB_ERROR_NOSUCHDB", -27);
// }}}
// {{{ warning codes
/*
* Warnings are not detected as errors by DB::isError(), and are not
* fatal. You can detect whether an error is in fact a warning with
* DB::isWarning().
*
* @deprecated
*/
define('DB_WARNING', -1000);
define('DB_WARNING_READ_ONLY', -1001);
// }}}
// {{{ prepared statement-related
/*
* These constants are used when storing information about prepared
* statements (using the "prepare" method in DB_dbtype).
*
* The prepare/execute model in DB is mostly borrowed from the ODBC
* extension, in a query the "?" character means a scalar parameter.
* There are two extensions though, a "&" character means an opaque
* parameter. An opaque parameter is simply a file name, the real
* data are in that file (useful for putting uploaded files into your
* database and such). The "!" char means a parameter that must be
* left as it is.
* They modify the quote behavoir:
* DB_PARAM_SCALAR (?) => 'original string quoted'
* DB_PARAM_OPAQUE (&) => 'string from file quoted'
* DB_PARAM_MISC (!) => original string
*/
define('DB_PARAM_SCALAR', 1);
define('DB_PARAM_OPAQUE', 2);
define('DB_PARAM_MISC', 3);
// }}}
// {{{ binary data-related
/*
* These constants define different ways of returning binary data
* from queries. Again, this model has been borrowed from the ODBC
* extension.
*
* DB_BINMODE_PASSTHRU sends the data directly through to the browser
* when data is fetched from the database.
* DB_BINMODE_RETURN lets you return data as usual.
* DB_BINMODE_CONVERT returns data as well, only it is converted to
* hex format, for example the string "123" would become "313233".
*/
define('DB_BINMODE_PASSTHRU', 1);
define('DB_BINMODE_RETURN', 2);
define('DB_BINMODE_CONVERT', 3);
// }}}
// {{{ fetch modes
/**
* This is a special constant that tells DB the user hasn't specified
* any particular get mode, so the default should be used.
*/
define('DB_FETCHMODE_DEFAULT', 0);
/**
* Column data indexed by numbers, ordered from 0 and up
*/
define('DB_FETCHMODE_ORDERED', 1);
/**
* Column data indexed by column names
*/
define('DB_FETCHMODE_ASSOC', 2);
/**
* Column data as object properties
*/
define('DB_FETCHMODE_OBJECT', 3);
/**
* For multi-dimensional results: normally the first level of arrays
* is the row number, and the second level indexed by column number or name.
* DB_FETCHMODE_FLIPPED switches this order, so the first level of arrays
* is the column name, and the second level the row number.
*/
define('DB_FETCHMODE_FLIPPED', 4);
/* for compatibility */
define('DB_GETMODE_ORDERED', DB_FETCHMODE_ORDERED);
define('DB_GETMODE_ASSOC', DB_FETCHMODE_ASSOC);
define('DB_GETMODE_FLIPPED', DB_FETCHMODE_FLIPPED);
// }}}
// {{{ tableInfo() && autoPrepare()-related
/**
* 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 DB_TABLEINFO_FULL accordingly
*/
define('DB_TABLEINFO_ORDER', 1);
define('DB_TABLEINFO_ORDERTABLE', 2);
define('DB_TABLEINFO_FULL', 3);
/*
* Used by autoPrepare()
*/
define('DB_AUTOQUERY_INSERT', 1);
define('DB_AUTOQUERY_UPDATE', 2);
// }}}
// }}}
// {{{ class DB
/**
* The main "DB" class is simply a container class with some static
* methods for creating DB objects as well as some utility functions
* common to all parts of DB.
*
* The object model of DB is as follows (indentation means inheritance):
*
* DB The main DB class. This is simply a utility class
* with some "static" methods for creating DB objects as
* well as common utility functions for other DB classes.
*
* DB_common The base for each DB implementation. Provides default
* | implementations (in OO lingo virtual methods) for
* | the actual DB implementations as well as a bunch of
* | query utility functions.
* |
* +-DB_mysql The DB implementation for MySQL. Inherits DB_common.
* When calling DB::factory or DB::connect for MySQL
* connections, the object returned is an instance of this
* class.
*
* @package DB
* @author Stig Bakken <ssb@php.net>
* @since PHP 4.0
*/
class DB
{
// {{{ &factory()
/**
* Create a new DB connection object for the specified database
* type
*
* @param string $type database type, for example "mysql"
*
* @return mixed a newly created DB object, or a DB error code on
* error
*
* access public
*/
function &factory($type)
{
include_once(PEAR_PATH."/DB/${type}.php");
$classname = "DB_${type}";
if (!class_exists($classname)) {
return DOLIPEAR::raiseError(null, DB_ERROR_NOT_FOUND,
null, null, null, 'DB_Error', true);
}
@$obj =& new $classname;
return $obj;
}
// }}}
// {{{ &connect()
/**
* Create a new DB connection object and connect to the specified
* database
*
* @param mixed $dsn "data source name", see the DB::parseDSN
* method for a description of the dsn format. Can also be
* specified as an array of the format returned by DB::parseDSN.
*
* @param mixed $options An associative array of option names and
* their values. For backwards compatibility, this parameter may
* also be a boolean that tells whether the connection should be
* persistent. See DB_common::setOption for more information on
* connection options.
*
* @return mixed a newly created DB connection object, or a DB
* error object on error
*
* @see DB::parseDSN
* @see DB::isError
* @see DB_common::setOption
*/
function &connect($dsn, $options = false)
{
if (is_array($dsn)) {
$dsninfo = $dsn;
} else {
$dsninfo = DB::parseDSN($dsn);
}
$type = $dsninfo["phptype"];
if (is_array($options) && isset($options["debug"]) &&
$options["debug"] >= 2) {
// expose php errors with sufficient debug level
include_once PEAR_PATH."/DB/${type}.php";
} else {
include_once PEAR_PATH."/DB/${type}.php";
}
$classname = "DB_${type}";
if (!class_exists($classname)) {
return DOLIPEAR::raiseError(null, DB_ERROR_NOT_FOUND, null, null,
"Unable to include the DB/{$type}.php file for `$dsn'",
'DB_Error', true);
}
@$obj =& new $classname;
if (is_array($options)) {
foreach ($options as $option => $value) {
$test = $obj->setOption($option, $value);
if (DB::isError($test)) {
return $test;
}
}
} else {
$obj->setOption('persistent', $options);
}
$err = $obj->connect($dsninfo, $obj->getOption('persistent'));
if (DB::isError($err)) {
$err->addUserInfo($dsn);
return $err;
}
return $obj;
}
// }}}
// {{{ apiVersion()
/**
* Return the DB API version
*
* @return int the DB API version number
*
* @access public
*/
function apiVersion()
{
return 2;
}
// }}}
// {{{ isError()
/**
* Tell whether a result code from a DB method is an error
*
* @param int $value result code
*
* @return bool whether $value is an error
*
* @access public
*/
function isError($value)
{
return (is_object($value) &&
(get_class($value) == 'db_error' ||
is_subclass_of($value, 'db_error')));
}
// }}}
// {{{ isConnection()
/**
* Tell whether a value is a DB connection
*
* @param mixed $value value to test
*
* @return bool whether $value is a DB connection
*
* @access public
*/
function isConnection($value)
{
return (is_object($value) &&
is_subclass_of($value, 'db_common') &&
method_exists($value, 'simpleQuery'));
}
// }}}
// {{{ isManip()
/**
* Tell whether a query is a data manipulation query (insert,
* update or delete) or a data definition query (create, drop,
* alter, grant, revoke).
*
* @access public
*
* @param string $query the query
*
* @return boolean whether $query is a data manipulation query
*/
function isManip($query)
{
$manips = 'INSERT|UPDATE|DELETE|'.'REPLACE|CREATE|DROP|'.
'ALTER|GRANT|REVOKE|'.'LOCK|UNLOCK';
if (preg_match('/^\s*"?('.$manips.')\s+/i', $query)) {
return true;
}
return false;
}
// }}}
// {{{ errorMessage()
/**
* Return a textual error message for a DB error code
*
* @param integer $value error code
*
* @return string error message, or false if the error code was
* not recognized
*/
function errorMessage($value)
{
static $errorMessages;
if (!isset($errorMessages)) {
$errorMessages = array(
DB_ERROR => 'unknown error',
DB_ERROR_ALREADY_EXISTS => 'already exists',
DB_ERROR_CANNOT_CREATE => 'can not create',
DB_ERROR_CANNOT_DELETE => 'can not delete',
DB_ERROR_CANNOT_DROP => 'can not drop',
DB_ERROR_CONSTRAINT => 'constraint violation',
DB_ERROR_DIVZERO => 'division by zero',
DB_ERROR_INVALID => 'invalid',
DB_ERROR_INVALID_DATE => 'invalid date or time',
DB_ERROR_INVALID_NUMBER => 'invalid number',
DB_ERROR_MISMATCH => 'mismatch',
DB_ERROR_NODBSELECTED => 'no database selected',
DB_ERROR_NOSUCHFIELD => 'no such field',
DB_ERROR_NOSUCHTABLE => 'no such table',
DB_ERROR_NOT_CAPABLE => 'DB backend not capable',
DB_ERROR_NOT_FOUND => 'not found',
DB_ERROR_NOT_LOCKED => 'not locked',
DB_ERROR_SYNTAX => 'syntax error',
DB_ERROR_UNSUPPORTED => 'not supported',
DB_ERROR_VALUE_COUNT_ON_ROW => 'value count on row',
DB_ERROR_INVALID_DSN => 'invalid DSN',
DB_ERROR_CONNECT_FAILED => 'connect failed',
DB_OK => 'no error',
DB_WARNING => 'unknown warning',
DB_WARNING_READ_ONLY => 'read only',
DB_ERROR_NEED_MORE_DATA => 'insufficient data supplied',
DB_ERROR_EXTENSION_NOT_FOUND=> 'extension not found',
DB_ERROR_NOSUCHDB => 'no such database',
DB_ERROR_ACCESS_VIOLATION => 'insufficient permissions',
DB_ERROR_TRUNCATED => 'truncated'
);
}
if (DB::isError($value)) {
$value = $value->getCode();
}
return isset($errorMessages[$value]) ? $errorMessages[$value] : $errorMessages[DB_ERROR];
}
// }}}
// {{{ parseDSN()
/**
* Parse a data source name
*
* A array with the following keys will be returned:
* phptype: Database backend used in PHP (mysql, odbc etc.)
* dbsyntax: Database used with regards to SQL syntax etc.
* protocol: Communication protocol to use (tcp, unix etc.)
* hostspec: Host specification (hostname[:port])
* database: Database to use on the DBMS server
* username: User name for login
* password: Password for login
*
* The format of the supplied DSN is in its fullest form:
*
* phptype(dbsyntax)://username:password@protocol+hostspec/database
*
* Most variations are allowed:
*
* phptype://username:password@protocol+hostspec:110//usr/db_file.db
* phptype://username:password@hostspec/database_name
* phptype://username:password@hostspec
* phptype://username@hostspec
* phptype://hostspec/database
* phptype://hostspec
* phptype(dbsyntax)
* phptype
*
* @param string $dsn Data Source Name to be parsed
*
* @return array an associative array
*
* @author Tomas V.V.Cox <cox@idecnet.com>
*/
function parseDSN($dsn)
{
if (is_array($dsn)) {
return $dsn;
}
$parsed = array(
'phptype' => false,
'dbsyntax' => false,
'username' => false,
'password' => false,
'protocol' => false,
'hostspec' => false,
'port' => false,
'socket' => false,
'database' => false
);
// 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'] = (empty($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 = (!empty($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, '/') !== 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 ($parsed['protocol'] == 'tcp') {
if (strpos($proto_opts, ':') !== false) {
list($parsed['hostspec'], $parsed['port']) = explode(':', $proto_opts);
} else {
$parsed['hostspec'] = $proto_opts;
}
} elseif ($parsed['protocol'] == 'unix') {
$parsed['socket'] = $proto_opts;
}
// Get dabase if any
// $dsn => database
if (!empty($dsn)) {
// /database
if (($pos = strpos($dsn, '?')) === false) {
$parsed['database'] = $dsn;
// /database?param1=value1&param2=value2
} else {
$parsed['database'] = 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 (!isset($parsed[$key])) { // don't allow params overwrite
$parsed[$key] = rawurldecode($value);
}
}
}
}
return $parsed;
}
// }}}
// {{{ assertExtension()
/**
* Load a PHP database extension if it is not loaded already.
*
* @access public
*
* @param string $name the base name of the extension (without the .so or
* .dll suffix)
*
* @return boolean true if the extension was already or successfully
* loaded, false if it could not be loaded
*/
function assertExtension($name)
{
if (!extension_loaded($name)) {
$dlext = OS_WINDOWS ? '.dll' : '.so';
$dlprefix = OS_WINDOWS ? 'php_' : '';
@dl($dlprefix . $name . $dlext);
return extension_loaded($name);
}
return true;
}
// }}}
}
// }}}
// {{{ class DB_Error
/**
* DB_Error implements a class for reporting portable database error
* messages.
*
* @package DB
* @author Stig Bakken <ssb@php.net>
*/
class DB_Error extends DOLIPEAR_Error
{
// {{{ constructor
/**
* DB_Error constructor.
*
* @param mixed $code DB error code, or string with error message.
* @param integer $mode what "error mode" to operate in
* @param integer $level what error level to use for $mode & PEAR_ERROR_TRIGGER
* @param mixed $debuginfo additional debug info, such as the last query
*
* @access public
*
* @see PEAR_Error
*/
function DB_Error($code = DB_ERROR, $mode = PEAR_ERROR_RETURN,
$level = E_USER_NOTICE, $debuginfo = null)
{
if (is_int($code)) {
$this->DOLIPEAR_Error('DB Error: ' . DB::errorMessage($code), $code, $mode, $level, $debuginfo);
} else {
$this->DOLIPEAR_Error("DB Error: $code", DB_ERROR, $mode, $level, $debuginfo);
}
}
// }}}
}
// }}}
// {{{ class DB_Result
/**
* This class implements a wrapper for a DB result set.
* A new instance of this class will be returned by the DB implementation
* after processing a query that returns data.
*
* @package DB
* @author Stig Bakken <ssb@php.net>
*/
class DB_result
{
// {{{ properties
var $dbh;
var $result;
var $row_counter = null;
/**
* for limit queries, the row to start fetching
* @var integer
*/
var $limit_from = null;
/**
* for limit queries, the number of rows to fetch
* @var integer
*/
var $limit_count = null;
// }}}
// {{{ constructor
/**
* DB_result constructor.
* @param resource &$dbh DB object reference
* @param resource $result result resource id
* @param array $options assoc array with optional result options
*/
function DB_result(&$dbh, $result, $options = array())
{
$this->dbh = &$dbh;
$this->result = $result;
foreach ($options as $key => $value) {
$this->setOption($key, $value);
}
$this->limit_type = $dbh->features['limit'];
$this->autofree = $dbh->options['autofree'];
$this->fetchmode = $dbh->fetchmode;
$this->fetchmode_object_class = $dbh->fetchmode_object_class;
}
function setOption($key, $value = null)
{
switch ($key) {
case 'limit_from':
$this->limit_from = $value; break;
case 'limit_count';
$this->limit_count = $value; break;
}
}
// }}}
// {{{ fetchRow()
/**
* Fetch and return a row of data (it uses driver->fetchInto for that)
* @param int $fetchmode format of fetched row
* @param int $rownum the row number to fetch
*
* @return array a row of data, NULL on no more rows or PEAR_Error on error
*
* @access public
*/
function &fetchRow($fetchmode = DB_FETCHMODE_DEFAULT, $rownum=null)
{
if ($fetchmode === DB_FETCHMODE_DEFAULT) {
$fetchmode = $this->fetchmode;
}
if ($fetchmode === DB_FETCHMODE_OBJECT) {
$fetchmode = DB_FETCHMODE_ASSOC;
$object_class = $this->fetchmode_object_class;
}
if ($this->limit_from !== null) {
if ($this->row_counter === null) {
$this->row_counter = $this->limit_from;
// Skip rows
if ($this->limit_type == false) {
$i = 0;
while ($i++ < $this->limit_from) {
$this->dbh->fetchInto($this->result, $arr, $fetchmode);
}
}
}
if ($this->row_counter >= (
$this->limit_from + $this->limit_count))
{
if ($this->autofree) {
$this->free();
}
return null;
}
if ($this->limit_type == 'emulate') {
$rownum = $this->row_counter;
}
$this->row_counter++;
}
$res = $this->dbh->fetchInto($this->result, $arr, $fetchmode, $rownum);
if ($res === DB_OK) {
if (isset($object_class)) {
// default mode specified in DB_common::fetchmode_object_class property
if ($object_class == 'stdClass') {
$arr = (object) $arr;
} else {
$arr = &new $object_class($arr);
}
}
return $arr;
}
if ($res == null && $this->autofree) {
$this->free();
}
return $res;
}
// }}}
// {{{ fetchInto()
/**
* Fetch a row of data into an existing variable.
*
* @param mixed &$arr reference to data containing the row
* @param integer $fetchmod format of fetched row
* @param integer $rownum the row number to fetch
*
* @return mixed DB_OK on success, NULL on no more rows or
* a DB_Error object on error
*
* @access public
*/
function fetchInto(&$arr, $fetchmode = DB_FETCHMODE_DEFAULT, $rownum=null)
{
if ($fetchmode === DB_FETCHMODE_DEFAULT) {
$fetchmode = $this->fetchmode;
}
if ($fetchmode === DB_FETCHMODE_OBJECT) {
$fetchmode = DB_FETCHMODE_ASSOC;
$object_class = $this->fetchmode_object_class;
}
if ($this->limit_from !== null) {
if ($this->row_counter === null) {
$this->row_counter = $this->limit_from;
// Skip rows
if ($this->limit_type == false) {
$i = 0;
while ($i++ < $this->limit_from) {
$this->dbh->fetchInto($this->result, $arr, $fetchmode);
}
}
}
if ($this->row_counter >= (
$this->limit_from + $this->limit_count))
{
if ($this->autofree) {
$this->free();
}
return null;
}
if ($this->limit_type == 'emulate') {
$rownum = $this->row_counter;
}
$this->row_counter++;
}
$res = $this->dbh->fetchInto($this->result, $arr, $fetchmode, $rownum);
if ($res === DB_OK) {
if (isset($object_class)) {
// default mode specified in DB_common::fetchmode_object_class property
if ($object_class == 'stdClass') {
$arr = (object) $arr;
} else {
$arr = new $object_class($arr);
}
}
return DB_OK;
}
if ($res == null && $this->autofree) {
$this->free();
}
return $res;
}
// }}}
// {{{ numCols()
/**
* Get the the number of columns in a result set.
*
* @return int the number of columns, or a DB error
*
* @access public
*/
function numCols()
{
return $this->dbh->numCols($this->result);
}
// }}}
// {{{ numRows()
/**
* Get the number of rows in a result set.
*
* @return int the number of rows, or a DB error
*
* @access public
*/
function numRows()
{
return $this->dbh->numRows($this->result);
}
// }}}
// {{{ nextResult()
/**
* Get the next result if a batch of queries was executed.
*
* @return bool true if a new result is available or false if not.
*
* @access public
*/
function nextResult()
{
return $this->dbh->nextResult($this->result);
}
// }}}
// {{{ free()
/**
* Frees the resources allocated for this result set.
* @return int error code
*
* @access public
*/
function free()
{
$err = $this->dbh->freeResult($this->result);
if(DB::isError($err)) {
return $err;
}
$this->result = false;
return true;
}
// }}}
// {{{ tableInfo()
/**
* @deprecated
*/
function tableInfo($mode = null)
{
return $this->dbh->tableInfo($this->result, $mode);
}
// }}}
// {{{ getRowCounter()
/**
* returns the actual row number
* @return integer
*/
function getRowCounter()
{
return $this->row_counter;
}
// }}}
}
// }}}
// {{{ class DB_Row
/**
* Pear DB Row Object
* @see DB_common::setFetchMode()
*/
class DB_row
{
// {{{ constructor
/**
* constructor
*
* @param resource row data as array
*/
function DB_row(&$arr)
{
for (reset($arr); $key = key($arr); next($arr)) {
$this->$key = &$arr[$key];
}
}
// }}}
}
// }}}
?>

File diff suppressed because it is too large Load Diff

View File

@ -1,844 +0,0 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 foldmethod=marker: */
// +----------------------------------------------------------------------+
// | PHP Version 4 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1997-2003 The PHP Group |
// +----------------------------------------------------------------------+
// | This source file is subject to version 2.02 of the PHP license, |
// | that is bundled with this package in the file LICENSE, and is |
// | available at through the world-wide-web at |
// | http://www.php.net/license/2_02.txt. |
// | If you did not receive a copy of the PHP license and are unable to |
// | obtain it through the world-wide-web, please send a note to |
// | license@php.net so we can mail you a copy immediately. |
// +----------------------------------------------------------------------+
// | Author: Stig Bakken <ssb@php.net> |
// +----------------------------------------------------------------------+
//
// $Id$
//
// Database independent query interface definition for PHP's MySQL
// extension.
//
//
// XXX legend:
//
// XXX ERRORMSG: The error message from the mysql function should
// be registered here.
//
//require_once 'DB/common.php';
require_once PEAR_PATH."/DB/common.php";
class DB_mysql extends DB_common
{
// {{{ properties
var $connection;
var $phptype, $dbsyntax;
var $prepare_tokens = array();
var $prepare_types = array();
var $num_rows = array();
var $transaction_opcount = 0;
var $autocommit = true;
var $fetchmode = DB_FETCHMODE_ORDERED; /* Default fetch mode */
var $_db = false;
// }}}
// {{{ constructor
/**
* DB_mysql constructor.
*
* @access public
*/
function DB_mysql()
{
$this->DB_common();
$this->phptype = 'mysql';
$this->dbsyntax = 'mysql';
$this->features = array(
'prepare' => false,
'pconnect' => true,
'transactions' => true,
'limit' => 'alter'
);
$this->errorcode_map = array(
1004 => DB_ERROR_CANNOT_CREATE,
1005 => DB_ERROR_CANNOT_CREATE,
1006 => DB_ERROR_CANNOT_CREATE,
1007 => DB_ERROR_ALREADY_EXISTS,
1008 => DB_ERROR_CANNOT_DROP,
1046 => DB_ERROR_NODBSELECTED,
1050 => DB_ERROR_ALREADY_EXISTS,
1051 => DB_ERROR_NOSUCHTABLE,
1054 => DB_ERROR_NOSUCHFIELD,
1062 => DB_ERROR_ALREADY_EXISTS,
1064 => DB_ERROR_SYNTAX,
1100 => DB_ERROR_NOT_LOCKED,
1136 => DB_ERROR_VALUE_COUNT_ON_ROW,
1146 => DB_ERROR_NOSUCHTABLE,
1048 => DB_ERROR_CONSTRAINT,
);
}
// }}}
// {{{ connect()
/**
* Connect to a database and log in as the specified user.
*
* @param $dsn the data source name (see DB::parseDSN for syntax)
* @param $persistent (optional) whether the connection should
* be persistent
* @access public
* @return int DB_OK on success, a DB error on failure
*/
function connect($dsninfo, $persistent = false)
{
if (!DB::assertExtension('mysql'))
return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND);
$this->dsn = $dsninfo;
if (isset($dsninfo['protocol']) && $dsninfo['protocol'] == 'unix') {
$dbhost = ':' . $dsninfo['socket'];
} else {
$dbhost = $dsninfo['hostspec'] ? $dsninfo['hostspec'] : 'localhost';
if (!empty($dsninfo['port'])) {
$dbhost .= ':' . $dsninfo['port'];
}
}
$user = $dsninfo['username'];
$pw = $dsninfo['password'];
$connect_function = $persistent ? 'mysql_pconnect' : 'mysql_connect';
if ($dbhost && $user && $pw) {
$conn = @$connect_function($dbhost, $user, $pw);
} elseif ($dbhost && $user) {
$conn = @$connect_function($dbhost, $user);
} elseif ($dbhost) {
$conn = @$connect_function($dbhost);
} else {
$conn = false;
}
if (empty($conn)) {
if (($err = @mysql_error()) != '') {
return $this->raiseError(DB_ERROR_CONNECT_FAILED, null, null,
null, $err);
} elseif (empty($php_errormsg)) {
return $this->raiseError(DB_ERROR_CONNECT_FAILED);
} else {
return $this->raiseError(DB_ERROR_CONNECT_FAILED, null, null,
null, $php_errormsg);
}
}
if ($dsninfo['database']) {
if (!@mysql_select_db($dsninfo['database'], $conn)) {
switch(mysql_errno($conn)) {
case 1049:
return $this->raiseError(DB_ERROR_NOSUCHDB, null, null,
null, mysql_error($conn));
break;
case 1044:
return $this->raiseError(DB_ERROR_ACCESS_VIOLATION, null, null,
null, mysql_error($conn));
break;
default:
return $this->raiseError(DB_ERROR, null, null,
null, mysql_error($conn));
break;
}
}
// fix to allow calls to different databases in the same script
$this->_db = $dsninfo['database'];
}
$this->connection = $conn;
return DB_OK;
}
// }}}
// {{{ disconnect()
/**
* Log out and disconnect from the database.
*
* @access public
*
* @return bool TRUE on success, FALSE if not connected.
*/
function disconnect()
{
$ret = mysql_close($this->connection);
$this->connection = null;
return $ret;
}
// }}}
// {{{ simpleQuery()
/**
* Send a query to MySQL and return the results as a MySQL resource
* identifier.
*
* @param the SQL query
*
* @access public
*
* @return mixed returns a valid MySQL result for successful SELECT
* queries, DB_OK for other successful queries. A DB error is
* returned on failure.
*/
function simpleQuery($query)
{
$ismanip = DB::isManip($query);
$this->last_query = $query;
$query = $this->modifyQuery($query);
if ($this->_db) {
if (!@mysql_select_db($this->_db, $this->connection)) {
return $this->mysqlRaiseError(DB_ERROR_NODBSELECTED);
}
}
if (!$this->autocommit && $ismanip) {
if ($this->transaction_opcount == 0) {
$result = @mysql_query('SET AUTOCOMMIT=0', $this->connection);
$result = @mysql_query('BEGIN', $this->connection);
if (!$result) {
return $this->mysqlRaiseError();
}
}
$this->transaction_opcount++;
}
$result = @mysql_query($query, $this->connection);
if (!$result) {
return $this->mysqlRaiseError();
}
if (is_resource($result)) {
$numrows = $this->numrows($result);
if (is_object($numrows)) {
return $numrows;
}
$this->num_rows[$result] = $numrows;
return $result;
}
return DB_OK;
}
// }}}
// {{{ nextResult()
/**
* Move the internal mysql result pointer to the next available result
*
* This method has not been implemented yet.
*
* @param a valid sql result resource
*
* @access public
*
* @return false
*/
function nextResult($result)
{
return false;
}
// }}}
// {{{ fetchInto()
/**
* Fetch a row and insert the data into an existing array.
*
* @param $result MySQL result identifier
* @param $arr (reference) array where data from the row is stored
* @param $fetchmode how the array data should be indexed
* @param $rownum the row number to fetch
* @access public
*
* @return int DB_OK on success, a DB error on failure
*/
function fetchInto($result, &$arr, $fetchmode, $rownum=null)
{
if ($rownum !== null) {
if (!@mysql_data_seek($result, $rownum)) {
return null;
}
}
if ($fetchmode & DB_FETCHMODE_ASSOC) {
$arr = @mysql_fetch_array($result, MYSQL_ASSOC);
} else {
$arr = @mysql_fetch_row($result);
}
if (!$arr) {
// See: http://bugs.php.net/bug.php?id=22328
// for why we can't check errors on fetching
return null;
/*
$errno = @mysql_errno($this->connection);
if (!$errno) {
return NULL;
}
return $this->mysqlRaiseError($errno);
*/
}
return DB_OK;
}
// }}}
// {{{ freeResult()
/**
* Free the internal resources associated with $result.
*
* @param $result MySQL result identifier or DB statement identifier
*
* @access public
*
* @return bool TRUE on success, FALSE if $result is invalid
*/
function freeResult($result)
{
if (is_resource($result)) {
return mysql_free_result($result);
}
$result = (int)$result; // $result is a prepared query handle
if (!isset($this->prepare_tokens[$result])) {
return false;
}
// I fixed the unset thing.
$this->prepare_types = array();
$this->prepare_tokens = array();
return true;
}
// }}}
// {{{ numCols()
/**
* Get the number of columns in a result set.
*
* @param $result MySQL result identifier
*
* @access public
*
* @return int the number of columns per row in $result
*/
function numCols($result)
{
$cols = @mysql_num_fields($result);
if (!$cols) {
return $this->mysqlRaiseError();
}
return $cols;
}
// }}}
// {{{ numRows()
/**
* Get the number of rows in a result set.
*
* @param $result MySQL result identifier
*
* @access public
*
* @return int the number of rows in $result
*/
function numRows($result)
{
$rows = @mysql_num_rows($result);
if ($rows === null) {
return $this->mysqlRaiseError();
}
return $rows;
}
// }}}
// {{{ autoCommit()
/**
* Enable/disable automatic commits
*/
function autoCommit($onoff = false)
{
// XXX if $this->transaction_opcount > 0, we should probably
// issue a warning here.
$this->autocommit = $onoff ? true : false;
return DB_OK;
}
// }}}
// {{{ commit()
/**
* Commit the current transaction.
*/
function commit()
{
if ($this->transaction_opcount > 0) {
if ($this->_db) {
if (!@mysql_select_db($this->_db, $this->connection)) {
return $this->mysqlRaiseError(DB_ERROR_NODBSELECTED);
}
}
$result = @mysql_query('COMMIT', $this->connection);
$result = @mysql_query('SET AUTOCOMMIT=1', $this->connection);
$this->transaction_opcount = 0;
if (!$result) {
return $this->mysqlRaiseError();
}
}
return DB_OK;
}
// }}}
// {{{ rollback()
/**
* Roll back (undo) the current transaction.
*/
function rollback()
{
if ($this->transaction_opcount > 0) {
if ($this->_db) {
if (!@mysql_select_db($this->_db, $this->connection)) {
return $this->mysqlRaiseError(DB_ERROR_NODBSELECTED);
}
}
$result = @mysql_query('ROLLBACK', $this->connection);
$result = @mysql_query('SET AUTOCOMMIT=1', $this->connection);
$this->transaction_opcount = 0;
if (!$result) {
return $this->mysqlRaiseError();
}
}
return DB_OK;
}
// }}}
// {{{ affectedRows()
/**
* Gets the number of rows affected by the data manipulation
* query. For other queries, this function returns 0.
*
* @return number of rows affected by the last query
*/
function affectedRows()
{
if (DB::isManip($this->last_query)) {
$result = @mysql_affected_rows($this->connection);
} else {
$result = 0;
}
return $result;
}
// }}}
// {{{ errorNative()
/**
* Get the native error code of the last error (if any) that
* occured on the current connection.
*
* @access public
*
* @return int native MySQL error code
*/
function errorNative()
{
return mysql_errno($this->connection);
}
// }}}
// {{{ nextId()
/**
* Get the next value in a sequence. We emulate sequences
* for MySQL. Will create the sequence if it does not exist.
*
* @access public
*
* @param string $seq_name the name of the sequence
*
* @param bool $ondemand whether to create the sequence table on demand
* (default is true)
*
* @return mixed a sequence integer, or a DB error
*/
function nextId($seq_name, $ondemand = true)
{
$seqname = $this->getSequenceName($seq_name);
do {
$repeat = 0;
$this->pushErrorHandling(DOLIPEAR_ERROR_RETURN);
$result = $this->query("UPDATE ${seqname} ".
'SET id=LAST_INSERT_ID(id+1)');
$this->popErrorHandling();
if ($result == DB_OK) {
/** COMMON CASE **/
$id = mysql_insert_id($this->connection);
if ($id != 0) {
return $id;
}
/** EMPTY SEQ TABLE **/
// Sequence table must be empty for some reason, so fill it and return 1
// Obtain a user-level lock
$result = $this->getOne("SELECT GET_LOCK('${seqname}_lock',10)");
if (DB::isError($result)) {
return $this->raiseError($result);
}
if ($result == 0) {
// Failed to get the lock, bail with a DB_ERROR_NOT_LOCKED error
return $this->mysqlRaiseError(DB_ERROR_NOT_LOCKED);
}
// add the default value
$result = $this->query("REPLACE INTO ${seqname} VALUES (0)");
if (DB::isError($result)) {
return $this->raiseError($result);
}
// Release the lock
$result = $this->getOne("SELECT RELEASE_LOCK('${seqname}_lock')");
if (DB::isError($result)) {
return $this->raiseError($result);
}
// We know what the result will be, so no need to try again
return 1;
/** ONDEMAND TABLE CREATION **/
} elseif ($ondemand && DB::isError($result) &&
$result->getCode() == DB_ERROR_NOSUCHTABLE)
{
$result = $this->createSequence($seq_name);
if (DB::isError($result)) {
return $this->raiseError($result);
} else {
$repeat = 1;
}
/** BACKWARDS COMPAT **/
} elseif (DB::isError($result) &&
$result->getCode() == DB_ERROR_ALREADY_EXISTS)
{
// see _BCsequence() comment
$result = $this->_BCsequence($seqname);
if (DB::isError($result)) {
return $this->raiseError($result);
}
$repeat = 1;
}
} while ($repeat);
return $this->raiseError($result);
}
// }}}
// {{{ createSequence()
function createSequence($seq_name)
{
$seqname = $this->getSequenceName($seq_name);
$res = $this->query("CREATE TABLE ${seqname} ".
'(id INTEGER UNSIGNED AUTO_INCREMENT NOT NULL,'.
' PRIMARY KEY(id))');
if (DB::isError($res)) {
return $res;
}
// insert yields value 1, nextId call will generate ID 2
$res = $this->query("INSERT INTO ${seqname} VALUES(0)");
if (DB::isError($res)) {
return $res;
}
// so reset to zero
return $this->query("UPDATE ${seqname} SET id = 0;");
}
// }}}
// {{{ dropSequence()
function dropSequence($seq_name)
{
$seqname = $this->getSequenceName($seq_name);
return $this->query("DROP TABLE ${seqname}");
}
// }}}
// {{{ _BCsequence()
/**
* Backwards compatibility with old sequence emulation implementation
* (clean up the dupes)
*
* @param string $seqname The sequence name to clean up
* @return mixed DB_Error or true
*/
function _BCsequence($seqname)
{
// Obtain a user-level lock... this will release any previous
// application locks, but unlike LOCK TABLES, it does not abort
// the current transaction and is much less frequently used.
$result = $this->getOne("SELECT GET_LOCK('${seqname}_lock',10)");
if (DB::isError($result)) {
return $result;
}
if ($result == 0) {
// Failed to get the lock, can't do the conversion, bail
// with a DB_ERROR_NOT_LOCKED error
return $this->mysqlRaiseError(DB_ERROR_NOT_LOCKED);
}
$highest_id = $this->getOne("SELECT MAX(id) FROM ${seqname}");
if (DB::isError($highest_id)) {
return $highest_id;
}
// This should kill all rows except the highest
// We should probably do something if $highest_id isn't
// numeric, but I'm at a loss as how to handle that...
$result = $this->query("DELETE FROM ${seqname} WHERE id <> $highest_id");
if (DB::isError($result)) {
return $result;
}
// If another thread has been waiting for this lock,
// it will go thru the above procedure, but will have no
// real effect
$result = $this->getOne("SELECT RELEASE_LOCK('${seqname}_lock')");
if (DB::isError($result)) {
return $result;
}
return true;
}
// }}}
// {{{ quote()
/**
* Quote the given string so it can be safely used within string delimiters
* in a query.
* @param $string mixed Data to be quoted
* @return mixed "NULL" string, quoted string or original data
*/
function quote($str = null)
{
switch (strtolower(gettype($str))) {
case 'null':
return 'NULL';
case 'integer':
case 'double':
return $str;
case 'string':
default:
if(function_exists('mysql_real_escape_string')) {
return "'".mysql_real_escape_string($str, $this->connection)."'";
} else {
return "'".mysql_escape_string($str)."'";
}
}
}
// }}}
// {{{ modifyQuery()
function modifyQuery($query, $subject = null)
{
if ($this->options['optimize'] == 'portability') {
// "DELETE FROM table" gives 0 affected rows in MySQL.
// This little hack lets you know how many rows were deleted.
if (preg_match('/^\s*DELETE\s+FROM\s+(\S+)\s*$/i', $query)) {
$query = preg_replace('/^\s*DELETE\s+FROM\s+(\S+)\s*$/',
'DELETE FROM \1 WHERE 1=1', $query);
}
}
return $query;
}
// }}}
// {{{ modifyLimitQuery()
function modifyLimitQuery($query, $from, $count)
{
if (DB::isManip($query)) {
return $query . " LIMIT $count";
} else {
return $query . " LIMIT $from, $count";
}
}
// }}}
// {{{ mysqlRaiseError()
function mysqlRaiseError($errno = null)
{
if ($errno === null) {
$errno = $this->errorCode(mysql_errno($this->connection));
}
return $this->raiseError($errno, null, null, null,
@mysql_errno($this->connection) . " ** " .
@mysql_error($this->connection));
}
// }}}
// {{{ tableInfo()
function tableInfo($result, $mode = null) {
$count = 0;
$id = 0;
$res = array();
/*
* depending on $mode, metadata returns the following values:
*
* - mode is null (default):
* $result[]:
* [0]["table"] table name
* [0]["name"] field name
* [0]["type"] field type
* [0]["len"] field length
* [0]["flags"] field flags
*
* - mode is DB_TABLEINFO_ORDER
* $result[]:
* ["num_fields"] number of metadata records
* [0]["table"] table name
* [0]["name"] field name
* [0]["type"] field type
* [0]["len"] field length
* [0]["flags"] field flags
* ["order"][field name] index of field named "field name"
* The last one is used, if you have a field name, but no index.
* Test: if (isset($result['meta']['myfield'])) { ...
*
* - mode is DB_TABLEINFO_ORDERTABLE
* the same as above. but additionally
* ["ordertable"][table name][field name] index of field
* named "field name"
*
* this is, because if you have fields from different
* tables with the same field name * they override each
* other with DB_TABLEINFO_ORDER
*
* you can combine DB_TABLEINFO_ORDER and
* DB_TABLEINFO_ORDERTABLE with DB_TABLEINFO_ORDER |
* DB_TABLEINFO_ORDERTABLE * or with DB_TABLEINFO_FULL
*/
// if $result is a string, then we want information about a
// table without a resultset
if (is_string($result)) {
$id = @mysql_list_fields($this->dsn['database'],
$result, $this->connection);
if (empty($id)) {
return $this->mysqlRaiseError();
}
} else { // else we want information about a resultset
$id = $result;
if (empty($id)) {
return $this->mysqlRaiseError();
}
}
$count = @mysql_num_fields($id);
// made this IF due to performance (one if is faster than $count if's)
if (empty($mode)) {
for ($i=0; $i<$count; $i++) {
$res[$i]['table'] = @mysql_field_table ($id, $i);
$res[$i]['name'] = @mysql_field_name ($id, $i);
$res[$i]['type'] = @mysql_field_type ($id, $i);
$res[$i]['len'] = @mysql_field_len ($id, $i);
$res[$i]['flags'] = @mysql_field_flags ($id, $i);
}
} else { // full
$res['num_fields']= $count;
for ($i=0; $i<$count; $i++) {
$res[$i]['table'] = @mysql_field_table ($id, $i);
$res[$i]['name'] = @mysql_field_name ($id, $i);
$res[$i]['type'] = @mysql_field_type ($id, $i);
$res[$i]['len'] = @mysql_field_len ($id, $i);
$res[$i]['flags'] = @mysql_field_flags ($id, $i);
if ($mode & DB_TABLEINFO_ORDER) {
$res['order'][$res[$i]['name']] = $i;
}
if ($mode & DB_TABLEINFO_ORDERTABLE) {
$res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i;
}
}
}
// free the result only if we were called on a table
if (is_string($result)) {
@mysql_free_result($id);
}
return $res;
}
// }}}
// {{{ getSpecialQuery()
/**
* Returns the query needed to get some backend info
* @param string $type What kind of info you want to retrieve
* @return string The SQL query string
*/
function getSpecialQuery($type)
{
switch ($type) {
case 'tables':
$sql = "SHOW TABLES";
break;
case 'views':
return DB_ERROR_NOT_CAPABLE;
case 'users':
$sql = "select distinct User from user";
if($this->dsn['database'] != 'mysql') {
$dsn = $this->dsn;
$dsn['database'] = 'mysql';
if (DB::isError($db = DB::connect($dsn))) {
return $db;
}
$sql = $db->getCol($sql);
$db->disconnect();
// XXX Fixme the mysql driver should take care of this
if (!@mysql_select_db($this->dsn['database'], $this->connection)) {
return $this->mysqlRaiseError(DB_ERROR_NODBSELECTED);
}
}
return $sql;
break;
case 'databases':
$sql = "SHOW DATABASES";
break;
default:
return null;
}
return $sql;
}
// }}}
// TODO/wishlist:
// longReadlen
// binmode
}
?>

File diff suppressed because it is too large Load Diff

View File

@ -1,788 +0,0 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 foldmethod=marker: */
// +----------------------------------------------------------------------+
// | PHP Version 4 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1997-2003 The PHP Group |
// +----------------------------------------------------------------------+
// | This source file is subject to version 2.02 of the PHP license, |
// | that is bundled with this package in the file LICENSE, and is |
// | available at through the world-wide-web at |
// | http://www.php.net/license/2_02.txt. |
// | If you did not receive a copy of the PHP license and are unable to |
// | obtain it through the world-wide-web, please send a note to |
// | license@php.net so we can mail you a copy immediately. |
// +----------------------------------------------------------------------+
// | Authors: Rui Hirokawa <rui_hirokawa@ybb.ne.jp> |
// | Stig Bakken <ssb@php.net> |
// +----------------------------------------------------------------------+
//
// $Id$
//
// Database independent query interface definition for PHP's PostgreSQL
// extension.
//
//require_once 'DB/common.php';
require_once PEAR_PATH."/DB/common.php";
class DB_pgsql extends DB_common
{
// {{{ properties
var $connection;
var $phptype, $dbsyntax;
var $prepare_tokens = array();
var $prepare_types = array();
var $transaction_opcount = 0;
var $dsn = array();
var $row = array();
var $num_rows = array();
var $affected = 0;
var $autocommit = true;
var $fetchmode = DB_FETCHMODE_ORDERED;
// }}}
// {{{ constructor
function DB_pgsql()
{
$this->DB_common();
$this->phptype = 'pgsql';
$this->dbsyntax = 'pgsql';
$this->features = array(
'prepare' => false,
'pconnect' => true,
'transactions' => true,
'limit' => 'alter'
);
$this->errorcode_map = array(
);
}
// }}}
// {{{ connect()
/**
* Connect to a database and log in as the specified user.
*
* @param $dsn the data source name (see DB::parseDSN for syntax)
* @param $persistent (optional) whether the connection should
* be persistent
*
* @return int DB_OK on success, a DB error code on failure
*/
function connect($dsninfo, $persistent = false)
{
if (!DB::assertExtension('pgsql'))
return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND);
$this->dsn = $dsninfo;
$protocol = (isset($dsninfo['protocol'])) ? $dsninfo['protocol'] : 'tcp';
$connstr = '';
if ($protocol == 'tcp') {
if (!empty($dsninfo['hostspec'])) {
$connstr = 'host=' . $dsninfo['hostspec'];
}
if (!empty($dsninfo['port'])) {
$connstr .= ' port=' . $dsninfo['port'];
}
}
if (isset($dsninfo['database'])) {
$connstr .= ' dbname=\'' . addslashes($dsninfo['database']) . '\'';
}
if (!empty($dsninfo['username'])) {
$connstr .= ' user=\'' . addslashes($dsninfo['username']) . '\'';
}
if (!empty($dsninfo['password'])) {
$connstr .= ' password=\'' . addslashes($dsninfo['password']) . '\'';
}
if (!empty($dsninfo['options'])) {
$connstr .= ' options=' . $dsninfo['options'];
}
if (!empty($dsninfo['tty'])) {
$connstr .= ' tty=' . $dsninfo['tty'];
}
$connect_function = $persistent ? 'pg_pconnect' : 'pg_connect';
// catch error
ob_start();
$conn = $connect_function($connstr);
$error = ob_get_contents();
ob_end_clean();
if ($conn == false) {
return $this->raiseError(DB_ERROR_CONNECT_FAILED, null,
null, null, strip_tags($error));
}
$this->connection = $conn;
return DB_OK;
}
// }}}
// {{{ disconnect()
/**
* Log out and disconnect from the database.
*
* @return bool TRUE on success, FALSE if not connected.
*/
function disconnect()
{
$ret = @pg_close($this->connection);
$this->connection = null;
return $ret;
}
// }}}
// {{{ simpleQuery()
/**
* Send a query to PostgreSQL and return the results as a
* PostgreSQL resource identifier.
*
* @param $query the SQL query
*
* @return int returns a valid PostgreSQL result for successful SELECT
* queries, DB_OK for other successful queries. A DB error code
* is returned on failure.
*/
function simpleQuery($query)
{
$ismanip = DB::isManip($query);
$this->last_query = $query;
$query = $this->modifyQuery($query);
if (!$this->autocommit && $ismanip) {
if ($this->transaction_opcount == 0) {
$result = @pg_exec($this->connection, "begin;");
if (!$result) {
return $this->pgsqlRaiseError();
}
}
$this->transaction_opcount++;
}
$result = @pg_exec($this->connection, $query);
if (!$result) {
return $this->pgsqlRaiseError();
}
// Determine which queries that should return data, and which
// should return an error code only.
if ($ismanip) {
$this->affected = @pg_cmdtuples($result);
return DB_OK;
} elseif (preg_match('/^\s*\(?\s*SELECT\s+/si', $query) &&
!preg_match('/^\s*\(?\s*SELECT\s+INTO\s/si', $query)) {
/* PostgreSQL commands:
ABORT, ALTER, BEGIN, CLOSE, CLUSTER, COMMIT, COPY,
CREATE, DECLARE, DELETE, DROP TABLE, EXPLAIN, FETCH,
GRANT, INSERT, LISTEN, LOAD, LOCK, MOVE, NOTIFY, RESET,
REVOKE, ROLLBACK, SELECT, SELECT INTO, SET, SHOW,
UNLISTEN, UPDATE, VACUUM
*/
$this->row[$result] = 0; // reset the row counter.
$numrows = $this->numrows($result);
if (is_object($numrows)) {
return $numrows;
}
$this->num_rows[$result] = $numrows;
$this->affected = 0;
return $result;
} else {
$this->affected = 0;
return DB_OK;
}
}
// }}}
// {{{ nextResult()
/**
* Move the internal pgsql result pointer to the next available result
*
* @param a valid fbsql result resource
*
* @access public
*
* @return true if a result is available otherwise return false
*/
function nextResult($result)
{
return false;
}
// }}}
// {{{ errorCode()
/**
* Map native error codes to DB's portable ones. Requires that
* the DB implementation's constructor fills in the $errorcode_map
* property.
*
* @param $nativecode the native error code, as returned by the backend
* database extension (string or integer)
*
* @return int a portable DB error code, or FALSE if this DB
* implementation has no mapping for the given error code.
*/
function errorCode($errormsg)
{
static $error_regexps;
if (empty($error_regexps)) {
$error_regexps = array(
'/(Table does not exist\.|Relation [\"\'].*[\"\'] does not exist|sequence does not exist|class ".+" not found)$/' => DB_ERROR_NOSUCHTABLE,
'/table [\"\'].*[\"\'] does not exist/' => DB_ERROR_NOSUCHTABLE,
'/Relation [\"\'].*[\"\'] already exists|Cannot insert a duplicate key into (a )?unique index.*/' => DB_ERROR_ALREADY_EXISTS,
'/divide by zero$/' => DB_ERROR_DIVZERO,
'/pg_atoi: error in .*: can\'t parse /' => DB_ERROR_INVALID_NUMBER,
'/ttribute [\"\'].*[\"\'] not found$|Relation [\"\'].*[\"\'] does not have attribute [\"\'].*[\"\']/' => DB_ERROR_NOSUCHFIELD,
'/parser: parse error at or near \"/' => DB_ERROR_SYNTAX,
'/referential integrity violation/' => DB_ERROR_CONSTRAINT
);
}
foreach ($error_regexps as $regexp => $code) {
if (preg_match($regexp, $errormsg)) {
return $code;
}
}
// Fall back to DB_ERROR if there was no mapping.
return DB_ERROR;
}
// }}}
// {{{ fetchInto()
/**
* Fetch a row and insert the data into an existing array.
*
* @param $result PostgreSQL result identifier
* @param $row (reference) array where data from the row is stored
* @param $fetchmode how the array data should be indexed
* @param $rownum the row number to fetch
*
* @return int DB_OK on success, a DB error code on failure
*/
function fetchInto($result, &$row, $fetchmode, $rownum=null)
{
$rownum = ($rownum !== null) ? $rownum : $this->row[$result];
if ($rownum >= $this->num_rows[$result]) {
return null;
}
if ($fetchmode & DB_FETCHMODE_ASSOC) {
$row = @pg_fetch_array($result, $rownum, PGSQL_ASSOC);
} else {
$row = @pg_fetch_row($result, $rownum);
}
if (!$row) {
$err = pg_errormessage($this->connection);
if (!$err) {
return null;
}
return $this->pgsqlRaiseError();
}
$this->row[$result] = ++$rownum;
return DB_OK;
}
// }}}
// {{{ freeResult()
/**
* Free the internal resources associated with $result.
*
* @param $result int PostgreSQL result identifier or DB statement identifier
*
* @return bool TRUE on success, FALSE if $result is invalid
*/
function freeResult($result)
{
if (is_resource($result)) {
return @pg_freeresult($result);
}
if (!isset($this->prepare_tokens[(int)$result])) {
return false;
}
unset($this->prepare_tokens[(int)$result]);
unset($this->prepare_types[(int)$result]);
unset($this->row[(int)$result]);
unset($this->num_rows[(int)$result]);
$this->affected = 0;
return true;
}
// }}}
// {{{ quote()
/**
* Quote the given string so it can be safely used within string delimiters
* in a query.
* @param $string mixed Data to be quoted
* @return mixed "NULL" string, quoted string or original data
*/
function quote($str = null)
{
switch (strtolower(gettype($str))) {
case 'null':
return 'NULL';
case 'integer':
case 'double' :
return $str;
case 'boolean':
return $str ? 'TRUE' : 'FALSE';
case 'string':
default:
$str = str_replace("'", "''", $str);
//PostgreSQL treats a backslash as an escape character.
$str = str_replace('\\', '\\\\', $str);
return "'$str'";
}
}
// }}}
// {{{ numCols()
/**
* Get the number of columns in a result set.
*
* @param $result resource PostgreSQL result identifier
*
* @return int the number of columns per row in $result
*/
function numCols($result)
{
$cols = @pg_numfields($result);
if (!$cols) {
return $this->pgsqlRaiseError();
}
return $cols;
}
// }}}
// {{{ numRows()
/**
* Get the number of rows in a result set.
*
* @param $result resource PostgreSQL result identifier
*
* @return int the number of rows in $result
*/
function numRows($result)
{
$rows = @pg_numrows($result);
if ($rows === null) {
return $this->pgsqlRaiseError();
}
return $rows;
}
// }}}
// {{{ errorNative()
/**
* Get the native error code of the last error (if any) that
* occured on the current connection.
*
* @return int native PostgreSQL error code
*/
function errorNative()
{
return pg_errormessage($this->connection);
}
// }}}
// {{{ autoCommit()
/**
* Enable/disable automatic commits
*/
function autoCommit($onoff = false)
{
// XXX if $this->transaction_opcount > 0, we should probably
// issue a warning here.
$this->autocommit = $onoff ? true : false;
return DB_OK;
}
// }}}
// {{{ commit()
/**
* Commit the current transaction.
*/
function commit()
{
if ($this->transaction_opcount > 0) {
// (disabled) hack to shut up error messages from libpq.a
//@fclose(@fopen("php://stderr", "w"));
$result = @pg_exec($this->connection, "end;");
$this->transaction_opcount = 0;
if (!$result) {
return $this->pgsqlRaiseError();
}
}
return DB_OK;
}
// }}}
// {{{ rollback()
/**
* Roll back (undo) the current transaction.
*/
function rollback()
{
if ($this->transaction_opcount > 0) {
$result = @pg_exec($this->connection, "abort;");
$this->transaction_opcount = 0;
if (!$result) {
return $this->pgsqlRaiseError();
}
}
return DB_OK;
}
// }}}
// {{{ affectedRows()
/**
* Gets the number of rows affected by the last query.
* if the last query was a select, returns 0.
*
* @return int number of rows affected by the last query or DB_ERROR
*/
function affectedRows()
{
return $this->affected;
}
// }}}
// {{{ nextId()
/**
* Get the next value in a sequence.
*
* We are using native PostgreSQL sequences. If a sequence does
* not exist, it will be created, unless $ondemand is false.
*
* @access public
* @param string $seq_name the name of the sequence
* @param bool $ondemand whether to create the sequence on demand
* @return a sequence integer, or a DB error
*/
function nextId($seq_name, $ondemand = true)
{
$seqname = $this->getSequenceName($seq_name);
$repeat = false;
do {
$this->pushErrorHandling(DOLIPEAR_ERROR_RETURN);
$result = $this->query("SELECT NEXTVAL('${seqname}')");
$this->popErrorHandling();
if ($ondemand && DB::isError($result) &&
$result->getCode() == DB_ERROR_NOSUCHTABLE) {
$repeat = true;
$this->pushErrorHandling(DOLIPEAR_ERROR_RETURN);
$result = $this->createSequence($seq_name);
$this->popErrorHandling();
if (DB::isError($result)) {
return $this->raiseError($result);
}
} else {
$repeat = false;
}
} while ($repeat);
if (DB::isError($result)) {
return $this->raiseError($result);
}
$arr = $result->fetchRow(DB_FETCHMODE_ORDERED);
$result->free();
return $arr[0];
}
// }}}
// {{{ createSequence()
/**
* Create the sequence
*
* @param string $seq_name the name of the sequence
* @return mixed DB_OK on success or DB error on error
* @access public
*/
function createSequence($seq_name)
{
$seqname = $this->getSequenceName($seq_name);
$result = $this->query("CREATE SEQUENCE ${seqname}");
return $result;
}
// }}}
// {{{ dropSequence()
/**
* Drop a sequence
*
* @param string $seq_name the name of the sequence
* @return mixed DB_OK on success or DB error on error
* @access public
*/
function dropSequence($seq_name)
{
$seqname = $this->getSequenceName($seq_name);
return $this->query("DROP SEQUENCE ${seqname}");
}
// }}}
// {{{ modifyLimitQuery()
function modifyLimitQuery($query, $from, $count)
{
$query = $query . " LIMIT $count OFFSET $from";
return $query;
}
// }}}
// {{{ pgsqlRaiseError()
function pgsqlRaiseError($errno = null)
{
$native = $this->errorNative();
if ($errno === null) {
$err = $this->errorCode($native);
} else {
$err = $errno;
}
return $this->raiseError($err, null, null, null, $native);
}
// }}}
// {{{ _pgFieldFlags()
/**
* Flags of a Field
*
* @param int $resource PostgreSQL result identifier
* @param int $num_field the field number
*
* @return string The flags of the field ("not_null", "default_xx", "primary_key",
* "unique" and "multiple_key" are supported)
* @access private
*/
function _pgFieldFlags($resource, $num_field, $table_name)
{
$field_name = @pg_fieldname($resource, $num_field);
$result = @pg_exec($this->connection, "SELECT f.attnotnull, f.atthasdef
FROM pg_attribute f, pg_class tab, pg_type typ
WHERE tab.relname = typ.typname
AND typ.typrelid = f.attrelid
AND f.attname = '$field_name'
AND tab.relname = '$table_name'");
if (@pg_numrows($result) > 0) {
$row = @pg_fetch_row($result, 0);
$flags = ($row[0] == 't') ? 'not_null ' : '';
if ($row[1] == 't') {
$result = @pg_exec($this->connection, "SELECT a.adsrc
FROM pg_attribute f, pg_class tab, pg_type typ, pg_attrdef a
WHERE tab.relname = typ.typname AND typ.typrelid = f.attrelid
AND f.attrelid = a.adrelid AND f.attname = '$field_name'
AND tab.relname = '$table_name' AND f.attnum = a.adnum");
$row = @pg_fetch_row($result, 0);
$num = str_replace('\'', '', $row[0]);
$flags .= "default_$num ";
}
}
$result = @pg_exec($this->connection, "SELECT i.indisunique, i.indisprimary, i.indkey
FROM pg_attribute f, pg_class tab, pg_type typ, pg_index i
WHERE tab.relname = typ.typname
AND typ.typrelid = f.attrelid
AND f.attrelid = i.indrelid
AND f.attname = '$field_name'
AND tab.relname = '$table_name'");
$count = @pg_numrows($result);
for ($i = 0; $i < $count ; $i++) {
$row = @pg_fetch_row($result, $i);
$keys = explode(" ", $row[2]);
if (in_array($num_field + 1, $keys)) {
$flags .= ($row[0] == 't') ? 'unique ' : '';
$flags .= ($row[1] == 't') ? 'primary ' : '';
if (count($keys) > 1)
$flags .= 'multiple_key ';
}
}
return trim($flags);
}
// }}}
// {{{ tableInfo()
/**
* Returns information about a table or a result set
*
* NOTE: doesn't support table name and flags if called from a db_result
*
* @param mixed $resource PostgreSQL result identifier or table name
* @param int $mode A valid tableInfo mode (DB_TABLEINFO_ORDERTABLE or
* DB_TABLEINFO_ORDER)
*
* @return array An array with all the information
*/
function tableInfo($result, $mode = null)
{
$count = 0;
$id = 0;
$res = array();
/*
* depending on $mode, metadata returns the following values:
*
* - mode is false (default):
* $result[]:
* [0]["table"] table name
* [0]["name"] field name
* [0]["type"] field type
* [0]["len"] field length
* [0]["flags"] field flags
*
* - mode is DB_TABLEINFO_ORDER
* $result[]:
* ["num_fields"] number of metadata records
* [0]["table"] table name
* [0]["name"] field name
* [0]["type"] field type
* [0]["len"] field length
* [0]["flags"] field flags
* ["order"][field name] index of field named "field name"
* The last one is used, if you have a field name, but no index.
* Test: if (isset($result['meta']['myfield'])) { ...
*
* - mode is DB_TABLEINFO_ORDERTABLE
* the same as above. but additionally
* ["ordertable"][table name][field name] index of field
* named "field name"
*
* this is, because if you have fields from different
* tables with the same field name * they override each
* other with DB_TABLEINFO_ORDER
*
* you can combine DB_TABLEINFO_ORDER and
* DB_TABLEINFO_ORDERTABLE with DB_TABLEINFO_ORDER |
* DB_TABLEINFO_ORDERTABLE * or with DB_TABLEINFO_FULL
*/
// if $result is a string, then we want information about a
// table without a resultset
if (is_string($result)) {
$id = @pg_exec($this->connection,"SELECT * FROM $result LIMIT 0");
if (empty($id)) {
return $this->pgsqlRaiseError();
}
} else { // else we want information about a resultset
$id = $result;
if (empty($id)) {
return $this->pgsqlRaiseError();
}
}
$count = @pg_numfields($id);
// made this IF due to performance (one if is faster than $count if's)
if (empty($mode)) {
for ($i=0; $i<$count; $i++) {
$res[$i]['table'] = (is_string($result)) ? $result : '';
$res[$i]['name'] = @pg_fieldname ($id, $i);
$res[$i]['type'] = @pg_fieldtype ($id, $i);
$res[$i]['len'] = @pg_fieldsize ($id, $i);
$res[$i]['flags'] = (is_string($result)) ? $this->_pgFieldflags($id, $i, $result) : '';
}
} else { // full
$res["num_fields"]= $count;
for ($i=0; $i<$count; $i++) {
$res[$i]['table'] = (is_string($result)) ? $result : '';
$res[$i]['name'] = @pg_fieldname ($id, $i);
$res[$i]['type'] = @pg_fieldtype ($id, $i);
$res[$i]['len'] = @pg_fieldsize ($id, $i);
$res[$i]['flags'] = (is_string($result)) ? $this->_pgFieldFlags($id, $i, $result) : '';
if ($mode & DB_TABLEINFO_ORDER) {
$res['order'][$res[$i]['name']] = $i;
}
if ($mode & DB_TABLEINFO_ORDERTABLE) {
$res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i;
}
}
}
// free the result only if we were called on a table
if (is_string($result) && is_resource($id)) {
@pg_freeresult($id);
}
return $res;
}
// }}}
// {{{ getTablesQuery()
/**
* Returns the query needed to get some backend info
* @param string $type What kind of info you want to retrieve
* @return string The SQL query string
*/
function getSpecialQuery($type)
{
switch ($type) {
case 'tables': {
$sql = "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_'
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_'";
break;
}
case 'views': {
// Table cols: viewname | viewowner | definition
$sql = "SELECT viewname FROM pg_views";
break;
}
case 'users': {
// cols: usename |usesysid|usecreatedb|usetrace|usesuper|usecatupd|passwd |valuntil
$sql = 'SELECT usename FROM pg_user';
break;
}
case 'databases': {
$sql = 'SELECT datname FROM pg_database';
break;
}
case 'functions': {
$sql = 'SELECT proname FROM pg_proc';
break;
}
default:
return null;
}
return $sql;
}
// }}}
}
// Local variables:
// tab-width: 4
// c-basic-offset: 4
// End:
?>

File diff suppressed because it is too large Load Diff

View File

@ -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$
//
/**
* @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

View File

@ -1,477 +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$
//
//require_once 'MDB2/Driver/Datatype/Common.php';
require_once PEAR_PATH."/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 (is_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);
}
// }}}
// {{{ 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 (DOLIPEAR::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 '';
}
// }}}
// {{{ _getDeclaration()
/**
* Obtain DBMS specific SQL code portion needed to declare a generic 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 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 protected
*/
function _getDeclarationOptions($field)
{
$charset = empty($field['charset']) ? '' :
' '.$this->_getCharsetFieldDeclaration($field['charset']);
$default = '';
if (array_key_exists('default', $field)) {
if ($field['default'] === '') {
$db =& $this->getDBInstance();
if (DOLIPEAR::isError($db)) {
return $db;
}
$field['default'] = empty($field['notnull'])
? null : $this->valid_default_values[$field['type']];
if ($field['default'] === ''
&& ($db->options['portability'] & MDB2_PORTABILITY_EMPTY_TO_NULL)
) {
$field['default'] = ' ';
}
}
$default = ' DEFAULT '.$this->quote($field['default'], $field['type']);
} elseif (empty($field['notnull'])) {
$default = ' DEFAULT NULL';
}
$notnull = empty($field['notnull']) ? ' NULL' : ' NOT NULL';
if ($default == ' DEFAULT NULL' && $notnull == ' NULL') {
$notnull = '';
}
$collation = empty($field['collation']) ? '' :
' '.$this->_getCollationFieldDeclaration($field['collation']);
return $charset.$default.$notnull.$collation;
}
// }}}
// {{{ _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 (DOLIPEAR::isError($db)) {
return $db;
}
$default = $autoinc = '';;
if (!empty($field['autoincrement'])) {
$autoinc = ' IDENTITY 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');
} elseif (empty($field['notnull'])) {
$default = ' DEFAULT NULL';
}
$notnull = empty($field['notnull']) ? ' NULL' : ' NOT NULL';
if ($default == ' DEFAULT NULL' && $notnull == ' NULL') {
$notnull = '';
}
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).$default.$notnull.$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 (DOLIPEAR::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 (DOLIPEAR::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 = bin2hex("0x".$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 = 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 '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 'varchar':
$fixed = false;
case 'char':
$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';
}
if ($fixed !== false) {
$fixed = true;
}
break;
case 'image':
case 'varbinary':
$type[] = 'blob';
$length = null;
break;
default:
$db =& $this->getDBInstance();
if (DOLIPEAR::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);
}
// }}}
}
?>

View File

@ -1,472 +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$
//
//require_once 'MDB2/Driver/Datatype/Common.php';
require_once PEAR_PATH."/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 (DOLIPEAR::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 (DOLIPEAR::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');
} 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.$autoinc;
}
// }}}
// {{{ matchPattern()
/**
* build a pattern matching string
*
* EXPERIMENTAL
*
* WARNING: this function is experimental and may change signature at
* any time until labelled as non-experimental
*
* @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 (DOLIPEAR::isError($db)) {
return $db;
}
$match = '';
if (!is_null($operator)) {
$field = is_null($field) ? '' : $field.' ';
$operator = strtoupper($operator);
switch ($operator) {
// case insensitive
case 'ILIKE':
$match = $field.'LIKE ';
break;
// case sensitive
case 'LIKE':
$match = $field.'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 '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';
}
}
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 (DOLIPEAR::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);
}
// }}}
}
?>

View File

@ -1,509 +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$
//
//require_once 'MDB2/Driver/Datatype/Common.php';
require_once PEAR_PATH."/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 (DOLIPEAR::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 (DOLIPEAR::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');
} 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.$autoinc;
}
// }}}
// {{{ matchPattern()
/**
* build a pattern matching string
*
* EXPERIMENTAL
*
* WARNING: this function is experimental and may change signature at
* any time until labelled as non-experimental
*
* @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 (DOLIPEAR::isError($db)) {
return $db;
}
$match = '';
if (!is_null($operator)) {
$field = is_null($field) ? '' : $field.' ';
$operator = strtoupper($operator);
switch ($operator) {
// case insensitive
case 'ILIKE':
$match = $field.'LIKE ';
break;
// case sensitive
case 'LIKE':
$match = $field.'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 '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';
}
}
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 (DOLIPEAR::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 (DOLIPEAR::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';
}
// }}}
}
?>

View File

@ -1,560 +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$
//require_once 'MDB2/Driver/Datatype/Common.php';
require_once PEAR_PATH."/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 (is_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 (DOLIPEAR::isError($db)) {
return $db;
}
switch ($field['type']) {
case 'text':
$length = !empty($field['length'])
? $field['length'] : $db->options['default_text_field_length'];
$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 (DOLIPEAR::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');
} elseif (empty($field['notnull'])) {
$default = ' DEFAULT NULL';
}
$notnull = empty($field['notnull']) ? '' : ' NOT 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)
{
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;
}
if (version_compare(PHP_VERSION, '5.2.0RC6', '>=')) {
$db =& $this->getDBInstance();
if (DOLIPEAR::isError($db)) {
return $db;
}
$connection = $db->getConnection();
if (DOLIPEAR::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
*
* EXPERIMENTAL
*
* WARNING: this function is experimental and may change signature at
* any time until labelled as non-experimental
*
* @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 (DOLIPEAR::isError($db)) {
return $db;
}
$match = '';
if (!is_null($operator)) {
$field = is_null($field) ? '' : $field.' ';
$operator = strtoupper($operator);
switch ($operator) {
// case insensitive
case 'ILIKE':
$match = $field.'ILIKE ';
break;
// case sensitive
case 'LIKE':
$match = $field.'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 (DOLIPEAR::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';
}
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 'float8':
case 'double':
case 'real':
$type[] = 'float';
break;
case 'decimal':
case 'money':
case 'numeric':
$type[] = 'decimal';
if ($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 (DOLIPEAR::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 (DOLIPEAR::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;
}
// }}}
}
?>

View File

@ -1,231 +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$
//
/**
* @package MDB2
* @category Database
* @author Lukas Smith <smith@pooteeweet.org>
*/
/**
* Base class for the function modules that is extended by each MDB2 driver
*
* @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 (DOLIPEAR::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)
*
* @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';
}
}
// }}}
// {{{ 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 (!is_null($length)) {
return "SUBSTRING($value FROM $position FOR $length)";
}
return "SUBSTRING($value FROM $position)";
}
// }}}
// {{{ 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)";
}
// }}}
// {{{ guid()
/**
* Returns global unique identifier
*
* @return string to get global unique identifier
* @access public
*/
function guid()
{
$db =& $this->getDBInstance();
if (DOLIPEAR::isError($db)) {
return $db;
}
$error =& $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
'method not implemented', __FUNCTION__);
return $error;
}
// }}}
}
?>

View File

@ -1,164 +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: Frank M. Kromann <frank@kromann.info> |
// +----------------------------------------------------------------------+
//
// $Id$
//
//require_once 'MDB2/Driver/Function/Common.php';
require_once PEAR_PATH."/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 (DOLIPEAR::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()';
}
}
// }}}
// {{{ 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 (!is_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).")";
}
// }}}
// {{{ guid()
/**
* Returns global unique identifier
*
* @return string to get global unique identifier
* @access public
*/
function guid()
{
return 'NEWID()';
}
// }}}
}
// }}}
?>

View File

@ -1,121 +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$
//
//require_once 'MDB2/Driver/Function/Common.php';
require_once PEAR_PATH."/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 (DOLIPEAR::isError($db)) {
return $db;
}
$query = 'CALL '.$name;
$query .= $params ? '('.implode(', ', $params).')' : '()';
return $db->query($query, $types, $result_class, $result_wrap_class);
}
// }}}
// {{{ 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()';
}
// }}}
}
?>

View File

@ -1,129 +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$
//
//require_once 'MDB2/Driver/Function/Common.php';
require_once PEAR_PATH."/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 (DOLIPEAR::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;
}
// }}}
// {{{ 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()';
}
// }}}
}
?>

View File

@ -1,100 +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$
//require_once 'MDB2/Driver/Function/Common.php';
require_once PEAR_PATH."/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 (DOLIPEAR::isError($db)) {
return $db;
}
$query = 'SELECT * FROM '.$name;
$query .= $params ? '('.implode(', ', $params).')' : '()';
return $db->query($query, $types, $result_class, $result_wrap_class);
}
// }}}
// {{{ 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()';
}
// }}}
}
?>

View File

@ -1,864 +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$
//
/**
* @package MDB2
* @category Database
* @author Lukas Smith <smith@pooteeweet.org>
*/
/**
* Base class for the management modules that is extended by each MDB2 driver
*
* @package MDB2
* @category Database
* @author Lukas Smith <smith@pooteeweet.org>
*/
class MDB2_Driver_Manager_Common extends MDB2_Module_Common
{
// {{{ getFieldDeclarationList()
/**
* Get declaration of a number of field in bulk
*
* @param array $fields a multidimensional associative array.
* The first dimension determines the field name, while the second
* dimension is keyed with the name of the properties
* of the field being declared as array indexes. Currently, the types
* of supported field properties are as follows:
*
* default
* Boolean 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 mixed string on success, a MDB2 error on failure
* @access public
*/
function getFieldDeclarationList($fields)
{
$db =& $this->getDBInstance();
if (DOLIPEAR::isError($db)) {
return $db;
}
if (!is_array($fields) || empty($fields)) {
return $db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null,
'missing any fields', __FUNCTION__);
}
foreach ($fields as $field_name => $field) {
$query = $db->getDeclaration($field['type'], $field_name, $field);
if (DOLIPEAR::isError($query)) {
return $query;
}
$query_fields[] = $query;
}
return implode(', ', $query_fields);
}
// }}}
// {{{ _fixSequenceName()
/**
* Removes any formatting in an sequence name using the 'seqname_format' option
*
* @param string $sqn string that containts name of a potential sequence
* @param bool $check if only formatted sequences should be returned
* @return string name of the sequence with possible formatting removed
* @access protected
*/
function _fixSequenceName($sqn, $check = false)
{
$db =& $this->getDBInstance();
if (DOLIPEAR::isError($db)) {
return $db;
}
$seq_pattern = '/^'.preg_replace('/%s/', '([a-z0-9_]+)', $db->options['seqname_format']).'$/i';
$seq_name = preg_replace($seq_pattern, '\\1', $sqn);
if ($seq_name && !strcasecmp($sqn, $db->getSequenceName($seq_name))) {
return $seq_name;
}
if ($check) {
return false;
}
return $sqn;
}
// }}}
// {{{ _fixIndexName()
/**
* Removes any formatting in an index name using the 'idxname_format' option
*
* @param string $idx string that containts name of anl index
* @return string name of the index with possible formatting removed
* @access protected
*/
function _fixIndexName($idx)
{
$db =& $this->getDBInstance();
if (DOLIPEAR::isError($db)) {
return $db;
}
$idx_pattern = '/^'.preg_replace('/%s/', '([a-z0-9_]+)', $db->options['idxname_format']).'$/i';
$idx_name = preg_replace($idx_pattern, '\\1', $idx);
if ($idx_name && !strcasecmp($idx, $db->getIndexName($idx_name))) {
return $idx_name;
}
return $idx;
}
// }}}
// {{{ createDatabase()
/**
* create a new database
*
* @param string $name name of the database that should be created
* @return mixed MDB2_OK on success, a MDB2 error on failure
* @access public
*/
function createDatabase($database)
{
$db =& $this->getDBInstance();
if (DOLIPEAR::isError($db)) {
return $db;
}
return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
'method not implemented', __FUNCTION__);
}
// }}}
// {{{ 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($database)
{
$db =& $this->getDBInstance();
if (DOLIPEAR::isError($db)) {
return $db;
}
return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
'method not implemented', __FUNCTION__);
}
// }}}
// {{{ _getCreateTableQuery()
/**
* Create a basic SQL query for a new table creation
* @param string $name Name of the database that should be created
* @param array $fields Associative array that contains the definition of each field of the new table
* @param array $options An associative array of table options
* @return mixed string (the SQL query) on success, a MDB2 error on failure
* @see createTable()
*/
function _getCreateTableQuery($name, $fields, $options = array())
{
$db =& $this->getDBInstance();
if (DOLIPEAR::isError($db)) {
return $db;
}
if (!$name) {
return $db->raiseError(MDB2_ERROR_CANNOT_CREATE, null, null,
'no valid table name specified', __FUNCTION__);
}
if (empty($fields)) {
return $db->raiseError(MDB2_ERROR_CANNOT_CREATE, null, null,
'no fields specified for table "'.$name.'"', __FUNCTION__);
}
$query_fields = $this->getFieldDeclarationList($fields);
if (DOLIPEAR::isError($query_fields)) {
return $query_fields;
}
if (!empty($options['primary'])) {
$query_fields.= ', PRIMARY KEY ('.implode(', ', array_keys($options['primary'])).')';
}
$name = $db->quoteIdentifier($name, true);
$result = 'CREATE ';
if (!empty($options['temporary'])) {
$result .= $this->_getTemporaryTableQuery();
}
$result .= " TABLE $name ($query_fields)";
return $result;
}
// }}}
// {{{ _getTemporaryTableQuery()
/**
* A method to return the required SQL string that fits between CREATE ... TABLE
* to create the table as a temporary table.
*
* Should be overridden in driver classes to return the correct string for the
* specific database type.
*
* The default is to return the string "TEMPORARY" - this will result in a
* SQL error for any database that does not support temporary tables, or that
* requires a different SQL command from "CREATE TEMPORARY TABLE".
*
* @return string The string required to be placed between "CREATE" and "TABLE"
* to generate a temporary table, if possible.
*/
function _getTemporaryTableQuery()
{
return 'TEMPORARY';
}
// }}}
// {{{ createTable()
/**
* create a new table
*
* @param string $name Name of the database that should be created
* @param array $fields Associative array that contains the definition of each field of the new table
* The indexes of the array entries are the names of the fields of the table an
* the array entry values are associative arrays like those that are meant to be
* passed with the field definitions to get[Type]Declaration() functions.
* array(
* 'id' => array(
* 'type' => 'integer',
* 'unsigned' => 1
* 'notnull' => 1
* 'default' => 0
* ),
* 'name' => array(
* 'type' => 'text',
* 'length' => 12
* ),
* 'password' => array(
* 'type' => 'text',
* 'length' => 12
* )
* );
* @param array $options An associative array of table options:
* array(
* 'comment' => 'Foo',
* 'temporary' => true|false,
* );
* @return mixed MDB2_OK on success, a MDB2 error on failure
* @access public
*/
function createTable($name, $fields, $options = array())
{
$query = $this->_getCreateTableQuery($name, $fields, $options);
if (DOLIPEAR::isError($query)) {
return $query;
}
$db =& $this->getDBInstance();
if (DOLIPEAR::isError($db)) {
return $db;
}
return $db->exec($query);
}
// }}}
// {{{ dropTable()
/**
* drop an existing table
*
* @param string $name name of the table that should be dropped
* @return mixed MDB2_OK on success, a MDB2 error on failure
* @access public
*/
function dropTable($name)
{
$db =& $this->getDBInstance();
if (DOLIPEAR::isError($db)) {
return $db;
}
$name = $db->quoteIdentifier($name, true);
return $db->exec("DROP TABLE $name");
}
// }}}
// {{{ 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 (DOLIPEAR::isError($db)) {
return $db;
}
return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
'method not implemented', __FUNCTION__);
}
// }}}
// {{{ 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 (DOLIPEAR::isError($db)) {
return $db;
}
return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
'method not implementedd', __FUNCTION__);
}
// }}}
// {{{ 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 (DOLIPEAR::isError($db)) {
return $db;
}
return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
'method not implemented', __FUNCTION__);
}
// }}}
// {{{ listViews()
/**
* list all views in the current database
*
* @param string database, the current is default
* NB: not all the drivers can get the view names from
* a database other than the current one
* @return mixed array of view names on success, a MDB2 error on failure
* @access public
*/
function listViews($database = null)
{
$db =& $this->getDBInstance();
if (DOLIPEAR::isError($db)) {
return $db;
}
return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
'method not implemented', __FUNCTION__);
}
// }}}
// {{{ 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 (DOLIPEAR::isError($db)) {
return $db;
}
return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
'method not implemented', __FUNCTION__);
}
// }}}
// {{{ 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 (DOLIPEAR::isError($db)) {
return $db;
}
return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
'method not implemented', __FUNCTION__);
}
// }}}
// {{{ 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 (DOLIPEAR::isError($db)) {
return $db;
}
return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
'method not implemented', __FUNCTION__);
}
// }}}
// {{{ listTables()
/**
* list all tables in the current database
*
* @param string database, the current is default.
* NB: not all the drivers can get the table names from
* a database other than the current one
* @return mixed array of table names on success, a MDB2 error on failure
* @access public
*/
function listTables($database = null)
{
$db =& $this->getDBInstance();
if (DOLIPEAR::isError($db)) {
return $db;
}
return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
'method not implemented', __FUNCTION__);
}
// }}}
// {{{ 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 (DOLIPEAR::isError($db)) {
return $db;
}
return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
'method not implemented', __FUNCTION__);
}
// }}}
// {{{ createIndex()
/**
* Get the stucture of a field into an array
*
* @param string $table name of the table on which the index is to be created
* @param string $name name of the index to be created
* @param array $definition associative array that defines properties of the index to be created.
* Currently, only one property named FIELDS is supported. This property
* is also an associative with the names of the index fields as array
* indexes. Each entry of this array is set to another type of associative
* array that specifies properties of the index that are specific to
* each field.
*
* Currently, only the sorting property is supported. It should be used
* to define the sorting direction of the index. It may be set to either
* ascending or descending.
*
* Not all DBMS support index sorting direction configuration. The DBMS
* drivers of those that do not support it ignore this property. Use the
* function supports() to determine whether the DBMS driver can manage indexes.
*
* Example
* array(
* 'fields' => array(
* 'user_name' => array(
* 'sorting' => 'ascending'
* ),
* 'last_login' => array()
* )
* )
* @return mixed MDB2_OK on success, a MDB2 error on failure
* @access public
*/
function createIndex($table, $name, $definition)
{
$db =& $this->getDBInstance();
if (DOLIPEAR::isError($db)) {
return $db;
}
$table = $db->quoteIdentifier($table, true);
$name = $db->quoteIdentifier($db->getIndexName($name), true);
$query = "CREATE INDEX $name ON $table";
$fields = array();
foreach (array_keys($definition['fields']) as $field) {
$fields[] = $db->quoteIdentifier($field, true);
}
$query .= ' ('. implode(', ', $fields) . ')';
return $db->exec($query);
}
// }}}
// {{{ dropIndex()
/**
* drop existing index
*
* @param string $table name of table that should be used in method
* @param string $name name of the index to be dropped
* @return mixed MDB2_OK on success, a MDB2 error on failure
* @access public
*/
function dropIndex($table, $name)
{
$db =& $this->getDBInstance();
if (DOLIPEAR::isError($db)) {
return $db;
}
$name = $db->quoteIdentifier($db->getIndexName($name), true);
return $db->exec("DROP INDEX $name");
}
// }}}
// {{{ 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 (DOLIPEAR::isError($db)) {
return $db;
}
return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
'method not implemented', __FUNCTION__);
}
// }}}
// {{{ createConstraint()
/**
* create a constraint on a table
*
* @param string $table name of the table on which the constraint is to be created
* @param string $name name of the constraint to be created
* @param array $definition associative array that defines properties of the constraint to be created.
* Currently, only one property named FIELDS is supported. This property
* is also an associative with the names of the constraint fields as array
* constraints. Each entry of this array is set to another type of associative
* array that specifies properties of the constraint that are specific to
* each field.
*
* Example
* array(
* 'fields' => array(
* 'user_name' => array(),
* 'last_login' => array()
* )
* )
* @return mixed MDB2_OK on success, a MDB2 error on failure
* @access public
*/
function createConstraint($table, $name, $definition)
{
$db =& $this->getDBInstance();
if (DOLIPEAR::isError($db)) {
return $db;
}
$table = $db->quoteIdentifier($table, true);
$name = $db->quoteIdentifier($db->getIndexName($name), true);
$query = "ALTER TABLE $table ADD CONSTRAINT $name";
if (!empty($definition['primary'])) {
$query.= ' PRIMARY KEY';
} elseif (!empty($definition['unique'])) {
$query.= ' UNIQUE';
}
$fields = array();
foreach (array_keys($definition['fields']) as $field) {
$fields[] = $db->quoteIdentifier($field, true);
}
$query .= ' ('. implode(', ', $fields) . ')';
return $db->exec($query);
}
// }}}
// {{{ 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 (DOLIPEAR::isError($db)) {
return $db;
}
$table = $db->quoteIdentifier($table, true);
$name = $db->quoteIdentifier($db->getIndexName($name), true);
return $db->exec("ALTER TABLE $table DROP CONSTRAINT $name");
}
// }}}
// {{{ 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 (DOLIPEAR::isError($db)) {
return $db;
}
return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
'method not implemented', __FUNCTION__);
}
// }}}
// {{{ 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 (DOLIPEAR::isError($db)) {
return $db;
}
return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
'method not implemented', __FUNCTION__);
}
// }}}
// {{{ 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($name)
{
$db =& $this->getDBInstance();
if (DOLIPEAR::isError($db)) {
return $db;
}
return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
'method not implemented', __FUNCTION__);
}
// }}}
// {{{ listSequences()
/**
* list all sequences in the current database
*
* @param string database, the current is default
* NB: not all the drivers can get the sequence names from
* a database other than the current one
* @return mixed array of sequence names on success, a MDB2 error on failure
* @access public
*/
function listSequences($database = null)
{
$db =& $this->getDBInstance();
if (DOLIPEAR::isError($db)) {
return $db;
}
return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
'method not implemented', __FUNCTION__);
}
// }}}
}
?>

View File

@ -1,777 +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. |
// +----------------------------------------------------------------------+
// | Authors: Frank M. Kromann <frank@kromann.info> |
// | David Coallier <davidc@php.net> |
// | Lorenzo Alberton <l.alberton@quipo.it> |
// +----------------------------------------------------------------------+
//
// $Id$
//
//require_once 'MDB2/Driver/Manager/Common.php';
require_once PEAR_PATH."/MDB2/Driver/Manager/Common.php";
// {{{ class MDB2_Driver_Manager_mssql
/**
* MDB2 MSSQL driver for the management modules
*
* @package MDB2
* @category Database
* @author Frank M. Kromann <frank@kromann.info>
* @author David Coallier <davidc@php.net>
* @author Lorenzo Alberton <l.alberton@quipo.it>
*/
class MDB2_Driver_Manager_mssql extends MDB2_Driver_Manager_Common
{
// {{{ createDatabase()
/**
* create a new database
*
* @param string $name name of the database that should be created
* @return mixed MDB2_OK on success, a MDB2 error on failure
* @access public
*/
function createDatabase($name)
{
$db =& $this->getDBInstance();
if (DOLIPEAR::isError($db)) {
return $db;
}
$name = $db->quoteIdentifier($name, true);
$query = "CREATE DATABASE $name";
if ($db->options['database_device']) {
$query.= ' ON '.$db->options['database_device'];
$query.= $db->options['database_size'] ? '=' .
$db->options['database_size'] : '';
}
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 (DOLIPEAR::isError($db)) {
return $db;
}
$name = $db->quoteIdentifier($name, true);
return $db->standaloneQuery("DROP DATABASE $name", null, true);
}
// }}}
// {{{ _getTemporaryTableQuery()
/**
* Override the parent method.
*
* @return string The string required to be placed between "CREATE" and "TABLE"
* to generate a temporary table, if possible.
*/
function _getTemporaryTableQuery()
{
return '';
}
// }}}
// {{{ createTable()
/**
* create a new table
*
* @param string $name Name of the database that should be created
* @param array $fields Associative array that contains the definition of each field of the new table
* The indexes of the array entries are the names of the fields of the table an
* the array entry values are associative arrays like those that are meant to be
* passed with the field definitions to get[Type]Declaration() functions.
*
* Example
* array(
*
* 'id' => array(
* 'type' => 'integer',
* 'unsigned' => 1,
* 'notnull' => 1,
* 'default' => 0,
* ),
* 'name' => array(
* 'type' => 'text',
* 'length' => 12,
* ),
* 'description' => array(
* 'type' => 'text',
* 'length' => 12,
* )
* );
* @param array $options An associative array of table options:
* array(
* 'comment' => 'Foo',
* 'temporary' => true|false,
* );
* @return mixed MDB2_OK on success, a MDB2 error on failure
* @access public
*/
function createTable($name, $fields, $options = array())
{
if (!empty($options['temporary'])) {
$name = '#'.$name;
}
return parent::createTable($name, $fields, $options);
}
// }}}
// {{{ 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 (DOLIPEAR::isError($db)) {
return $db;
}
foreach ($changes as $change_name => $change) {
switch ($change_name) {
case 'add':
break;
case 'remove':
break;
case 'name':
case 'rename':
case 'change':
default:
return $db->raiseError(MDB2_ERROR_CANNOT_ALTER, null, null,
'change type "'.$change_name.'" not yet supported', __FUNCTION__);
}
}
if ($check) {
return MDB2_OK;
}
$query = '';
if (!empty($changes['add']) && is_array($changes['add'])) {
foreach ($changes['add'] as $field_name => $field) {
if ($query) {
$query.= ', ';
} else {
$query.= 'ADD COLUMN ';
}
$query.= $db->getDeclaration($field['type'], $field_name, $field);
}
}
if (!empty($changes['remove']) && is_array($changes['remove'])) {
foreach ($changes['remove'] as $field_name => $field) {
if ($query) {
$query.= ', ';
}
$field_name = $db->quoteIdentifier($field_name, true);
$query.= 'DROP COLUMN ' . $field_name;
}
}
if (!$query) {
return MDB2_OK;
}
$name = $db->quoteIdentifier($name, true);
return $db->exec("ALTER TABLE $name $query");
}
// }}}
// {{{ 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 (DOLIPEAR::isError($db)) {
return $db;
}
$query = 'EXEC sp_tables @table_type = "\'TABLE\'"';
$table_names = $db->queryCol($query, null, 2);
if (DOLIPEAR::isError($table_names)) {
return $table_names;
}
$result = array();
foreach ($table_names as $table_name) {
if (!$this->_fixSequenceName($table_name, true)) {
$result[] = $table_name;
}
}
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 (DOLIPEAR::isError($db)) {
return $db;
}
$table = $db->quoteIdentifier($table, true);
$db->setLimit(1);
$result2 = $db->query("SELECT * FROM $table");
if (DOLIPEAR::isError($result2)) {
return $result2;
}
$result = $result2->getColumnNames();
$result2->free();
if (DOLIPEAR::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 (DOLIPEAR::isError($db)) {
return $db;
}
$key_name = 'INDEX_NAME';
$pk_name = 'PK_NAME';
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
if ($db->options['field_case'] == CASE_LOWER) {
$key_name = strtolower($key_name);
$pk_name = strtolower($pk_name);
} else {
$key_name = strtoupper($key_name);
$pk_name = strtoupper($pk_name);
}
}
$table = $db->quote($table, 'text');
$query = "EXEC sp_statistics @table_name=$table";
$indexes = $db->queryCol($query, 'text', $key_name);
if (DOLIPEAR::isError($indexes)) {
return $indexes;
}
$query = "EXEC sp_pkeys @table_name=$table";
$pk_all = $db->queryCol($query, 'text', $pk_name);
$result = array();
foreach ($indexes as $index) {
if (!in_array($index, $pk_all) && ($index = $this->_fixIndexName($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);
}
// }}}
// {{{ 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 (DOLIPEAR::isError($db)) {
return $db;
}
$result = $db->queryCol('SELECT name FROM sys.databases');
if (DOLIPEAR::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 (DOLIPEAR::isError($db)) {
return $db;
}
$result = $db->queryCol('SELECT DISTINCT loginame FROM master..sysprocesses');
if (DOLIPEAR::isError($result) || empty($result)) {
return $result;
}
foreach (array_keys($result) as $k) {
$result[$k] = trim($result[$k]);
}
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 (DOLIPEAR::isError($db)) {
return $db;
}
$query = "SELECT name
FROM sysobjects
WHERE objectproperty(id, N'IsMSShipped') = 0
AND (objectproperty(id, N'IsTableFunction') = 1
OR objectproperty(id, N'IsScalarFunction') = 1)";
/*
SELECT ROUTINE_NAME
FROM INFORMATION_SCHEMA.ROUTINES
WHERE ROUTINE_TYPE = 'FUNCTION'
*/
$result = $db->queryCol($query);
if (DOLIPEAR::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, otherwise, false which
* could be a db error if the db is not instantiated or could
* be the results of the error that occured during the
* querying of the sysobject module.
* @access public
*/
function listTableTriggers($table = null)
{
$db =& $this->getDBInstance();
if (DOLIPEAR::isError($db)) {
return $db;
}
$table = $db->quote($table, 'text');
$query = "SELECT o.name
FROM sysobjects o
WHERE xtype = 'TR'
AND OBJECTPROPERTY(o.id, 'IsMSShipped') = 0";
if (!is_null($table)) {
$query .= " AND object_name(parent_obj) = $table";
}
$result = $db->queryCol($query);
if (DOLIPEAR::isError($result)) {
return $result;
}
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE &&
$db->options['field_case'] == CASE_LOWER)
{
$result = array_map(($db->options['field_case'] == CASE_LOWER ?
'strtolower' : 'strtoupper'), $result);
}
return $result;
}
// }}}
// {{{ listViews()
/**
* list all views in the current database
*
* @param string database, the current is default
* @return mixed array of view names on success, a MDB2 error on failure
* @access public
*/
function listViews()
{
$db =& $this->getDBInstance();
if (DOLIPEAR::isError($db)) {
return $db;
}
$query = "SELECT name
FROM sysobjects
WHERE xtype = 'V'";
/*
SELECT *
FROM sysobjects
WHERE objectproperty(id, N'IsMSShipped') = 0
AND objectproperty(id, N'IsView') = 1
*/
$result = $db->queryCol($query);
if (DOLIPEAR::isError($result)) {
return $result;
}
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE &&
$db->options['field_case'] == CASE_LOWER)
{
$result = array_map(($db->options['field_case'] == CASE_LOWER ?
'strtolower' : 'strtoupper'), $result);
}
return $result;
}
// }}}
// {{{ dropIndex()
/**
* drop existing index
*
* @param string $table name of table that should be used in method
* @param string $name name of the index to be dropped
* @return mixed MDB2_OK on success, a MDB2 error on failure
* @access public
*/
function dropIndex($table, $name)
{
$db =& $this->getDBInstance();
if (DOLIPEAR::isError($db)) {
return $db;
}
$table = $db->quoteIdentifier($table, true);
$name = $db->quoteIdentifier($db->getIndexName($name), true);
return $db->exec("DROP INDEX $table.$name");
}
// }}}
// {{{ 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 (DOLIPEAR::isError($db)) {
return $db;
}
$table = $db->quoteIdentifier($table, true);
$query = "SELECT c.constraint_name
FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS c
WHERE c.constraint_catalog = DB_NAME()
AND c.table_name = '$table'";
$constraints = $db->queryCol($query);
if (DOLIPEAR::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) {
$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 (DOLIPEAR::isError($db)) {
return $db;
}
$sequence_name = $db->quoteIdentifier($db->getSequenceName($seq_name), true);
$seqcol_name = $db->quoteIdentifier($db->options['seqcol_name'], true);
$query = "CREATE TABLE $sequence_name ($seqcol_name " .
"INT PRIMARY KEY CLUSTERED IDENTITY($start,1) NOT NULL)";
$res = $db->exec($query);
if (DOLIPEAR::isError($res)) {
return $res;
}
$query = "SET IDENTITY_INSERT $sequence_name ON ".
"INSERT INTO $sequence_name ($seqcol_name) VALUES ($start)";
$res = $db->exec($query);
if (!DOLIPEAR::isError($res)) {
return MDB2_OK;
}
$result = $db->exec("DROP TABLE $sequence_name");
if (DOLIPEAR::isError($result)) {
return $db->raiseError($result, null, null,
'could not drop inconsistent sequence table', __FUNCTION__);
}
return $db->raiseError($res, null, null,
'could not create sequence table', __FUNCTION__);
}
// }}}
// {{{ dropSequence()
/**
* This function drops an 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 (DOLIPEAR::isError($db)) {
return $db;
}
$sequence_name = $db->quoteIdentifier($db->getSequenceName($seq_name), true);
return $db->exec("DROP TABLE $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 (DOLIPEAR::isError($db)) {
return $db;
}
$query = "SELECT name FROM sysobjects WHERE xtype = 'U'";
$table_names = $db->queryCol($query);
if (DOLIPEAR::isError($table_names)) {
return $table_names;
}
$result = array();
foreach ($table_names as $table_name) {
if ($sqn = $this->_fixSequenceName($table_name, true)) {
$result[] = $sqn;
}
}
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

View File

@ -1,724 +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$
//require_once 'MDB2/Driver/Manager/Common.php';
require_once PEAR_PATH."/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
* @return mixed MDB2_OK on success, a MDB2 error on failure
* @access public
*/
function createDatabase($name)
{
$db =& $this->getDBInstance();
if (DOLIPEAR::isError($db)) {
return $db;
}
$name = $db->quoteIdentifier($name, true);
return $db->standaloneQuery("CREATE DATABASE $name", 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 (DOLIPEAR::isError($db)) {
return $db;
}
$name = $db->quoteIdentifier($name, true);
return $db->standaloneQuery("DROP DATABASE $name", null, true);
}
// }}}
// {{{ 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 (DOLIPEAR::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;
}
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 (DOLIPEAR::isError($result)) {
return $result;
}
}
}
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 (DOLIPEAR::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['type'])) {
$server_info = $db->getServerVersion();
if (DOLIPEAR::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);
$query = "ALTER $field_name TYPE ".$db->datatype->getTypeDeclaration($field['definition']);
$result = $db->exec("ALTER TABLE $name $query");
if (DOLIPEAR::isError($result)) {
return $result;
}
}
if (array_key_exists('default', $field)) {
$query = "ALTER $field_name SET DEFAULT ".$db->quote($field['definition']['default'], $field['definition']['type']);
$result = $db->exec("ALTER TABLE $name $query");
if (DOLIPEAR::isError($result)) {
return $result;
}
}
if (!empty($field['notnull'])) {
$query = "ALTER $field_name ".($field['definition']['notnull'] ? "SET" : "DROP").' NOT NULL';
$result = $db->exec("ALTER TABLE $name $query");
if (DOLIPEAR::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 (DOLIPEAR::isError($result)) {
return $result;
}
}
}
$name = $db->quoteIdentifier($name, true);
if (!empty($changes['name'])) {
$change_name = $db->quoteIdentifier($changes['name'], true);
$result = $db->exec("ALTER TABLE $name RENAME TO ".$change_name);
if (DOLIPEAR::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 (DOLIPEAR::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 (DOLIPEAR::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 (DOLIPEAR::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 (DOLIPEAR::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 (DOLIPEAR::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 (DOLIPEAR::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 (DOLIPEAR::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 (DOLIPEAR::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 (DOLIPEAR::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 (DOLIPEAR::isError($db)) {
return $db;
}
$query = 'SELECT trg.tgname AS trigger_name
FROM pg_trigger trg,
pg_class tbl
WHERE trg.tgrelid = tbl.oid';
if (!is_null($table)) {
$table = $db->quote(strtoupper($table), 'text');
$query .= " AND tbl.relname = $table";
}
$result = $db->queryCol($query);
if (DOLIPEAR::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 (DOLIPEAR::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 (DOLIPEAR::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 (DOLIPEAR::isError($db)) {
return $db;
}
$table = $db->quoteIdentifier($table, true);
$db->setLimit(1);
$result2 = $db->query("SELECT * FROM $table");
if (DOLIPEAR::isError($result2)) {
return $result2;
}
$result = $result2->getColumnNames();
$result2->free();
if (DOLIPEAR::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 (DOLIPEAR::isError($db)) {
return $db;
}
$table = $db->quote($table, 'text');
$subquery = "SELECT indexrelid FROM pg_index, pg_class";
$subquery.= " WHERE pg_class.relname=$table AND pg_class.oid=pg_index.indrelid AND indisunique != 't' AND indisprimary != 't'";
$query = "SELECT relname FROM pg_class WHERE oid IN ($subquery)";
$indexes = $db->queryCol($query, 'text');
if (DOLIPEAR::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);
}
// }}}
// {{{ 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 (DOLIPEAR::isError($db)) {
return $db;
}
$table = $db->quote($table, 'text');
$subquery = "SELECT indexrelid FROM pg_index, pg_class";
$subquery.= " WHERE pg_class.relname=$table AND pg_class.oid=pg_index.indrelid AND (indisunique = 't' OR indisprimary = 't')";
$query = "SELECT relname FROM pg_class WHERE oid IN ($subquery)";
$constraints = $db->queryCol($query);
if (DOLIPEAR::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 (DOLIPEAR::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 (DOLIPEAR::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 (DOLIPEAR::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 (DOLIPEAR::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;
}
}
?>

View File

@ -1,58 +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$
//
/**
* Base class for the natuve modules that is extended by each MDB2 driver
*
* @package MDB2
* @category Database
* @author Lukas Smith <smith@pooteeweet.org>
*/
class MDB2_Driver_Native_Common extends MDB2_Module_Common
{
}
?>

View File

@ -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, 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$
//
//require_once 'MDB2/Driver/Native/Common.php';
require_once PEAR_PATH."/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
{
}
?>

View File

@ -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$
//
//require_once 'MDB2/Driver/Native/Common.php';
require_once PEAR_PATH."/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
{
}
?>

View File

@ -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$
//
//require_once 'MDB2/Driver/Native/Common.php';
require_once PEAR_PATH."/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
{
}
?>

View File

@ -1,89 +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$
//require_once 'MDB2/Driver/Native/Common.php';
require_once PEAR_PATH."/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 (DOLIPEAR::isError($db)) {
return $db;
}
$connection = $db->getConnection();
if (DOLIPEAR::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;
}
}
?>

View File

@ -1,476 +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$
//
/**
* @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
*
* @package MDB2
* @category Database
* @author Lukas Smith <smith@pooteeweet.org>
*/
class MDB2_Driver_Reverse_Common extends MDB2_Module_Common
{
// }}}
// {{{ 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 (DOLIPEAR::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 (DOLIPEAR::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] => 1
* [fields] => array (
* [field1name] => array() // one entry per each field covered
* [field2name] => array() // by the index
* [field3name] => array(
* [sorting] => ascending
* )
* )
* );
* </pre>
* @access public
*/
function getTableConstraintDefinition($table, $index)
{
$db =& $this->getDBInstance();
if (DOLIPEAR::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 (DOLIPEAR::isError($db)) {
return $db;
}
$start = $db->currId($sequence);
if (DOLIPEAR::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 (DOLIPEAR::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 (DOLIPEAR::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 (DOLIPEAR::isError($fields)) {
return $fields;
}
$flags = array();
$idxname_format = $db->getOption('idxname_format');
$db->setOption('idxname_format', '%s');
$indexes = $db->manager->listTableIndexes($result);
if (DOLIPEAR::isError($indexes)) {
$db->setOption('idxname_format', $idxname_format);
return $indexes;
}
foreach ($indexes as $index) {
$definition = $this->getTableIndexDefinition($result, $index);
if (DOLIPEAR::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 (DOLIPEAR::isError($constraints)) {
return $constraints;
}
foreach ($constraints as $constraint) {
$definition = $this->getTableConstraintDefinition($result, $constraint);
if (DOLIPEAR::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;
}
}
}
}
if ($mode) {
$res['num_fields'] = count($fields);
}
foreach ($fields as $i => $field) {
$definition = $this->getTableFieldDefinition($result, $field);
if (DOLIPEAR::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;
}
}
?>

View File

@ -1,592 +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 |
// | 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$
//
//require_once 'MDB2/Driver/Reverse/Common.php';
require_once PEAR_PATH."/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 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, $field_name)
{
$db =& $this->getDBInstance();
if (DOLIPEAR::isError($db)) {
return $db;
}
$result = $db->loadModule('Datatype', null, true);
if (DOLIPEAR::isError($result)) {
return $result;
}
$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'
ORDER BY t.table_name";
$column = $db->queryRow($query, null, MDB2_FETCHMODE_ASSOC);
if (DOLIPEAR::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 (DOLIPEAR::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 (is_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 (!is_null($length)) {
$definition[0]['length'] = $length;
}
if (!is_null($unsigned)) {
$definition[0]['unsigned'] = $unsigned;
}
if (!is_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 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, $index_name)
{
$db =& $this->getDBInstance();
if (DOLIPEAR::isError($db)) {
return $db;
}
$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)
ORDER BY tablename, indexname, ik.keyno";
$index_name_mdb2 = $db->getIndexName($index_name);
$result = $db->queryRow(sprintf($query, $index_name_mdb2));
if (!DOLIPEAR::isError($result) && !is_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 (DOLIPEAR::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 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, $constraint_name)
{
$db =& $this->getDBInstance();
if (DOLIPEAR::isError($db)) {
return $db;
}
$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',
k.ordinal_position
FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE k
LEFT JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS c
ON k.table_name = c.table_name
AND k.constraint_name = c.constraint_name
AND k.table_schema = c.table_schema
WHERE k.constraint_catalog = DB_NAME()
AND k.table_name = '$table'
AND k.constraint_name = '%s'
ORDER BY k.constraint_name,
k.ordinal_position";
$constraint_name_mdb2 = $db->getIndexName($constraint_name);
$result = $db->queryRow(sprintf($query, $constraint_name_mdb2));
if (!DOLIPEAR::isError($result) && !is_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 (DOLIPEAR::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['ordinal_position']
);
/*
if (!empty($row['collation'])) {
$definition['fields'][$column_name]['sorting'] = ($row['collation'] == 'ASC'
? 'ascending' : 'descending');
}
*/
$definition['primary'] = $row['primary'];
$definition['unique'] = $row['unique'];
$definition['foreign'] = $row['foreign'];
$definition['check'] = $row['check'];
}
$result->free();
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 (DOLIPEAR::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 (DOLIPEAR::isError($def)) {
return $def;
}
$trg_body = $db->queryCol('EXEC sp_helptext '. $db->quote($trigger, 'text'), 'text');
if (!DOLIPEAR::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 (DOLIPEAR::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 (DOLIPEAR::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 (DOLIPEAR::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);
}
}
// }}}
}
?>

View File

@ -1,438 +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$
//
//require_once 'MDB2/Driver/Reverse/Common.php';
require_once PEAR_PATH."/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 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, $field_name)
{
$db =& $this->getDBInstance();
if (DOLIPEAR::isError($db)) {
return $db;
}
$result = $db->loadModule('Datatype', null, true);
if (DOLIPEAR::isError($result)) {
return $result;
}
$table = $db->quoteIdentifier($table, true);
$query = "SHOW COLUMNS FROM $table LIKE ".$db->quote($field_name);
$columns = $db->queryAll($query, null, MDB2_FETCHMODE_ASSOC);
if (DOLIPEAR::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 (DOLIPEAR::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 (is_null($default) && $notnull) {
$default = '';
}
}
$autoincrement = false;
if (!empty($column['extra']) && $column['extra'] == 'auto_increment') {
$autoincrement = true;
}
$definition[0] = array(
'notnull' => $notnull,
'nativetype' => preg_replace('/^([a-z]+)[^a-z].*/i', '\\1', $column['type'])
);
if (!is_null($length)) {
$definition[0]['length'] = $length;
}
if (!is_null($unsigned)) {
$definition[0]['unsigned'] = $unsigned;
}
if (!is_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 structure of an index into an array
*
* @param string $table 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 getTableIndexDefinition($table, $constraint_name)
{
$db =& $this->getDBInstance();
if (DOLIPEAR::isError($db)) {
return $db;
}
$table = $db->quoteIdentifier($table, true);
$query = "SHOW INDEX FROM $table /*!50002 WHERE Key_name = %s */";
$constraint_name_mdb2 = $db->getIndexName($constraint_name);
$result = $db->queryRow(sprintf($query, $db->quote($constraint_name_mdb2)));
if (!DOLIPEAR::isError($result) && !is_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 (DOLIPEAR::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 ($constraint_name == $key_name) {
if (!$row['non_unique']) {
return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
$constraint_name . ' is not an existing table constraint', __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,
$constraint_name . ' is not an existing table constraint', __FUNCTION__);
}
return $definition;
}
// }}}
// {{{ getTableConstraintDefinition()
/**
* Get the structure of a constraint into an array
*
* @param string $table 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 getTableConstraintDefinition($table, $index_name)
{
$db =& $this->getDBInstance();
if (DOLIPEAR::isError($db)) {
return $db;
}
$table = $db->quoteIdentifier($table, true);
$query = "SHOW INDEX FROM $table /*!50002 WHERE Key_name = %s */";
if (strtolower($index_name) != 'primary') {
$index_name_mdb2 = $db->getIndexName($index_name);
$result = $db->queryRow(sprintf($query, $db->quote($index_name_mdb2)));
if (!DOLIPEAR::isError($result) && !is_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 (DOLIPEAR::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,
'it was not specified an existing table constraint', __FUNCTION__);
}
if ($row['key_name'] == 'PRIMARY') {
$definition['primary'] = true;
} else {
$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 $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
'it was not specified 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 (DOLIPEAR::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 (DOLIPEAR::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 (DOLIPEAR::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 (DOLIPEAR::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;
}
}
?>

View File

@ -1,501 +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$
//
//require_once 'MDB2/Driver/Reverse/Common.php';
require_once PEAR_PATH."/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 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, $field_name)
{
$db =& $this->getDBInstance();
if (DOLIPEAR::isError($db)) {
return $db;
}
$result = $db->loadModule('Datatype', null, true);
if (DOLIPEAR::isError($result)) {
return $result;
}
$table = $db->quoteIdentifier($table, true);
$query = "SHOW COLUMNS FROM $table LIKE ".$db->quote($field_name);
$columns = $db->queryAll($query, null, MDB2_FETCHMODE_ASSOC);
if (DOLIPEAR::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 (DOLIPEAR::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 (is_null($default) && $notnull) {
$default = '';
}
}
$autoincrement = false;
if (!empty($column['extra']) && $column['extra'] == 'auto_increment') {
$autoincrement = true;
}
$definition[0] = array(
'notnull' => $notnull,
'nativetype' => preg_replace('/^([a-z]+)[^a-z].*/i', '\\1', $column['type'])
);
if (!is_null($length)) {
$definition[0]['length'] = $length;
}
if (!is_null($unsigned)) {
$definition[0]['unsigned'] = $unsigned;
}
if (!is_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 structure of an index into an array
*
* @param string $table 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, $index_name)
{
$db =& $this->getDBInstance();
if (DOLIPEAR::isError($db)) {
return $db;
}
$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 (!DOLIPEAR::isError($result) && !is_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 (DOLIPEAR::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,
'it was not specified 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,
'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 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, $constraint_name)
{
$db =& $this->getDBInstance();
if (DOLIPEAR::isError($db)) {
return $db;
}
$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 (!DOLIPEAR::isError($result) && !is_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 (DOLIPEAR::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 ($constraint_name == $key_name) {
if ($row['non_unique']) {
return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
$constraint_name . ' is not an existing table constraint', __FUNCTION__);
}
if ($row['key_name'] == 'PRIMARY') {
$definition['primary'] = true;
} else {
$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 $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 (DOLIPEAR::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 (DOLIPEAR::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 (DOLIPEAR::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 (DOLIPEAR::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;
}
}
?>

View File

@ -1,440 +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. |
// +----------------------------------------------------------------------+
// | Authors: Paul Cooper <pgc@ucecom.com> |
// | Lorenzo Alberton <l.alberton@quipo.it> |
// +----------------------------------------------------------------------+
//
// $Id$
//require_once 'MDB2/Driver/Reverse/Common.php';
require_once PEAR_PATH."/MDB2/Driver/Reverse/Common.php";
/**
* MDB2 PostGreSQL driver for the schema reverse engineering module
*
* @package MDB2
* @category Database
* @author Paul Cooper <pgc@ucecom.com>
*/
class MDB2_Driver_Reverse_pgsql extends MDB2_Driver_Reverse_Common
{
// {{{ 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 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, $field_name)
{
$db =& $this->getDBInstance();
if (DOLIPEAR::isError($db)) {
return $db;
}
$result = $db->loadModule('Datatype', null, true);
if (DOLIPEAR::isError($result)) {
return $result;
}
$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 (DOLIPEAR::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 (DOLIPEAR::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'
&& !preg_match("/nextval\('([^']+)'/", $column['default'])
) {
$default = $column['default'];#substr($column['adsrc'], 1, -1);
if (is_null($default) && $notnull) {
$default = '';
}
}
$autoincrement = false;
if (preg_match("/nextval\('([^']+)'/", $column['default'], $nextvals)) {
$autoincrement = true;
}
$definition[0] = array('notnull' => $notnull, 'nativetype' => $column['type']);
if (!is_null($length)) {
$definition[0]['length'] = $length;
}
if (!is_null($unsigned)) {
$definition[0]['unsigned'] = $unsigned;
}
if (!is_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 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, $index_name)
{
$db =& $this->getDBInstance();
if (DOLIPEAR::isError($db)) {
return $db;
}
$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 (DOLIPEAR::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 (DOLIPEAR::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);
$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 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, $constraint_name)
{
$db =& $this->getDBInstance();
if (DOLIPEAR::isError($db)) {
return $db;
}
$query = 'SELECT relname, indisunique, indisprimary, indkey FROM pg_index, pg_class';
$query.= ' WHERE pg_class.oid = pg_index.indexrelid';
$query.= " AND (indisunique = 't' OR indisprimary = 't')";
$query.= ' 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 (DOLIPEAR::isError($row) || empty($row)) {
// fallback to the given $index_name, without transformation
$row = $db->queryRow(sprintf($query, $db->quote($constraint_name, 'text')), null, MDB2_FETCHMODE_ASSOC);
}
if (DOLIPEAR::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__);
}
$row = array_change_key_case($row, CASE_LOWER);
$db->loadModule('Manager', null, true);
$columns = $db->manager->listTableFields($table);
$definition = array();
if ($row['indisprimary'] == 't') {
$definition['primary'] = true;
} elseif ($row['indisunique'] == 't') {
$definition['unique'] = true;
}
$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;
}
// }}}
// {{{ 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 (DOLIPEAR::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,
trg.tgenabled 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 (DOLIPEAR::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 (DOLIPEAR::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;
}
}
?>

View File

@ -1,962 +0,0 @@
<?php
// vim: set et ts=4 sw=4 fdm=marker:
// +----------------------------------------------------------------------+
// | 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: Frank M. Kromann <frank@kromann.info> |
// +----------------------------------------------------------------------+
//
// $Id$
//
// {{{ Class MDB2_Driver_mssql
/**
* MDB2 MSSQL Server driver
*
* @package MDB2
* @category Database
* @author Frank M. Kromann <frank@kromann.info>
*/
class MDB2_Driver_mssql extends MDB2_Driver_Common
{
// {{{ properties
var $string_quoting = array('start' => "'", 'end' => "'", 'escape' => "'", 'escape_pattern' => false);
var $identifier_quoting = array('start' => '[', 'end' => ']', 'escape' => ']');
// }}}
// {{{ constructor
/**
* Constructor
*/
function __construct()
{
parent::__construct();
$this->phptype = 'mssql';
$this->dbsyntax = 'mssql';
$this->supported['sequences'] = 'emulated';
$this->supported['indexes'] = true;
$this->supported['affected_rows'] = true;
$this->supported['transactions'] = true;
$this->supported['savepoints'] = false;
$this->supported['summary_functions'] = true;
$this->supported['order_by_text'] = true;
$this->supported['current_id'] = 'emulated';
$this->supported['limit_queries'] = 'emulated';
$this->supported['LOBs'] = true;
$this->supported['replace'] = 'emulated';
$this->supported['sub_selects'] = true;
$this->supported['auto_increment'] = true;
$this->supported['primary_key'] = true;
$this->supported['result_introspection'] = true;
$this->supported['prepared_statements'] = 'emulated';
$this->supported['pattern_escaping'] = true;
$this->options['database_device'] = false;
$this->options['database_size'] = false;
}
// }}}
// {{{ errorInfo()
/**
* This method is used to collect information about an error
*
* @param integer $error
* @return array
* @access public
*/
function errorInfo($error = null)
{
$native_code = null;
if ($this->connection) {
$result = @mssql_query('select @@ERROR as ErrorCode', $this->connection);
if ($result) {
$native_code = @mssql_result($result, 0, 0);
@mssql_free_result($result);
}
}
$native_msg = @mssql_get_last_message();
if (is_null($error)) {
static $ecode_map;
if (empty($ecode_map)) {
$ecode_map = array(
102 => MDB2_ERROR_SYNTAX,
110 => MDB2_ERROR_VALUE_COUNT_ON_ROW,
155 => MDB2_ERROR_NOSUCHFIELD,
156 => MDB2_ERROR_SYNTAX,
170 => MDB2_ERROR_SYNTAX,
207 => MDB2_ERROR_NOSUCHFIELD,
208 => MDB2_ERROR_NOSUCHTABLE,
245 => MDB2_ERROR_INVALID_NUMBER,
319 => MDB2_ERROR_SYNTAX,
321 => MDB2_ERROR_NOSUCHFIELD,
325 => MDB2_ERROR_SYNTAX,
336 => MDB2_ERROR_SYNTAX,
515 => MDB2_ERROR_CONSTRAINT_NOT_NULL,
547 => MDB2_ERROR_CONSTRAINT,
1018 => MDB2_ERROR_SYNTAX,
1035 => MDB2_ERROR_SYNTAX,
1913 => MDB2_ERROR_ALREADY_EXISTS,
2209 => MDB2_ERROR_SYNTAX,
2223 => MDB2_ERROR_SYNTAX,
2248 => MDB2_ERROR_SYNTAX,
2256 => MDB2_ERROR_SYNTAX,
2257 => MDB2_ERROR_SYNTAX,
2627 => MDB2_ERROR_CONSTRAINT,
2714 => MDB2_ERROR_ALREADY_EXISTS,
3607 => MDB2_ERROR_DIVZERO,
3701 => MDB2_ERROR_NOSUCHTABLE,
7630 => MDB2_ERROR_SYNTAX,
8134 => MDB2_ERROR_DIVZERO,
9303 => MDB2_ERROR_SYNTAX,
9317 => MDB2_ERROR_SYNTAX,
9318 => MDB2_ERROR_SYNTAX,
9331 => MDB2_ERROR_SYNTAX,
9332 => MDB2_ERROR_SYNTAX,
15253 => MDB2_ERROR_SYNTAX,
);
}
if (isset($ecode_map[$native_code])) {
if ($native_code == 3701
&& preg_match('/Cannot drop the index/i', $native_msg)
) {
$error = MDB2_ERROR_NOT_FOUND;
} else {
$error = $ecode_map[$native_code];
}
}
}
return array($error, $native_code, $native_msg);
}
// }}}
// {{{ function escapePattern($text)
/**
* Quotes pattern (% and _) characters in a string)
*
* @param string the input string to quote
*
* @return string quoted string
*
* @access public
*/
function escapePattern($text)
{
$text = str_replace("[", "[ [ ]", $text);
foreach ($this->wildcards as $wildcard) {
$text = str_replace($wildcard, '[' . $wildcard . ']', $text);
}
return $text;
}
// }}}
// {{{ beginTransaction()
/**
* Start a transaction or set a savepoint.
*
* @param string name of a savepoint to set
* @return mixed MDB2_OK on success, a MDB2 error on failure
*
* @access public
*/
function beginTransaction($savepoint = null)
{
$this->debug('Starting transaction/savepoint', __FUNCTION__, array('is_manip' => true, 'savepoint' => $savepoint));
if (!is_null($savepoint)) {
if (!$this->in_transaction) {
return $this->raiseError(MDB2_ERROR_INVALID, null, null,
'savepoint cannot be released when changes are auto committed', __FUNCTION__);
}
$query = 'SAVE TRANSACTION '.$savepoint;
return $this->_doQuery($query, true);
} elseif ($this->in_transaction) {
return MDB2_OK; //nothing to do
}
if (!$this->destructor_registered && $this->opened_persistent) {
$this->destructor_registered = true;
register_shutdown_function('MDB2_closeOpenTransactions');
}
$result =& $this->_doQuery('BEGIN TRANSACTION', true);
if (DOLIPEAR::isError($result)) {
return $result;
}
$this->in_transaction = true;
return MDB2_OK;
}
// }}}
// {{{ commit()
/**
* Commit the database changes done during a transaction that is in
* progress or release a savepoint. This function may only be called when
* auto-committing is disabled, otherwise it will fail. Therefore, a new
* transaction is implicitly started after committing the pending changes.
*
* @param string name of a savepoint to release
* @return mixed MDB2_OK on success, a MDB2 error on failure
*
* @access public
*/
function commit($savepoint = null)
{
$this->debug('Committing transaction/savepoint', __FUNCTION__, array('is_manip' => true, 'savepoint' => $savepoint));
if (!$this->in_transaction) {
return $this->raiseError(MDB2_ERROR_INVALID, null, null,
'commit/release savepoint cannot be done changes are auto committed', __FUNCTION__);
}
if (!is_null($savepoint)) {
return MDB2_OK;
}
$result =& $this->_doQuery('COMMIT TRANSACTION', true);
if (DOLIPEAR::isError($result)) {
return $result;
}
$this->in_transaction = false;
return MDB2_OK;
}
// }}}
// {{{ rollback()
/**
* Cancel any database changes done during a transaction or since a specific
* savepoint that is in progress. This function may only be called when
* auto-committing is disabled, otherwise it will fail. Therefore, a new
* transaction is implicitly started after canceling the pending changes.
*
* @param string name of a savepoint to rollback to
* @return mixed MDB2_OK on success, a MDB2 error on failure
*
* @access public
*/
function rollback($savepoint = null)
{
$this->debug('Rolling back transaction/savepoint', __FUNCTION__, array('is_manip' => true, 'savepoint' => $savepoint));
if (!$this->in_transaction) {
return $this->raiseError(MDB2_ERROR_INVALID, null, null,
'rollback cannot be done changes are auto committed', __FUNCTION__);
}
if (!is_null($savepoint)) {
$query = 'ROLLBACK TRANSACTION '.$savepoint;
return $this->_doQuery($query, true);
}
$result =& $this->_doQuery('ROLLBACK TRANSACTION', true);
if (DOLIPEAR::isError($result)) {
return $result;
}
$this->in_transaction = false;
return MDB2_OK;
}
// }}}
// {{{ connect()
/**
* Connect to the database
*
* @return true on success, MDB2 Error Object on failure
*/
function connect()
{
if (is_resource($this->connection)) {
if (count(array_diff($this->connected_dsn, $this->dsn)) == 0
&& $this->opened_persistent == $this->options['persistent']
) {
return MDB2_OK;
}
$this->disconnect(false);
}
if (!DOLIPEAR::loadExtension($this->phptype)) {
return $this->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
'extension '.$this->phptype.' is not compiled into PHP', __FUNCTION__);
}
$params = array(
$this->dsn['hostspec'] ? $this->dsn['hostspec'] : 'localhost',
$this->dsn['username'] ? $this->dsn['username'] : null,
$this->dsn['password'] ? $this->dsn['password'] : null,
);
if ($this->dsn['port']) {
$params[0].= ((substr(PHP_OS, 0, 3) == 'WIN') ? ',' : ':').$this->dsn['port'];
}
$connect_function = $this->options['persistent'] ? 'mssql_pconnect' : 'mssql_connect';
$connection = @call_user_func_array($connect_function, $params);
if ($connection <= 0) {
return $this->raiseError(MDB2_ERROR_CONNECT_FAILED, null, null,
'unable to establish a connection', __FUNCTION__, __FUNCTION__);
}
if (!empty($this->dsn['charset'])) {
$result = $this->setCharset($this->dsn['charset'], $connection);
if (DOLIPEAR::isError($result)) {
return $result;
}
}
if ((bool)ini_get('mssql.datetimeconvert')) {
@ini_set('mssql.datetimeconvert', '0');
}
if (empty($this->dsn['disable_iso_date'])) {
@mssql_query('SET DATEFORMAT ymd', $connection);
}
$this->connection = $connection;
$this->connected_dsn = $this->dsn;
$this->connected_database_name = '';
$this->opened_persistent = $this->options['persistent'];
$this->dbsyntax = $this->dsn['dbsyntax'] ? $this->dsn['dbsyntax'] : $this->phptype;
if ($this->database_name) {
if ($this->database_name != $this->connected_database_name) {
if (!@mssql_select_db($this->database_name, $connection)) {
$err = $this->raiseError(null, null, null,
'Could not select the database: '.$this->database_name, __FUNCTION__);
return $err;
}
$this->connected_database_name = $this->database_name;
}
}
return MDB2_OK;
}
// }}}
// {{{ disconnect()
/**
* Log out and disconnect from the database.
*
* @param boolean $force if the disconnect should be forced even if the
* connection is opened persistently
* @return mixed true on success, false if not connected and error
* object on error
* @access public
*/
function disconnect($force = true)
{
if (is_resource($this->connection)) {
if ($this->in_transaction) {
$dsn = $this->dsn;
$database_name = $this->database_name;
$persistent = $this->options['persistent'];
$this->dsn = $this->connected_dsn;
$this->database_name = $this->connected_database_name;
$this->options['persistent'] = $this->opened_persistent;
$this->rollback();
$this->dsn = $dsn;
$this->database_name = $database_name;
$this->options['persistent'] = $persistent;
}
if (!$this->opened_persistent || $force) {
@mssql_close($this->connection);
}
}
return parent::disconnect($force);
}
// }}}
// {{{ _doQuery()
/**
* Execute a query
* @param string $query query
* @param boolean $is_manip if the query is a manipulation query
* @param resource $connection
* @param string $database_name
* @return result or error object
* @access protected
*/
function &_doQuery($query, $is_manip = false, $connection = null, $database_name = null)
{
$this->last_query = $query;
$result = $this->debug($query, 'query', array('is_manip' => $is_manip, 'when' => 'pre'));
if ($result) {
if (DOLIPEAR::isError($result)) {
return $result;
}
$query = $result;
}
if ($this->options['disable_query']) {
$result = $is_manip ? 0 : null;
return $result;
}
if (is_null($connection)) {
$connection = $this->getConnection();
if (DOLIPEAR::isError($connection)) {
return $connection;
}
}
if (is_null($database_name)) {
$database_name = $this->database_name;
}
if ($database_name) {
if ($database_name != $this->connected_database_name) {
if (!@mssql_select_db($database_name, $connection)) {
$err = $this->raiseError(null, null, null,
'Could not select the database: '.$database_name, __FUNCTION__);
return $err;
}
$this->connected_database_name = $database_name;
}
}
$result = @mssql_query($query, $connection);
if (!$result) {
$err =& $this->raiseError(null, null, null,
'Could not execute statement', __FUNCTION__);
return $err;
}
$this->debug($query, 'query', array('is_manip' => $is_manip, 'when' => 'post', 'result' => $result));
return $result;
}
// }}}
// {{{ _affectedRows()
/**
* Returns the number of rows affected
*
* @param resource $result
* @param resource $connection
* @return mixed MDB2 Error Object or the number of rows affected
* @access private
*/
function _affectedRows($connection, $result = null)
{
if (is_null($connection)) {
$connection = $this->getConnection();
if (DOLIPEAR::isError($connection)) {
return $connection;
}
}
return @mssql_rows_affected($connection);
}
// }}}
// {{{ _modifyQuery()
/**
* Changes a query string for various DBMS specific reasons
*
* @param string $query query to modify
* @param boolean $is_manip if it is a DML query
* @param integer $limit limit the number of rows
* @param integer $offset start reading from given offset
* @return string modified query
* @access protected
*/
function _modifyQuery($query, $is_manip, $limit, $offset)
{
if ($limit > 0) {
$fetch = $offset + $limit;
if (!$is_manip) {
return preg_replace('/^([\s(])*SELECT( DISTINCT)?(?!\s*TOP\s*\()/i',
"\\1SELECT\\2 TOP $fetch", $query);
}
}
return $query;
}
// }}}
// {{{ getServerVersion()
/**
* return version information about the server
*
* @param bool $native determines if the raw version string should be returned
* @return mixed array/string with version information or MDB2 error object
* @access public
*/
function getServerVersion($native = false)
{
if ($this->connected_server_info) {
$server_info = $this->connected_server_info;
} else {
$query = 'SELECT @@VERSION';
$server_info = $this->queryOne($query, 'text');
if (DOLIPEAR::isError($server_info)) {
return $server_info;
}
}
// cache server_info
$this->connected_server_info = $server_info;
if (!$native && !DOLIPEAR::isError($server_info)) {
if (preg_match('/([0-9]+)\.([0-9]+)\.([0-9]+)/', $server_info, $tmp)) {
$server_info = array(
'major' => $tmp[1],
'minor' => $tmp[2],
'patch' => $tmp[3],
'extra' => null,
'native' => $server_info,
);
} else {
$server_info = array(
'major' => null,
'minor' => null,
'patch' => null,
'extra' => null,
'native' => $server_info,
);
}
}
return $server_info;
}
// }}}
// {{{ _checkSequence
/**
* Checks if there's a sequence that exists.
*
* @param string $seq_name The sequence name to verify.
* @return bool $tableExists The value if the table exists or not
* @access private
*/
function _checkSequence($seq_name)
{
$query = "SELECT * FROM $seq_name";
$tableExists =& $this->_doQuery($query, true);
if (DOLIPEAR::isError($tableExists)) {
if ($tableExists->getCode() == MDB2_ERROR_NOSUCHTABLE) {
return false;
}
//return $tableExists;
return false;
}
return mssql_result($tableExists, 0, 0);
}
// }}}
// {{{ nextID()
/**
* Returns the next free id of a sequence
*
* @param string $seq_name name of the sequence
* @param boolean $ondemand when true the sequence is
* automatic created, if it
* not exists
*
* @return mixed MDB2 Error Object or id
* @access public
*/
function nextID($seq_name, $ondemand = true)
{
$sequence_name = $this->quoteIdentifier($this->getSequenceName($seq_name), true);
$seqcol_name = $this->quoteIdentifier($this->options['seqcol_name'], true);
$this->expectError(MDB2_ERROR_NOSUCHTABLE);
$seq_val = $this->_checkSequence($sequence_name);
if ($seq_val) {
$query = "SET IDENTITY_INSERT $sequence_name OFF ".
"INSERT INTO $sequence_name ($seqcol_name) DEFAULT VALUES";
} else {
$query = "INSERT INTO $sequence_name ($seqcol_name) VALUES (0)";
}
$result =& $this->_doQuery($query, true);
$this->popExpect();
if (DOLIPEAR::isError($result)) {
if ($ondemand && !$this->_checkSequence($sequence_name)) {
$this->loadModule('Manager', null, true);
$result = $this->manager->createSequence($seq_name);
if (DOLIPEAR::isError($result)) {
return $this->raiseError($result, null, null,
'on demand sequence '.$seq_name.' could not be created', __FUNCTION__);
} else {
return $this->nextID($seq_name, false);
}
}
return $result;
}
$value = $this->lastInsertID($sequence_name);
if (is_numeric($value)) {
$query = "DELETE FROM $sequence_name WHERE $seqcol_name < $value";
$result =& $this->_doQuery($query, true);
if (DOLIPEAR::isError($result)) {
$this->warnings[] = 'nextID: could not delete previous sequence table values from '.$seq_name;
}
}
return $value;
}
// }}}
// {{{ lastInsertID()
/**
* Returns the autoincrement ID if supported or $id or fetches the current
* ID in a sequence called: $table.(empty($field) ? '' : '_'.$field)
*
* @param string $table name of the table into which a new row was inserted
* @param string $field name of the field into which a new row was inserted
* @return mixed MDB2 Error Object or id
* @access public
*/
function lastInsertID($table = null, $field = null)
{
$server_info = $this->getServerVersion();
if (is_array($server_info) && !is_null($server_info['major'])
&& $server_info['major'] >= 8
) {
$query = "SELECT SCOPE_IDENTITY()";
} else {
$query = "SELECT @@IDENTITY";
}
return $this->queryOne($query, 'integer');
}
// }}}
}
// }}}
// {{{ Class MDB2_Result_mssql
/**
* MDB2 MSSQL Server result driver
*
* @package MDB2
* @category Database
* @author Frank M. Kromann <frank@kromann.info>
*/
class MDB2_Result_mssql extends MDB2_Result_Common
{
// {{{ _skipLimitOffset()
/**
* Skip the first row of a result set.
*
* @param resource $result
* @return mixed a result handle or MDB2_OK on success, a MDB2 error on failure
* @access protected
*/
function _skipLimitOffset()
{
if ($this->limit) {
if ($this->rownum >= $this->limit) {
return false;
}
}
if ($this->offset) {
while ($this->offset_count < $this->offset) {
++$this->offset_count;
if (!is_array(@mssql_fetch_row($this->result))) {
$this->offset_count = $this->limit;
return false;
}
}
}
return MDB2_OK;
}
// }}}
// {{{ fetchRow()
/**
* Fetch a row and insert the data into an existing array.
*
* @param int $fetchmode how the array data should be indexed
* @param int $rownum number of the row where the data can be found
* @return int data array on success, a MDB2 error on failure
* @access public
*/
function &fetchRow($fetchmode = MDB2_FETCHMODE_DEFAULT, $rownum = null)
{
if (!$this->_skipLimitOffset()) {
$null = null;
return $null;
}
if (!is_null($rownum)) {
$seek = $this->seek($rownum);
if (DOLIPEAR::isError($seek)) {
return $seek;
}
}
if ($fetchmode == MDB2_FETCHMODE_DEFAULT) {
$fetchmode = $this->db->fetchmode;
}
if ($fetchmode & MDB2_FETCHMODE_ASSOC) {
$row = @mssql_fetch_assoc($this->result);
if (is_array($row)
&& $this->db->options['portability'] & MDB2_PORTABILITY_FIX_CASE
) {
$row = array_change_key_case($row, $this->db->options['field_case']);
}
} else {
$row = @mssql_fetch_row($this->result);
}
if (!$row) {
if ($this->result === false) {
$err =& $this->db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null,
'resultset has already been freed', __FUNCTION__);
return $err;
}
$null = null;
return $null;
}
$mode = $this->db->options['portability'] & MDB2_PORTABILITY_EMPTY_TO_NULL;
if ($mode) {
$this->db->_fixResultArrayValues($row, $mode);
}
if (!empty($this->types)) {
$row = $this->db->datatype->convertResultRow($this->types, $row, false);
}
if (!empty($this->values)) {
$this->_assignBindColumns($row);
}
if ($fetchmode === MDB2_FETCHMODE_OBJECT) {
$object_class = $this->db->options['fetch_class'];
if ($object_class == 'stdClass') {
$row = (object) $row;
} else {
$row = &new $object_class($row);
}
}
++$this->rownum;
return $row;
}
// }}}
// {{{ _getColumnNames()
/**
* Retrieve the names of columns returned by the DBMS in a query result.
*
* @return mixed Array variable that holds the names of columns as keys
* or an MDB2 error on failure.
* Some DBMS may not return any columns when the result set
* does not contain any rows.
* @access private
*/
function _getColumnNames()
{
$columns = array();
$numcols = $this->numCols();
if (DOLIPEAR::isError($numcols)) {
return $numcols;
}
for ($column = 0; $column < $numcols; $column++) {
$column_name = @mssql_field_name($this->result, $column);
$columns[$column_name] = $column;
}
if ($this->db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
$columns = array_change_key_case($columns, $this->db->options['field_case']);
}
return $columns;
}
// }}}
// {{{ numCols()
/**
* Count the number of columns returned by the DBMS in a query result.
*
* @return mixed integer value with the number of columns, a MDB2 error
* on failure
* @access public
*/
function numCols()
{
$cols = @mssql_num_fields($this->result);
if (is_null($cols)) {
if ($this->result === false) {
return $this->db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null,
'resultset has already been freed', __FUNCTION__);
} elseif (is_null($this->result)) {
return count($this->types);
}
return $this->db->raiseError(null, null, null,
'Could not get column count', __FUNCTION__);
}
return $cols;
}
// }}}
// {{{ nextResult()
/**
* Move the internal result pointer to the next available result
*
* @return true on success, false if there is no more result set or an error object on failure
* @access public
*/
function nextResult()
{
if ($this->result === false) {
return $this->db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null,
'resultset has already been freed', __FUNCTION__);
} elseif (is_null($this->result)) {
return false;
}
return @mssql_next_result($this->result);
}
// }}}
// {{{ free()
/**
* Free the internal resources associated with $result.
*
* @return boolean true on success, false if $result is invalid
* @access public
*/
function free()
{
if (is_resource($this->result) && $this->db->connection) {
$free = @mssql_free_result($this->result);
if ($free === false) {
return $this->db->raiseError(null, null, null,
'Could not free result', __FUNCTION__);
}
}
$this->result = false;
return MDB2_OK;
}
}
/**
* MDB2 MSSQL Server buffered result driver
*
* @package MDB2
* @category Database
* @author Frank M. Kromann <frank@kromann.info>
*/
class MDB2_BufferedResult_mssql extends MDB2_Result_mssql
{
// }}}
// {{{ seek()
/**
* Seek to a specific row in a result set
*
* @param int $rownum number of the row where the data can be found
* @return mixed MDB2_OK on success, a MDB2 error on failure
* @access public
*/
function seek($rownum = 0)
{
if ($this->rownum != ($rownum - 1) && !@mssql_data_seek($this->result, $rownum)) {
if ($this->result === false) {
return $this->db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null,
'resultset has already been freed', __FUNCTION__);
} elseif (is_null($this->result)) {
return MDB2_OK;
}
return $this->db->raiseError(MDB2_ERROR_INVALID, null, null,
'tried to seek to an invalid row number ('.$rownum.')', __FUNCTION__);
}
$this->rownum = $rownum - 1;
return MDB2_OK;
}
// {{{ valid()
/**
* Check if the end of the result set has been reached
*
* @return mixed true or false on sucess, a MDB2 error on failure
* @access public
*/
function valid()
{
$numrows = $this->numRows();
if (DOLIPEAR::isError($numrows)) {
return $numrows;
}
return $this->rownum < ($numrows - 1);
}
// }}}
// {{{ numRows()
/**
* Returns the number of rows in a result object
*
* @return mixed MDB2 Error Object or the number of rows
* @access public
*/
function numRows()
{
$rows = @mssql_num_rows($this->result);
if (is_null($rows)) {
if ($this->result === false) {
return $this->db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null,
'resultset has already been freed', __FUNCTION__);
} elseif (is_null($this->result)) {
return 0;
}
return $this->db->raiseError(null, null, null,
'Could not get row count', __FUNCTION__);
}
if ($this->limit) {
$rows -= $this->limit;
if ($rows < 0) {
$rows = 0;
}
}
return $rows;
}
}
// }}}
// {{{ MDB2_Statement_mssql
/**
* MDB2 MSSQL Server statement driver
*
* @package MDB2
* @category Database
* @author Frank M. Kromann <frank@kromann.info>
*/
class MDB2_Statement_mssql extends MDB2_Statement_Common
{
}
// }}}
?>

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

View File

@ -1,714 +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$
/**
* @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 (DOLIPEAR::isError($query)) {
return $query;
}
$db =& $this->getDBInstance();
if (DOLIPEAR::isError($db)) {
return $db;
}
return $db->prepare($query, $types, $result_types);
}
// }}}
// {{{ 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 (DOLIPEAR::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 (DOLIPEAR::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 (DOLIPEAR::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 ($where !== false && !is_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 (DOLIPEAR::isError($db)) {
return $db;
}
$result = $db->setLimit($limit, $offset);
if (DOLIPEAR::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 (DOLIPEAR::isError($db)) {
return $db;
}
settype($params, 'array');
if (empty($params)) {
return $db->exec($query);
}
$stmt = $db->prepare($query, $param_types, MDB2_PREPARE_MANIP);
if (DOLIPEAR::isError($stmt)) {
return $stmt;
}
$result = $stmt->execute($params);
if (DOLIPEAR::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 (DOLIPEAR::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 (DOLIPEAR::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 (DOLIPEAR::isError($db)) {
return $db;
}
settype($params, 'array');
if (empty($params)) {
return $db->queryRow($query, $types, $fetchmode);
}
$stmt = $db->prepare($query, $param_types, $types);
if (DOLIPEAR::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 (DOLIPEAR::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 (DOLIPEAR::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 (DOLIPEAR::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 (DOLIPEAR::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 (DOLIPEAR::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 (DOLIPEAR::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 (DOLIPEAR::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 (DOLIPEAR::isError($db)) {
return $db;
}
if ($db->supports('auto_increment') !== true) {
$seq = $table.(empty($field) ? '' : '_'.$field);
$id = $db->nextID($seq, $ondemand);
if (!$quote || DOLIPEAR::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 (DOLIPEAR::isError($db)) {
return $db;
}
if ($db->supports('auto_increment') !== true) {
return $id;
}
return $db->lastInsertID($table, $field);
}
// }}}
}
?>

View File

@ -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$
/**
* 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 (is_null($this->row)) {
$row = $this->result->fetchRow($this->fetchmode);
if (DOLIPEAR::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);
}
// }}}
}
?>

View File

@ -1,265 +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$
/**
* @package MDB2
* @category Database
* @author Lukas Smith <smith@pooteeweet.org>
*/
//require_once 'MDB2.php';
require_once PEAR_PATH."/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;
}
?>

View File

@ -1,969 +0,0 @@
<?php
//
// +----------------------------------------------------------------------+
// | PEAR, the PHP Extension and Application Repository |
// +----------------------------------------------------------------------+
// | Copyright (c) 1997-2003 The PHP Group |
// +----------------------------------------------------------------------+
// | This source file is subject to version 2.0 of the PHP license, |
// | that is bundled with this package in the file LICENSE, and is |
// | available through the world-wide-web at the following url: |
// | http://www.php.net/license/3_0.txt. |
// | If you did not receive a copy of the PHP license and are unable to |
// | obtain it through the world-wide-web, please send a note to |
// | license@php.net so we can mail you a copy immediately. |
// +----------------------------------------------------------------------+
// | Authors: Sterling Hughes <sterling@php.net> |
// | Stig Bakken <ssb@php.net> |
// | Tomas V.V.Cox <cox@idecnet.com> |
// +----------------------------------------------------------------------+
//
// $Id$
//
define('DOLIPEAR_ERROR_RETURN', 1);
define('DOLIPEAR_ERROR_PRINT', 2);
define('DOLIPEAR_ERROR_TRIGGER', 4);
define('DOLIPEAR_ERROR_DIE', 8);
define('DOLIPEAR_ERROR_CALLBACK', 16);
define('DOLIPEAR_ERROR_EXCEPTION', 32);
define('DOLIPEAR_ZE2', (function_exists('version_compare') &&
version_compare(zend_version(), "2-dev", "ge")));
if (substr(PHP_OS, 0, 3) == 'WIN') {
define('OS_WINDOWS', true);
define('OS_UNIX', false);
define('DOLIPEAR_OS', 'Windows');
} else {
define('OS_WINDOWS', false);
define('OS_UNIX', true);
define('DOLIPEAR_OS', 'Unix'); // blatant assumption
}
$GLOBALS['_DOLIPEAR_default_error_mode'] = DOLIPEAR_ERROR_RETURN;
$GLOBALS['_DOLIPEAR_default_error_options'] = E_USER_NOTICE;
$GLOBALS['_DOLIPEAR_destructor_object_list'] = array();
$GLOBALS['_DOLIPEAR_shutdown_funcs'] = array();
$GLOBALS['_DOLIPEAR_error_handler_stack'] = array();
// Fix LDR Pour compatibilité tout PHP
//ini_set('track_errors', true);
/**
* Base class for other DOLIPEAR classes. Provides rudimentary
* emulation of destructors.
*
* If you want a destructor in your class, inherit DOLIPEAR and make a
* destructor method called _yourclassname (same name as the
* constructor, but with a "_" prefix). Also, in your constructor you
* have to call the DOLIPEAR constructor: $this->DOLIPEAR();.
* The destructor method will be called without parameters. Note that
* at in some SAPI implementations (such as Apache), any output during
* the request shutdown (in which destructors are called) seems to be
* discarded. If you need to get any debug information from your
* destructor, use error_log(), syslog() or something similar.
*
* IMPORTANT! To use the emulated destructors you need to create the
* objects by reference: $obj =& new DOLIPEAR_child;
*
* @since PHP 4.0.2
* @author Stig Bakken <ssb@php.net>
* @see http://pear.php.net/manual/
*/
class DOLIPEAR
{
// {{{ properties
/**
* Whether to enable internal debug messages.
*
* @var bool
* @access private
*/
var $_debug = false;
/**
* Default error mode for this object.
*
* @var int
* @access private
*/
var $_default_error_mode = null;
/**
* Default error options used for this object when error mode
* is DOLIPEAR_ERROR_TRIGGER.
*
* @var int
* @access private
*/
var $_default_error_options = null;
/**
* Default error handler (callback) for this object, if error mode is
* DOLIPEAR_ERROR_CALLBACK.
*
* @var string
* @access private
*/
var $_default_error_handler = '';
/**
* Which class to use for error objects.
*
* @var string
* @access private
*/
var $_error_class = 'DOLIPEAR_Error';
/**
* An array of expected errors.
*
* @var array
* @access private
*/
var $_expected_errors = array();
// }}}
// {{{ constructor
/**
* Constructor. Registers this object in
* $_DOLIPEAR_destructor_object_list for destructor emulation if a
* destructor object exists.
*
* @param string $error_class (optional) which class to use for
* error objects, defaults to DOLIPEAR_Error.
* @access public
* @return void
*/
function DOLIPEAR($error_class = null)
{
$classname = get_class($this);
if ($this->_debug) {
print "DOLIPEAR constructor called, class=$classname\n";
}
if ($error_class !== null) {
$this->_error_class = $error_class;
}
while ($classname) {
$destructor = "_$classname";
if (method_exists($this, $destructor)) {
global $_DOLIPEAR_destructor_object_list;
$_DOLIPEAR_destructor_object_list[] = &$this;
break;
} else {
$classname = get_parent_class($classname);
}
}
}
// }}}
// {{{ destructor
/**
* Destructor (the emulated type of...). Does nothing right now,
* but is included for forward compatibility, so subclass
* destructors should always call it.
*
* See the note in the class desciption about output from
* destructors.
*
* @access public
* @return void
*/
function _DOLIPEAR() {
if ($this->_debug) {
printf("DOLIPEAR destructor called, class=%s\n", get_class($this));
}
}
// }}}
// {{{ getStaticProperty()
/**
* If you have a class that's mostly/entirely static, and you need static
* properties, you can use this method to simulate them. Eg. in your method(s)
* do this: $myVar = &DOLIPEAR::getStaticProperty('myVar');
* You MUST use a reference, or they will not persist!
*
* @access public
* @param string $class The calling classname, to prevent clashes
* @param string $var The variable to retrieve.
* @return mixed A reference to the variable. If not set it will be
* auto initialised to NULL.
*/
function &getStaticProperty($class, $var)
{
static $properties;
return $properties[$class][$var];
}
// }}}
// {{{ registerShutdownFunc()
/**
* Use this function to register a shutdown method for static
* classes.
*
* @access public
* @param mixed $func The function name (or array of class/method) to call
* @param mixed $args The arguments to pass to the function
* @return void
*/
function registerShutdownFunc($func, $args = array())
{
$GLOBALS['_DOLIPEAR_shutdown_funcs'][] = array($func, $args);
}
// }}}
// {{{ isError()
/**
* Tell whether a value is a DOLIPEAR error.
*
* @param mixed $data the value to test
* @param int $code if $data is an error object, return true
* only if $code is a string and
* $obj->getMessage() == $code or
* $code is an integer and $obj->getCode() == $code
* @access public
* @return bool true if parameter is an error
*/
function isError($data, $code = null)
{
if (is_object($data) && (get_class($data) == 'pear_error' ||
is_subclass_of($data, 'pear_error'))) {
if (is_null($code)) {
return true;
} elseif (is_string($code)) {
return $data->getMessage() == $code;
} else {
return $data->getCode() == $code;
}
}
return false;
}
// }}}
// {{{ setErrorHandling()
/**
* Sets how errors generated by this object should be handled.
* Can be invoked both in objects and statically. If called
* statically, setErrorHandling sets the default behaviour for all
* DOLIPEAR objects. If called in an object, setErrorHandling sets
* the default behaviour for that object.
*
* @param int $mode
* One of DOLIPEAR_ERROR_RETURN, DOLIPEAR_ERROR_PRINT,
* DOLIPEAR_ERROR_TRIGGER, DOLIPEAR_ERROR_DIE,
* DOLIPEAR_ERROR_CALLBACK or DOLIPEAR_ERROR_EXCEPTION.
*
* @param mixed $options
* When $mode is DOLIPEAR_ERROR_TRIGGER, this is the error level (one
* of E_USER_NOTICE, E_USER_WARNING or E_USER_ERROR).
*
* When $mode is DOLIPEAR_ERROR_CALLBACK, this parameter is expected
* to be the callback function or method. A callback
* function is a string with the name of the function, a
* callback method is an array of two elements: the element
* at index 0 is the object, and the element at index 1 is
* the name of the method to call in the object.
*
* When $mode is DOLIPEAR_ERROR_PRINT or DOLIPEAR_ERROR_DIE, this is
* a printf format string used when printing the error
* message.
*
* @access public
* @return void
* @see DOLIPEAR_ERROR_RETURN
* @see DOLIPEAR_ERROR_PRINT
* @see DOLIPEAR_ERROR_TRIGGER
* @see DOLIPEAR_ERROR_DIE
* @see DOLIPEAR_ERROR_CALLBACK
* @see DOLIPEAR_ERROR_EXCEPTION
*
* @since PHP 4.0.5
*/
function setErrorHandling($mode = null, $options = null)
{
if (isset($this)) {
$setmode = &$this->_default_error_mode;
$setoptions = &$this->_default_error_options;
} else {
$setmode = &$GLOBALS['_DOLIPEAR_default_error_mode'];
$setoptions = &$GLOBALS['_DOLIPEAR_default_error_options'];
}
switch ($mode) {
case DOLIPEAR_ERROR_RETURN:
case DOLIPEAR_ERROR_PRINT:
case DOLIPEAR_ERROR_TRIGGER:
case DOLIPEAR_ERROR_DIE:
case DOLIPEAR_ERROR_EXCEPTION:
case null:
$setmode = $mode;
$setoptions = $options;
break;
case DOLIPEAR_ERROR_CALLBACK:
$setmode = $mode;
if ((is_string($options) && function_exists($options)) ||
(is_array($options) && method_exists(@$options[0], @$options[1])))
{
$setoptions = $options;
} else {
trigger_error("invalid error callback", E_USER_WARNING);
}
break;
default:
trigger_error("invalid error mode", E_USER_WARNING);
break;
}
}
// }}}
// {{{ expectError()
/**
* This method is used to tell which errors you expect to get.
* Expected errors are always returned with error mode
* DOLIPEAR_ERROR_RETURN. Expected error codes are stored in a stack,
* and this method pushes a new element onto it. The list of
* expected errors are in effect until they are popped off the
* stack with the popExpect() method.
*
* Note that this method can not be called statically
*
* @param mixed $code a single error code or an array of error codes to expect
*
* @return int the new depth of the "expected errors" stack
* @access public
*/
function expectError($code = '*')
{
if (is_array($code)) {
array_push($this->_expected_errors, $code);
} else {
array_push($this->_expected_errors, array($code));
}
return sizeof($this->_expected_errors);
}
// }}}
// {{{ popExpect()
/**
* This method pops one element off the expected error codes
* stack.
*
* @return array the list of error codes that were popped
*/
function popExpect()
{
return array_pop($this->_expected_errors);
}
// }}}
// {{{ _checkDelExpect()
/**
* This method checks unsets an error code if available
*
* @param mixed error code
* @return bool true if the error code was unset, false otherwise
* @access private
* @since PHP 4.3.0
*/
function _checkDelExpect($error_code)
{
$deleted = false;
foreach ($this->_expected_errors AS $key => $error_array) {
if (in_array($error_code, $error_array)) {
unset($this->_expected_errors[$key][array_search($error_code, $error_array)]);
$deleted = true;
}
// clean up empty arrays
if (0 == count($this->_expected_errors[$key])) {
unset($this->_expected_errors[$key]);
}
}
return $deleted;
}
// }}}
// {{{ delExpect()
/**
* This method deletes all occurences of the specified element from
* the expected error codes stack.
*
* @param mixed $error_code error code that should be deleted
* @return mixed list of error codes that were deleted or error
* @access public
* @since PHP 4.3.0
*/
function delExpect($error_code)
{
$deleted = false;
if ((is_array($error_code) && (0 != count($error_code)))) {
// $error_code is a non-empty array here;
// we walk through it trying to unset all
// values
foreach($error_code AS $key => $error) {
if ($this->_checkDelExpect($error)) {
$deleted = true;
} else {
$deleted = false;
}
}
return $deleted ? true : DOLIPEAR::raiseError("The expected error you submitted does not exist"); // IMPROVE ME
} elseif (!empty($error_code)) {
// $error_code comes alone, trying to unset it
if ($this->_checkDelExpect($error_code)) {
return true;
} else {
return DOLIPEAR::raiseError("The expected error you submitted does not exist"); // IMPROVE ME
}
} else {
// $error_code is empty
return DOLIPEAR::raiseError("The expected error you submitted is empty"); // IMPROVE ME
}
}
// }}}
// {{{ raiseError()
/**
* This method is a wrapper that returns an instance of the
* configured error class with this object's default error
* handling applied. If the $mode and $options parameters are not
* specified, the object's defaults are used.
*
* @param mixed $message a text error message or a DOLIPEAR error object
*
* @param int $code a numeric error code (it is up to your class
* to define these if you want to use codes)
*
* @param int $mode One of DOLIPEAR_ERROR_RETURN, DOLIPEAR_ERROR_PRINT,
* DOLIPEAR_ERROR_TRIGGER, DOLIPEAR_ERROR_DIE,
* DOLIPEAR_ERROR_CALLBACK, DOLIPEAR_ERROR_EXCEPTION.
*
* @param mixed $options If $mode is DOLIPEAR_ERROR_TRIGGER, this parameter
* specifies the PHP-internal error level (one of
* E_USER_NOTICE, E_USER_WARNING or E_USER_ERROR).
* If $mode is DOLIPEAR_ERROR_CALLBACK, this
* parameter specifies the callback function or
* method. In other error modes this parameter
* is ignored.
*
* @param string $userinfo If you need to pass along for example debug
* information, this parameter is meant for that.
*
* @param string $error_class The returned error object will be
* instantiated from this class, if specified.
*
* @param bool $skipmsg If true, raiseError will only pass error codes,
* the error message parameter will be dropped.
*
* @access public
* @return object a DOLIPEAR error object
* @see DOLIPEAR::setErrorHandling
* @since PHP 4.0.5
*/
function raiseError($message = null,
$code = null,
$mode = null,
$options = null,
$userinfo = null,
$error_class = null,
$skipmsg = false)
{
// The error is yet a DOLIPEAR error object
if (is_object($message)) {
$code = $message->getCode();
$userinfo = $message->getUserInfo();
$error_class = $message->getType();
$message = $message->getMessage();
}
if (isset($this) && isset($this->_expected_errors) && sizeof($this->_expected_errors) > 0 && sizeof($exp = end($this->_expected_errors))) {
if ($exp[0] == "*" ||
(is_int(reset($exp)) && in_array($code, $exp)) ||
(is_string(reset($exp)) && in_array($message, $exp))) {
$mode = DOLIPEAR_ERROR_RETURN;
}
}
// No mode given, try global ones
if ($mode === null) {
// Class error handler
if (isset($this) && isset($this->_default_error_mode)) {
$mode = $this->_default_error_mode;
$options = $this->_default_error_options;
// Global error handler
} elseif (isset($GLOBALS['_DOLIPEAR_default_error_mode'])) {
$mode = $GLOBALS['_DOLIPEAR_default_error_mode'];
$options = $GLOBALS['_DOLIPEAR_default_error_options'];
}
}
if ($error_class !== null) {
$ec = $error_class;
} elseif (isset($this) && isset($this->_error_class)) {
$ec = $this->_error_class;
} else {
$ec = 'DOLIPEAR_Error';
}
if ($skipmsg) {
return new $ec($code, $mode, $options, $userinfo);
} else {
return new $ec($message, $code, $mode, $options, $userinfo);
}
}
// }}}
// {{{ throwError()
/**
* Simpler form of raiseError with fewer options. In most cases
* message, code and userinfo are enough.
*
* @param string $message
*
*/
function &throwError($message = null,
$code = null,
$userinfo = null)
{
if (isset($this) && is_subclass_of($this, 'DOLIPEAR_Error')) {
return $this->raiseError($message, $code, null, null, $userinfo);
} else {
return DOLIPEAR::raiseError($message, $code, null, null, $userinfo);
}
}
// }}}
// {{{ pushErrorHandling()
/**
* Push a new error handler on top of the error handler options stack. With this
* you can easily override the actual error handler for some code and restore
* it later with popErrorHandling.
*
* @param mixed $mode (same as setErrorHandling)
* @param mixed $options (same as setErrorHandling)
*
* @return bool Always true
*
* @see DOLIPEAR::setErrorHandling
*/
function pushErrorHandling($mode, $options = null)
{
$stack = &$GLOBALS['_DOLIPEAR_error_handler_stack'];
if (isset($this)) {
$def_mode = &$this->_default_error_mode;
$def_options = &$this->_default_error_options;
} else {
$def_mode = &$GLOBALS['_DOLIPEAR_default_error_mode'];
$def_options = &$GLOBALS['_DOLIPEAR_default_error_options'];
}
$stack[] = array($def_mode, $def_options);
if (isset($this)) {
$this->setErrorHandling($mode, $options);
} else {
DOLIPEAR::setErrorHandling($mode, $options);
}
$stack[] = array($mode, $options);
return true;
}
// }}}
// {{{ popErrorHandling()
/**
* Pop the last error handler used
*
* @return bool Always true
*
* @see DOLIPEAR::pushErrorHandling
*/
function popErrorHandling()
{
$stack = &$GLOBALS['_DOLIPEAR_error_handler_stack'];
array_pop($stack);
list($mode, $options) = $stack[sizeof($stack) - 1];
array_pop($stack);
if (isset($this)) {
$this->setErrorHandling($mode, $options);
} else {
DOLIPEAR::setErrorHandling($mode, $options);
}
return true;
}
// }}}
// {{{ loadExtension()
/**
* OS independant PHP extension load. Remember to take care
* on the correct extension name for case sensitive OSes.
*
* @param string $ext The extension name
* @return bool Success or not on the dl() call
*/
function loadExtension($ext)
{
if (!extension_loaded($ext)) {
// if either returns true dl() will produce a FATAL error, stop that
if ((ini_get('enable_dl') != 1) || (ini_get('safe_mode') == 1)) {
return false;
}
if (OS_WINDOWS) {
$suffix = '.dll';
} elseif (PHP_OS == 'HP-UX') {
$suffix = '.sl';
} elseif (PHP_OS == 'AIX') {
$suffix = '.a';
} elseif (PHP_OS == 'OSX') {
$suffix = '.bundle';
} else {
$suffix = '.so';
}
return @dl('php_'.$ext.$suffix) || @dl($ext.$suffix);
}
return true;
}
// }}}
}
// {{{ _DOLIPEAR_call_destructors()
function _DOLIPEAR_call_destructors()
{
global $_DOLIPEAR_destructor_object_list;
if (is_array($_DOLIPEAR_destructor_object_list) &&
sizeof($_DOLIPEAR_destructor_object_list))
{
reset($_DOLIPEAR_destructor_object_list);
while (list($k, $objref) = each($_DOLIPEAR_destructor_object_list)) {
$classname = get_class($objref);
while ($classname) {
$destructor = "_$classname";
if (method_exists($objref, $destructor)) {
$objref->$destructor();
break;
} else {
$classname = get_parent_class($classname);
}
}
}
// Empty the object list to ensure that destructors are
// not called more than once.
$_DOLIPEAR_destructor_object_list = array();
}
// Now call the shutdown functions
if (is_array($GLOBALS['_DOLIPEAR_shutdown_funcs']) AND !empty($GLOBALS['_DOLIPEAR_shutdown_funcs'])) {
foreach ($GLOBALS['_DOLIPEAR_shutdown_funcs'] as $value) {
call_user_func_array($value[0], $value[1]);
}
}
}
// }}}
class DOLIPEAR_Error
{
// {{{ properties
var $error_message_prefix = '';
var $mode = DOLIPEAR_ERROR_RETURN;
var $level = E_USER_NOTICE;
var $code = -1;
var $message = '';
var $userinfo = '';
var $backtrace = null;
// }}}
// {{{ constructor
/**
* DOLIPEAR_Error constructor
*
* @param string $message message
*
* @param int $code (optional) error code
*
* @param int $mode (optional) error mode, one of: DOLIPEAR_ERROR_RETURN,
* DOLIPEAR_ERROR_PRINT, DOLIPEAR_ERROR_DIE, DOLIPEAR_ERROR_TRIGGER,
* DOLIPEAR_ERROR_CALLBACK or DOLIPEAR_ERROR_EXCEPTION
*
* @param mixed $options (optional) error level, _OR_ in the case of
* DOLIPEAR_ERROR_CALLBACK, the callback function or object/method
* tuple.
*
* @param string $userinfo (optional) additional user/debug info
*
* @access public
*
*/
function DOLIPEAR_Error($message = 'unknown error', $code = null,
$mode = null, $options = null, $userinfo = null)
{
if ($mode === null) {
$mode = DOLIPEAR_ERROR_RETURN;
}
$this->message = $message;
$this->code = $code;
$this->mode = $mode;
$this->userinfo = $userinfo;
if (function_exists("debug_backtrace")) {
$this->backtrace = debug_backtrace();
}
if ($mode & DOLIPEAR_ERROR_CALLBACK) {
$this->level = E_USER_NOTICE;
$this->callback = $options;
} else {
if ($options === null) {
$options = E_USER_NOTICE;
}
$this->level = $options;
$this->callback = null;
}
if ($this->mode & DOLIPEAR_ERROR_PRINT) {
if (is_null($options) || is_int($options)) {
$format = "%s";
} else {
$format = $options;
}
printf($format, $this->getMessage());
}
if ($this->mode & DOLIPEAR_ERROR_TRIGGER) {
trigger_error($this->getMessage(), $this->level);
}
if ($this->mode & DOLIPEAR_ERROR_DIE) {
$msg = $this->getMessage();
if (is_null($options) || is_int($options)) {
$format = "%s";
if (substr($msg, -1) != "\n") {
$msg .= "\n";
}
} else {
$format = $options;
}
die(sprintf($format, $msg));
}
if ($this->mode & DOLIPEAR_ERROR_CALLBACK) {
if (is_string($this->callback) && strlen($this->callback)) {
call_user_func($this->callback, $this);
} elseif (is_array($this->callback) &&
sizeof($this->callback) == 2 &&
is_object($this->callback[0]) &&
is_string($this->callback[1]) &&
strlen($this->callback[1])) {
call_user_func($this->callback, $this);
}
}
if (DOLIPEAR_ZE2 && $this->mode & DOLIPEAR_ERROR_EXCEPTION) {
eval('throw $this;');
}
}
// }}}
// {{{ getMode()
/**
* Get the error mode from an error object.
*
* @return int error mode
* @access public
*/
function getMode() {
return $this->mode;
}
// }}}
// {{{ getCallback()
/**
* Get the callback function/method from an error object.
*
* @return mixed callback function or object/method array
* @access public
*/
function getCallback() {
return $this->callback;
}
// }}}
// {{{ getMessage()
/**
* Get the error message from an error object.
*
* @return string full error message
* @access public
*/
function getMessage()
{
return ($this->error_message_prefix . $this->message);
}
// }}}
// {{{ getCode()
/**
* Get error code from an error object
*
* @return int error code
* @access public
*/
function getCode()
{
return $this->code;
}
// }}}
// {{{ getType()
/**
* Get the name of this error/exception.
*
* @return string error/exception name (type)
* @access public
*/
function getType()
{
return get_class($this);
}
// }}}
// {{{ getUserInfo()
/**
* Get additional user-supplied information.
*
* @return string user-supplied information
* @access public
*/
function getUserInfo()
{
return $this->userinfo;
}
// }}}
// {{{ getDebugInfo()
/**
* Get additional debug information supplied by the application.
*
* @return string debug information
* @access public
*/
function getDebugInfo()
{
return $this->getUserInfo();
}
// }}}
// {{{ getBacktrace()
/**
* Get the call backtrace from where the error was generated.
* Supported with PHP 4.3.0 or newer.
*
* @param int $frame (optional) what frame to fetch
* @return array Backtrace, or NULL if not available.
* @access public
*/
function getBacktrace($frame = null)
{
if ($frame === null) {
return $this->backtrace;
}
return $this->backtrace[$frame];
}
// }}}
// {{{ addUserInfo()
function addUserInfo($info)
{
if (empty($this->userinfo)) {
$this->userinfo = $info;
} else {
$this->userinfo .= " ** $info";
}
}
// }}}
// {{{ toString()
/**
* Make a string representation of this object.
*
* @return string a string with an object summary
* @access public
*/
function toString() {
$modes = array();
$levels = array(E_USER_NOTICE => 'notice',
E_USER_WARNING => 'warning',
E_USER_ERROR => 'error');
if ($this->mode & DOLIPEAR_ERROR_CALLBACK) {
if (is_array($this->callback)) {
$callback = get_class($this->callback[0]) . '::' .
$this->callback[1];
} else {
$callback = $this->callback;
}
return sprintf('[%s: message="%s" code=%d mode=callback '.
'callback=%s prefix="%s" info="%s"]',
get_class($this), $this->message, $this->code,
$callback, $this->error_message_prefix,
$this->userinfo);
}
if ($this->mode & DOLIPEAR_ERROR_PRINT) {
$modes[] = 'print';
}
if ($this->mode & DOLIPEAR_ERROR_TRIGGER) {
$modes[] = 'trigger';
}
if ($this->mode & DOLIPEAR_ERROR_DIE) {
$modes[] = 'die';
}
if ($this->mode & DOLIPEAR_ERROR_RETURN) {
$modes[] = 'return';
}
return sprintf('[%s: message="%s" code=%d mode=%s level=%s '.
'prefix="%s" info="%s"]',
get_class($this), $this->message, $this->code,
implode("|", $modes), $levels[$this->level],
$this->error_message_prefix,
$this->userinfo);
}
// }}}
}
register_shutdown_function("_DOLIPEAR_call_destructors");
/*
* Local Variables:
* mode: php
* tab-width: 4
* c-basic-offset: 4
* End:
*/
?>